0

Itsybitsy 32u4 8Mhz ultra slow on wake up
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Sun Aug 25, 2019 6:55 am

Hi !

I've a strange issue, my Itsybitsy is sometimes (~20% of the time) really slow when he wake up from sleep.

It works, but really slowly, like it was running at 1Mhz.

Any idea what is wrong ?


The sleep function :
Code: Select all | TOGGLE FULL SIZE
void sleepNow() {  // here we put the arduino to sleep   

   power_timer0_disable();
   power_timer1_disable();
power_spi_disable();
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

   sleep_enable();          // enables the sleep bit in the mcucr register
                      // so sleep is possible. just a safety pin


   attachInterrupt(2, wakeUpNow, CHANGE); // use interrupt 1 (pin 2) and run function

   sleep_mode();            // here the device is actually put to sleep!!
                      // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP

   sleep_disable();         // first thing after waking from sleep:
                      // disable sleep...
   detachInterrupt(2);      // disables interrupt 1 on pin 2 so the
                      // wakeUpNow code will not be executed
                      // during normal running time.
}


The wake up function :
Code: Select all | TOGGLE FULL SIZE
void wakeUpNow() {
   power_timer0_enable();
   power_timer1_enable();
   power_spi_enable();
}


Thanks for support

Regards

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Sun Aug 25, 2019 12:22 pm

Hi !

Just discovered that it's not only a wake up issue but also a boot issue.

It also sometime start at ultra low speed for unknown reasons. :-(

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Tue Aug 27, 2019 2:44 pm

I've tried my code on a ProMicro 16Mhz -> Same behavior

So the issue is not linked to the ItsyBitsy.

I've doubled checked with the Chinese RF module, and I've to admit that it is also slower, not as much, but still slower.

If I press very quickly on the button after the wake up the speed is OK, it's only after a little time that the system is slow.

At the end I think there is something wrong with my wake up logic.

Here is the whole code, perhaps someone will find my mistake :

Code: Select all | TOGGLE FULL SIZE
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <ctype.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <Bounce2.h>
#include <LowPower.h>

#define BUTTON_PIN 0
#define LED_PIN 1
#define CE_PIN A4
#define CSN_PIN A5
#define LOW_POWER_MODE_PIN 8

#define BLINK_INTERVAL 1000 
#define SLEEP_DELAY 480000

//LED states
#define LED_OFF 0
#define LED_ON 1
#define LED_BLINK 2

//LED blink speed
#define LED_SLOW 1000

//LED Brightness
#define LED_MAX_BRIGHTNESS 255
#define LED_MED_BRIGHTNESS 150
#define LED_MIN_BRIGHTNESS 50

//**************************************************************************************

float version = 2.06;

//**************************************************************************************


//RF24
const uint8_t masterAddress[6] = "SRV00";
uint8_t thisButtonAddress[6];

const uint8_t DIPSwitchPins[] = { 7, 9, 10, 11 };

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

volatile int ledState = LOW;

volatile bool do_blinkLed = false;

volatile bool wakeUP = false;

//volatile bool turnedON = true;

long previousMillis = 0;

long lastActionMillis = 0;

Bounce debouncer = Bounce();

int RcvCnt = 0;

int buttonNumber = 0;

//Struct for LED
struct LED {
   byte state;
   int blinkSpeed;
   int blinkCount;
   int brightness;
   unsigned long lastStateChange;
};

//Struct for data to send
typedef struct {
   uint8_t rnd;
   uint8_t type;
   uint8_t msg;
}
A_t;

//Struct for data received
typedef struct {
   uint8_t rnd;
   uint8_t type;
   uint8_t msg;
}
B_t;

A_t Data_Sent;
B_t Data_Received;

struct LED led = { LED_BLINK, LED_FAST, 3, 0, 0 };

//****************************************

void setup() {

   Serial.begin(9600);

   pinMode(LED_PIN, OUTPUT); //Led pin

   pinMode(13, OUTPUT);// onboard LED
   digitalWrite(13, LOW);

   pinMode(LOW_POWER_MODE_PIN, INPUT_PULLUP); //Low power mode pin

   getButtonNr();

   delay(500);

   radio.begin();

   delay(500);// Give RF module some time to run.

   setupRF24();

   debouncer.attach(BUTTON_PIN, INPUT_PULLUP);
   debouncer.interval(5); // interval in ms

   // No power save if Button is pressed or if Jumper is present
   if (digitalRead(BUTTON_PIN) ? 1 : 0 || digitalRead(LOW_POWER_MODE_PIN) ? 0 : 1) {
      digitalWrite(13, HIGH);//turn ON on board led to indicate that we are well connected to USB
   }
   else {
      //save power
      ADCSRA = 0;
      power_adc_disable();
      power_twi_disable();
      power_usart0_disable();
      power_usart1_disable();
      power_timer2_disable();
      power_timer3_disable();
      // disable the USB
      USBCON |= _BV(FRZCLK);  //freeze USB clock
      PLLCSR &= ~_BV(PLLE);   // turn off USB PLL
      USBCON &= ~_BV(USBE);   // disable USB
      power_usb_disable();
   }
}

//****************************************

void loop() {

   if (wakeUP) {

      radio.powerUp();

      delay(500);

      pinMode(BUTTON_PIN, INPUT_PULLUP);

      led.state = LED_BLINK;
      led.blinkCount = 3;

      wakeUP = false;

      lastActionMillis = millis();

   }

   do {

      LED();

      debouncer.update();      // Update the Bounce instance

      // Wait for button being pressed
      if (debouncer.read() == HIGH) {
         if (millis() - lastActionMillis > 200) {
            if (led.state == LED_OFF || !LED_BLINK) {
               sendToMaster(buttonNumber);
            }
         }

         lastActionMillis = millis();
      }

      //Go to sleep if no actions for some times
      if (millis() - lastActionMillis > SLEEP_DELAY) {
         sleepNow();   //Time to go to  sleep to save some power, wake up when button pressed
      }

   } while (!radio.available());

   radio.read(&Data_Received, sizeof(Data_Received));

   int order = Data_Received.msg;

   switch (Data_Received.msg) {

   case 0://test

      break;

   case 10://Make the led blinking
      led.state = LED_BLINK;
      led.blinkCount = 65000;
      led.brightness = 0;
      break;

   case 11://Turn light on
      led.state = LED_ON;
      break;

   case 12://Turn light off
      led.state = LED_OFF;
      break;

   case 55://Force to go to sleep
      sleepNow();
      break;

   case 66://Reset button
      led.state = LED_OFF;
      led.blinkCount = 0;
      break;
      break;

   case 99://Answer Hello I'm alive
      break;

   }

   lastActionMillis = millis();

}

//****************************************

void setupRF24() {
   radio.setDataRate(RF24_250KBPS);
   radio.setPALevel(RF24_PA_MAX);
   radio.setChannel(125);
   radio.openReadingPipe(1, thisButtonAddress);
   radio.enableAckPayload();
   radio.setRetries(5, 15); // delay, count
   radio.startListening();
   radio.openWritingPipe(masterAddress);
}
//****************************************

void sendToMaster(int cmd) {

   if (Data_Sent.rnd == 0) {
      srandom(random() ^ ((uint32_t)analogRead(4) << 22) ^ micros());
      Data_Sent.rnd = random(0, 5000);
   }
   else {
      Data_Sent.rnd++;
   }

   Data_Sent.msg = cmd;

   radio.stopListening();

   delay(10);

   radio.write(&Data_Sent, sizeof(Data_Sent));

   radio.startListening();
   
}

//****************************************

void blinkLED() {
   unsigned long currentMillis = millis();

   if (currentMillis - previousMillis > BLINK_INTERVAL) {

      // save the last time you blinked the LED

      previousMillis = currentMillis;

      // set the LED with the ledState of the variable:
      digitalWrite(LED_PIN, ledState);

      ledState = !ledState;
   }
}


//****************************************

void blinkLED(int d) {
   digitalWrite(LED_PIN, HIGH);
   delay(d);
   digitalWrite(LED_PIN, LOW);
}

//****************************************

void blinkLED(int d, int t) {
   for (int i = 0; i < t; i++) {
      blinkLED(d);
      delay(d);
   }
}

//****************************************

//Read the button number from the DIP switch
void getButtonNr() {

   for (int i = 0; i < sizeof(DIPSwitchPins); ++i) {
      // Setup pin
      pinMode(DIPSwitchPins[i], INPUT_PULLUP);

      uint8_t curState = digitalRead(DIPSwitchPins[i]) ? 0 : 1;
      buttonNumber += (curState << i);
   }

   snprintf(thisButtonAddress, 6, "BTN%02d", buttonNumber);
}

//****************************************

void LED() {

   unsigned long date = millis();
   int valeurPWM;

   switch (led.state) {

   case LED_OFF:
      analogWrite(LED_PIN, 0);
      break;

   case LED_ON:
      analogWrite(LED_PIN, LED_MAX_BRIGHTNESS);
      break;

   case LED_BLINK:
      if (date - led.lastStateChange >= led.blinkSpeed) {
         led.lastStateChange = date;

         switch (led.brightness) {
         case 0:
            led.brightness = 250;
            break;
         case 250:
            led.brightness = 0;
            led.blinkCount--;
            break;
         }
         analogWrite(LED_PIN, led.brightness);

         if (led.blinkCount == 0)
            led.state = LED_OFF;
      }

      break;

   }
}

//****************************************

void wakeUpNow() {
   power_timer0_enable();
   power_timer1_enable();
   power_spi_enable();
   wakeUP = true;
}

//****************************************

void sleepNow() { 

   radio.powerDown();

   blinkLED(300, 2);

   led.state = LED_OFF;

   attachInterrupt(2, wakeUpNow, CHANGE);

   power_timer0_disable();
   power_timer1_disable();
   power_spi_disable();

   set_sleep_mode(SLEEP_MODE_PWR_DOWN);

   sleep_enable();


   sleep_mode();

   sleep_disable();
                     
   detachInterrupt(2);

}


Thanks

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by adafruit_support_mike on Sun Sep 01, 2019 6:36 pm

Try reducing the code above to the smallest version that still demonstrates the problem. That will help isolate what's going wrong.

adafruit_support_mike
 
Posts: 58843
Joined: Thu Feb 11, 2010 2:51 pm

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Mon Sep 02, 2019 1:18 am

Hi !

I've already reduced the code to a very simple version that still require the manual push of a button to "see/feel" the issue.

Seems hard to me to simplify further.

Something is happening during or after deep sleep that impact RF transmission.

I've read that the Timer is stopped during sleep and that could create some issues with millis() on wake up.

At the moment I perform a software reset with a watchdog on wake up to solve the issue.

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by adafruit_support_mike on Mon Sep 02, 2019 11:42 pm

Post the simplified version and we'll take a look.

adafruit_support_mike
 
Posts: 58843
Joined: Thu Feb 11, 2010 2:51 pm

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Tue Sep 03, 2019 2:25 am

Here it is :

Code: Select all | TOGGLE FULL SIZE
    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <ctype.h>
    #include <avr/sleep.h>
    #include <avr/power.h>
    #include <Bounce2.h>
    #include <LowPower.h>

    #define BUTTON_PIN 0
    #define LED_PIN 1
    #define CE_PIN A4
    #define CSN_PIN A5

    //LED states
    #define LED_OFF 0
    #define LED_ON 1
    #define LED_BLINK 2

    //**************************************************************************************

    //RF24
    const uint8_t masterAddress[6] = "SRV00";
    uint8_t thisButtonAddress[6] = "BTN02";

    RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

    volatile bool wakeUP = false;

    long lastActionMillis = 0;

    Bounce debouncer = Bounce();

    int buttonNumber = 2;

    //Struct for LED
    struct LED {
       byte state;
       int blinkSpeed;
       int blinkCount;
       int brightness;
       unsigned long lastStateChange;
    };

    //Struct for data to send
    typedef struct {
       uint8_t rnd;
       uint8_t type;
       uint8_t msg;
    }
    A_t;

    //Struct for data received
    typedef struct {
       uint8_t rnd;
       uint8_t type;
       uint8_t msg;
    }
    B_t;

    A_t Data_Sent;
    B_t Data_Received;

    struct LED led = { LED_BLINK, LED_FAST, 3, 0, 0 };

    //****************************************

    void setup() {

       Serial.begin(9600);

       pinMode(LED_PIN, OUTPUT); //Led pin

       radio.begin();

       delay(500);// Give RF module some time to run.

       setupRF24();

       debouncer.attach(BUTTON_PIN, INPUT_PULLUP);
       debouncer.interval(5); // interval in ms

    }

    //****************************************

    void loop() {

       if (wakeUP) {

          radio.powerUp();

          delay(500);

          pinMode(BUTTON_PIN, INPUT_PULLUP);

          led.state = LED_BLINK;
          led.blinkCount = 3;

          wakeUP = false;

          lastActionMillis = millis();

       }

       do {

          LED();

          debouncer.update();
         
          if (debouncer.read() == HIGH) {
             if (millis() - lastActionMillis > 200) {
                if (led.state == LED_OFF || !LED_BLINK) {
                   sendToMaster(buttonNumber);
                }
             }
             lastActionMillis = millis();
          }

          if (millis() - lastActionMillis > 480000) {
             sleepNow();
          }

       } while (!radio.available());

       radio.read(&Data_Received, sizeof(Data_Received));

       int order = Data_Received.msg;

       switch (Data_Received.msg) {

       case 11://Turn light on
          led.state = LED_ON;
          break;

       case 12://Turn light off
          led.state = LED_OFF;
          break;

       case 55://Force to go to sleep
          sleepNow();
          break;

       }
       lastActionMillis = millis();
    }

    //****************************************

    void setupRF24() {
       radio.setDataRate(RF24_250KBPS);
       radio.setPALevel(RF24_PA_MAX);
       radio.setChannel(125);
       radio.openReadingPipe(1, thisButtonAddress);
       radio.enableAckPayload();
       radio.setRetries(5, 15); // delay, count
       radio.startListening();
       radio.openWritingPipe(masterAddress);
    }
    //****************************************

    void sendToMaster(int cmd) {

       Data_Sent.rnd++;
         
       Data_Sent.msg = cmd;

       radio.stopListening();

       delay(10);

       radio.write(&Data_Sent, sizeof(Data_Sent));

       radio.startListening();
       
    }

    //****************************************

    void blinkLED(int d, int t) {
       for (int i = 0; i < t; i++) {
          digitalWrite(LED_PIN, HIGH);
             delay(d);
             digitalWrite(LED_PIN, LOW);
          delay(d);
       }
    }

    //****************************************

    void LED() {

       unsigned long date = millis();
       
       switch (led.state) {

       case LED_OFF:
          analogWrite(LED_PIN, 0);
          break;

       case LED_ON:
          analogWrite(LED_PIN, 255);
          break;
       }
    }

    //****************************************

    void wakeUpNow() {
       power_timer0_enable();
       power_timer1_enable();
       power_spi_enable();
       wakeUP = true;
    }

    //****************************************

    void sleepNow() {

       radio.powerDown();

       blinkLED(300, 2);

       led.state = LED_OFF;

       attachInterrupt(2, wakeUpNow, CHANGE);

       power_timer0_disable();
       power_timer1_disable();
       power_spi_disable();

       set_sleep_mode(SLEEP_MODE_PWR_DOWN);

       sleep_enable();

       sleep_mode();

       sleep_disable();
                         
       detachInterrupt(2);

    }

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by adafruit_support_mike on Tue Sep 03, 2019 3:35 am

If the board wakes up normally when you remove the code that talks to the nRF52, I'd guess it has something to do with establishing a connection to the radio.

adafruit_support_mike
 
Posts: 58843
Joined: Thu Feb 11, 2010 2:51 pm

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Tue Sep 03, 2019 3:49 am

Yes it's the RF that's slow.

Here is a video showing how the system behave :

https://youtu.be/DRIaGC7TSno

There is something happening during deep sleep that impact the RF, but what ?

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by adafruit_support_mike on Wed Sep 04, 2019 2:08 am

The radio may assume it's been disconnected when the microcontroller drops into a low-power mode. Try repeating the setup process after the board wakes up.

adafruit_support_mike
 
Posts: 58843
Joined: Thu Feb 11, 2010 2:51 pm

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by Alkerion on Wed Sep 04, 2019 2:23 am

HI !

Already tried, it doesn't solve the issue.

I even tried to totally turn off the RF module on sleep and turn it on on wake up, still doesn't work, the RF is still slow.

Alkerion
 
Posts: 70
Joined: Fri Jul 24, 2015 4:26 am

Re: Itsybitsy 32u4 8Mhz ultra slow on wake up

by adafruit_support_mike on Wed Sep 04, 2019 3:32 am

I'm afraid we don't know anything about the nRFL201. You might want to check with the folks at SparkFun to see if they know about any issues related to low power.

adafruit_support_mike
 
Posts: 58843
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.