Close

Programming sleep and animations

A project log for 900 MHz radio

Hope RF module + Atmega 328

adellelinadellelin 05/20/2021 at 16:410 Comments

Before getting into the details of the project, I wanted to share a handy snippet of code that Matt and I add to all our code out so that if we haven't worked on your board in a while, we can see what program has been uploaded last when connected to the serial monitor:

uploaded: '/Users/dev/wedding_badges_rfm69/Arduino/RadioHead69_TX_0425b/RadioHead69_TX_0425b.ino' on May 20 2021

 These lines of code are added to setup():

  // output last filename uploaded and date
  Serial.print("uploaded: '");
  Serial.print(__FILE__);
  Serial.print("' on ");
  Serial.println(__DATE__);

To program the sleep cycle,  we use the elapsed millis library and power down function from the Low power lab library

#include  //get library from:https://github.com/lowpowerlab/lowpower

// timers for animation cycles 
#include  elapsedMillis waitSleepElapsed; 
int waitSleepDuration = 3000;  

void loop(){ 
 if (awake == false) {
    LowPower.powerDown(SLEEP_2S, ADC_ON, BOD_OFF);
  }
}

void check_if_should_sleep(){
    if (waitSleepElapsed > waitSleepDuration) {
        awake = false;
        setAllOff();  
    } 
}

For the animation code. The first animation is a single pixel fade up and down in order. We create an array of integers that represent the pixel array and set all values to 0. When the receiver gets a message, it flips the value of the first pixel to 1:

void handleModeOnReceive(int receivedMessage){
  if (animationMode != receivedMessage){
    for (int i = 0; i < NUM_LEDS; i++) {
      setBrightness(i, 0);
      selected[i] = 0;
    }
    selected[0] = 1;
    animationMode = receivedMessage;
  }
}

Within the animation loop, we're checking to see if any of these values are equal to one, if they are, then that LED gets the animation sequence:

void animateFade() {
  float percentComplete = (((float)animationValue) / (float)animationDuration);
  // check each led
  for (int i = 0; i < NUM_LEDS; i++) {
    float fade = percentComplete; // fade up or down
    if (selected[i] == 0) {
      fade = 0.0;
    }
    // set the one on chase to fade up
    setBrightness(i, fade * brightness); //*random(1,3)); <- gives a sparkle
  }
}

// fade is float scaled between 0.0 and brightness
void setBrightness(int i, float fade) {
  SoftPWMSet(ledPins[i], fade);
}

There is another loop that flips the value of the next LED index in the array to 1 in order:

void animate_led_ordered() {  
  // at every loop, flip the value of the next index to one
  // and self to zero
  for (int i = NUM_LEDS - 1; i >= 0 ; i--) {
    if (selected[i] == 1) {
      selected[i] = 0;
      selected[i + 1] = 1;
      break;
    }
  }
}

Within the main loop, is where we handle the timers:

if (awake == true) {
    // double animation duration to allow fade up and down
    if (animationElapsed > 2 * animationDuration) {
      animate_led_ordered();
      // start animation timer for led index with value 1
      animationElapsed = 0;
    }
    // fade down
    else if (animationElapsed > animationDuration) {
      animationValue = 2 * animationDuration - animationElapsed;
    }
    else {
      // fade up
      animationValue = animationElapsed;
    }

This creates the animation in the video at the top of the log.

Discussions