Skip to content

Commit

Permalink
Added Arduino Code #13
Browse files Browse the repository at this point in the history
  • Loading branch information
ClemensElflein committed Nov 19, 2021
1 parent f54443a commit e0fe086
Show file tree
Hide file tree
Showing 32 changed files with 4,949 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Arduino/SelfomatController/AgreementState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "AgreementState.h"
#include "IdleState.h"

AgreementState AgreementState::INSTANCE;

bool AgreementState::processCommand(const uint8_t* buffer, size_t size) {
// Handle 'a' since we're already in agreement
if(size == 1 && buffer[0] == 'a') {
sendCommand('A');
return true;
}

// Process base commands.
if(BaseState::processCommand(buffer, size))
return true;

return false;
}

void AgreementState::animationStep(unsigned long dt) {
// Fade
if (shouldExit) {
if (b > 0.0) {
b -= min(b, 0.025);
} else {
exitAnimationDone = true;
}
} else {
if (b < 1.0) {
b += min(1-b, 0.01);
}
}


float angleOffset = timeInState()/300.0f;
float anglePerLed = (2.0 * PI) / ring.numPixels();
for(int j = 0; j < ring.numPixels(); j++) {
float angle = (float)j * anglePerLed + angleOffset;
float sin_x = sin(angle);
uint8_t brightness = sin_x*sin_x * 255.0f * b;
ring.setPixelColor(j, 0, brightness, 0);
}
ring.show();
}

BaseState* AgreementState::logicStep() {
if(!shouldExit && digitalRead(PIN_BUTTON) == LOW) {
shouldExit = true;
sendCommand('c');
}

if(shouldExit && exitAnimationDone) {
sendCommand('a');
return &IdleState::INSTANCE;
}
return this;
}

void AgreementState::enter() {
BaseState::enter();
b = 0;
frame = 0;
exitAnimationDone = shouldExit = false;
sendCommand('A');
}

void AgreementState::exit() {

}

bool AgreementState::needsHeartbeat() {
return !heartbeatDeactivated;
}
44 changes: 44 additions & 0 deletions Arduino/SelfomatController/AgreementState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef AGREEMENT_STATE_H
#define AGREEMENT_STATE_H

#include "State.h"
#include "globals.h"
#include "Arduino.h"

class AgreementState : public BaseState {
private:
uint8_t frame;
float b;
bool shouldExit;
bool exitAnimationDone;
public:
static AgreementState INSTANCE;
/**
* Handle a serial command.
* @param buffer: the command buffer
* @param size: buffer length
*
* @returns: true, if the command was handled
*/
virtual bool processCommand(const uint8_t* buffer, size_t size);
virtual void animationStep(unsigned long dt);

/**
* Do some polling logic
* @returns the pointer to the next state (can return itself)
*/
virtual BaseState* logicStep();
/**
* Called ONCE on state enter
*/
virtual void enter();

/**
* Called ONCE before state exits
*/
virtual void exit();

virtual bool needsHeartbeat();
};

#endif
68 changes: 68 additions & 0 deletions Arduino/SelfomatController/BootingState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include "BootingState.h"
#include "IdleState.h"

BootingState BootingState::INSTANCE;

bool BootingState::processCommand(const uint8_t* buffer, size_t size) {
bool parentHandled = BaseState::processCommand(buffer, size);
// If it was a heartbeat, we want to exit
if (size == 1 && buffer[0] == '.') {
shouldExit = true;
return true;
}
return parentHandled;
}

void BootingState::animationStep(unsigned long dt) {
// Fade
if (shouldExit) {
if (b > 0) {
b-=min(b,4);
} else {
exitAnimationDone = true;
}
} else {
if (b < 255) {
b+=min(4, 255-b);
}
}

// Animate
for (int i = 0; i < ring.numPixels(); i++) {
byte diff = (i - frame) % ring.numPixels();
byte color = (b / ring.numPixels() * diff);
ring.setPixelColor(i, 0, color, color >> 2);
}
ring.show();

// Skip to next frame
frame++;
}

BaseState* BootingState::logicStep() {
BaseState* parentStep = BaseState::logicStep();
if(parentStep)
return parentStep;

if(shouldExit && exitAnimationDone) {
return &IdleState::INSTANCE;
}

return this;
}

void BootingState::enter() {
frame = 0;
exitAnimationDone = shouldExit = false;
}

void BootingState::exit() {
// Booting done, we need a heartbeat. Assume we got it now
heartbeatDeactivated = false;
lastHeartbeat = millis();
}

bool BootingState::needsHeartbeat() {
// Booting so no heartbeat required
return false;
}
44 changes: 44 additions & 0 deletions Arduino/SelfomatController/BootingState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef BOOTING_STATE_H
#define BOOTING_STATE_H

#include "State.h"
#include "globals.h"
#include "Arduino.h"

class BootingState: public BaseState {
private:
uint32_t frame = 0;
int b = 0;
bool shouldExit;
bool exitAnimationDone;
public:
static BootingState INSTANCE;
/**
* Handle a serial command.
* @param buffer: the command buffer
* @param size: buffer length
*
* @returns: true, if the command was handled
*/
virtual bool processCommand(const uint8_t* buffer, size_t size);
virtual void animationStep(unsigned long dt);

/**
* Do some polling logic
* @returns the pointer to the next state (can return itself)
*/
virtual BaseState* logicStep();
/**
* Called ONCE on state enter
*/
virtual void enter();

/**
* Called ONCE before state exits
*/
virtual void exit();

virtual bool needsHeartbeat();
};

#endif
75 changes: 75 additions & 0 deletions Arduino/SelfomatController/BusyState.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "BusyState.h"
#include "IdleState.h"
#include "PrintingState.h"
#include "PinChangeInterrupt.h"

BusyState BusyState::INSTANCE;

bool BusyState::processCommand(const uint8_t* buffer, size_t size) {
if(BaseState::processCommand(buffer, size))
return true;

if(size == 1) {
switch(buffer[0]) {
case 'k':
exitIdle = true;
return true;
case 'p':
exitPrint = true;
return true;
default:
return false;
}
}
return false;
}

void BusyState::animationStep(unsigned long dt) {
// No animation here!
}

BaseState* BusyState::logicStep() {

if(flashTriggered) {
if(settings.flashDurationMicros < 0) {
delay(10);
} else {
while(micros() - flashStartMicros < settings.flashDurationMicros);
}
digitalWrite(PIN_FLASH_ON, LOW);
flashTriggered = false;
}

// timeout in busy state
if(timeInState() > 15000 || exitIdle) {
return &IdleState::INSTANCE;
}
if(exitPrint) {
return &PrintingState::INSTANCE;
}
return this;
}

void BusyState::enter() {
BaseState::enter();
flashTriggered = exitPrint = exitIdle = false;
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(PIN_FLASH_CAM_TRIGGER), triggerFlash, FALLING);
}

void BusyState::exit() {
// first, detach the interrupt!!
detachPinChangeInterrupt(digitalPinToPinChangeInterrupt(PIN_FLASH_CAM_TRIGGER));
// then turn off the light for safety
digitalWrite(PIN_FLASH_ON, LOW);
}

bool BusyState::needsHeartbeat() {
return !heartbeatDeactivated;
}


void BusyState::triggerFlash() {
PORTB |= 0b1000;
flashTriggered = true;
flashStartMicros = micros();
}
51 changes: 51 additions & 0 deletions Arduino/SelfomatController/BusyState.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef BUSY_STATE_H
#define BUSY_STATE_H

#include "State.h"
#include "globals.h"
#include "Arduino.h"

// Storage for flash ISR
static volatile unsigned long flashStartMicros;
static volatile bool flashTriggered;

class BusyState : public BaseState {
private:




bool exitPrint, exitIdle;
public:
static BusyState INSTANCE;

static void triggerFlash();
/**
* Handle a serial command.
* @param buffer: the command buffer
* @param size: buffer length
*
* @returns: true, if the command was handled
*/
virtual bool processCommand(const uint8_t* buffer, size_t size);
virtual void animationStep(unsigned long dt);

/**
* Do some polling logic
* @returns the pointer to the next state (can return itself)
*/
virtual BaseState* logicStep();
/**
* Called ONCE on state enter
*/
virtual void enter();

/**
* Called ONCE before state exits
*/
virtual void exit();

virtual bool needsHeartbeat();
};

#endif
Loading

0 comments on commit e0fe086

Please sign in to comment.