Make it more intuitive

Updates to the bed make it a lot more intuitive.

The signal lights for the alarm are now built into the switches that turn them off.
The lights on the buttons flash with the tone until they are pressed, then they go off to signify that that button is no longer active. A user's attention goes to the flashing light - it is sending a signal to the user saying "look at me". When they stop flashing it sends a "nothing to see here" message.

The new flowchart looks like this...

To update the code to reflect this was surprisingly easy, but it took me about 6 hours of research and trial and error to realise how simple the solution was.

Here is the video of it working...



Here is the code...
// Bed Code
// two lights flash and buzzer beeps
// two buttons to press to stop the alarm
// light signals both alarm and button state
#include <Servo.h>
#include <Bounce2.h>

class Flasher
{
    // Class Member Variables
    // These are initialized at startup
    int ledPin;      // the number of the LED pin
    long OnTime;     // milliseconds of on-time
    long OffTime;    // milliseconds of off-time
    // These maintain the current state
    int ledState;                 // ledState used to set the LED
    unsigned long previousMillis;   // will store last time LED was updated
    // Constructor - creates a Flasher
    // and initializes the member variables and state
  public:
    Flasher(int pin, long on, long off)
    {
      ledPin = pin;
      pinMode(ledPin, OUTPUT);
      OnTime = on;
      OffTime = off;
      ledState = LOW;
      previousMillis = 0;
    }
    void Update()
    {
      // check to see if it's time to change the state of the LED
      unsigned long currentMillis = millis();
      if ((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
      {
        ledState = LOW;  // Turn it off
        previousMillis = currentMillis;  // Remember the time
        digitalWrite(ledPin, ledState);  // Update the actual LED
      }
      else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
      {
        ledState = HIGH;  // turn it on
        previousMillis = currentMillis;   // Remember the time
        digitalWrite(ledPin, ledState);   // Update the actual LED
      }
    }
};
class Sweeper
{
    Servo servo;               //the servo
    int pos;                  // current servo position
    int increment;            //increment to move for each interval
    int updateInterval;       // interval between updates
    unsigned long lastUpdate;  //last update of position
  public:
    Sweeper(int interval)
    {
      updateInterval = interval;
      increment = 1;
    }
    void Attach(int pin)
    {
      servo.attach(pin);
    }
    void Reset()
    {
      servo.write (0); // sets the servo to position zero
      pos = 0;
    }
    void Detach()
    {
      servo.detach();
    }
    void Update()
    {
      if ((millis() - lastUpdate) > updateInterval) // time to update
      {
        lastUpdate = millis();
        pos += increment;
        servo.write(pos);
        Serial.println(pos);
        if (pos >= 140) // sets the distance of the servo sweep, then end of sweep
        {
          servo.write(0); // sets the servo back to zero
          while (1) {     // stops all functions
          }
        }
      }
    }
};

// Add all of the flasher and sweeper class instances here (keep going until you run out of pins)
Flasher LED1(6, 200, 800);     // pin, on time, off time
Flasher LED2(7, 200, 800);     // pin, on time, off time
Flasher BUZZER(11, 100, 900);  // pin, on time, off time
Sweeper sweeper1 (45);        // controls the speed of the servo (lower = faster)
Bounce debouncerA = Bounce(); // Instantiate a Bounce object - reads a button push
Bounce debouncerB = Bounce(); // Instantiate a Bounce object
const int BUTTON_A = 8; // these are the button pins, constants won't change
const int BUTTON_B = 9;
bool bedMoveA = false;
bool bedMoveB = false;

void setup()
{
  debouncerA.attach(BUTTON_A, INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncerA.interval(25); // Use a debounce interval of 25 milliseconds
  debouncerB.attach(BUTTON_B, INPUT_PULLUP); // Attach the debouncer to a pin with INPUT_PULLUP mode
  debouncerB.interval(25); // Use a debounce interval of 25 milliseconds
  Serial.begin(9600);
  sweeper1.Attach(3);     // attaches sweeper1 servo to pin 3
  sweeper1.Reset();
}
void loop()
{
  debouncerA.update(); // Update the Bounce instance
  debouncerB.update(); // Update the Bounce instance
  Serial.println(bedMoveA);
  Serial.print(bedMoveB);
  if (debouncerA.fell()) // press button A
  {
    bedMoveA = true;
    Serial.print("bedMove"); // remembers the button press
  }
  if (debouncerB.fell())    // press button B
  {
    bedMoveB = true;
    Serial.print("bedMove"); // remembers the button press
  }
  if (!bedMoveA && !bedMoveB) // if neither buttons are pressed, flash A & B and beep Buzzer
  {
    LED1.Update();
    LED2.Update();
    BUZZER.Update();
  }
  if (bedMoveA && !bedMoveB) // if only button A is pressed, don't update LED A
  {
    LED2.Update();
    BUZZER.Update();
  }
  if (!bedMoveA && bedMoveB) // if only button B is pressed, don't update LED B
  {
    LED1.Update();
    BUZZER.Update();
  }
  if (bedMoveA && bedMoveB) // if both buttons are pressed, move to the servo loop
  {
    sweeper1.Update();
  }
}

Now I have to make the time to make a flashy new model. 

Comments