A-Star Micro, Serial loss when sleeping mcu

I looked here and some other forums, and cannot find following issue addressed fully to my understanding.

I have an A*u with a temp sensor that periodically prints its measurement over serial. Into the code I added a sleep function in place of the delay millis for measurement interval and power saving. The board loses its Serial port once the “sleep” sketch is uploaded. The “delay” sketch runs fine.

Have found some references to this issue, vaguely describing the mcu board not informing the USB host it is going to sleep, in order to preserve the serial port, &c.
The two workarounds offered at Reviving using the Arduino IDE did not work.

Will be researching this further, but if folks here could assist in informing me, that would be great.

Thanks, Mark

Hello, Mark.

We do not have any example code for putting the A-Star 32U4 to sleep. If it sleeps while connected to USB, you will need to make sure that the AVR can still respond to USB packets. For some USB packets, that will definitely require waking up the CPU and running some code. You might consider programming the AVR so that it never goes to sleep while USB is connected.

If you are currently able to program your A-Star, there is no need to use the reviving procedures documented in the A-Star 32U4 user’s guide. If you are unable to program your A-Star, can you describe in detail what happens when you attempt to use the “uploading-before-bootloader” method?

–David

Aloha David, and thanks for responding.

Have researched several fora in re this issue. Most OP’ers begin with similar quandary as mine. Reading Chapter 22 of datasheet is a start for me, but my modest, hobbyist level understanding of that material will take some time to improve.
My arduino sketch is attached. Desire is to use the 32u4 A* Micro in place of the bare chip Attiny84A and 328P-PU/AU nodes I been building, for no reason other than have couple extra 32u4’s on hand. Sleeping a 32u4 would be something handy to know I figure. The Attiny84 and 328’s are for me easy to work with. Generally, the node will sleep for a while (15mins), wake up, send its data over radio and go back to sleep. The USB peripheral on the 32u4 that’s where I get hung up. Hell, may not even need the USB in application, but for testing/debugging is kinda helpful to have.

LM335_tester.ino (2.5 KB)

Aloha,
Mark

In the sleep mode you are trying to use (Power-down Mode), the main oscillator and the USB clock are shut down, so the AVR cannot be woken up by USB packets. You would need to use Idle Mode or ADC Noise Reduction Mode.

Here is some code I came up with that seems to work:

// This code shows how to put the ATmega32U4 to sleep while still
// maintaining the USB connection.
//
// Control transfers wake up the CPU and are handled quickly.
// Serial data received (and probably also data sent) via USB is not
// handled quickly because we have not configured the USB endpoint
// interrupts to wake up the CPU.  However, we use the watchdog timer
// to wake up the CPU once per second so that those things will get
// handled eventually.  

#include <avr/sleep.h>
#include <avr/wdt.h>

ISR(WDT_vect) {}

void setup() {
  pinMode(13, OUTPUT);
  set_sleep_mode(SLEEP_MODE_IDLE);

  // Enable watchdog timer interrupt with 1 s timeout.
  cli();
  wdt_reset();
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  WDTCSR = (1 << WDIE) | (1 << WDP1) | (1 << WDP2);  
  sei();
}

void loop() {
  while (Serial.available()) {
    uint8_t r = Serial.read();
    Serial.write(r + 1);
  }

  // Blink the yellow LED so we can see how often the CPU wakes up.
  digitalWrite(13, HIGH);
  delay(15);
  digitalWrite(13, LOW);
  delay(15);

  sleepNow();
}

void sleepNow() {
  // Disable the Arduino IDE's Timer 0 interrupt, which fires approximately
  // once per millisecond.
  TIMSK0 &= ~(1 << TOIE0);

  // Disable the USB start of frame interrupt, which fires approximately
  // once per millisecond while USB is connected.
  UDIEN &= ~(1 << SOFE);

  // Go to sleep using the sequence documented in sleep.h.
  cli();
  sleep_enable();
  sei();
  sleep_cpu();
  sleep_disable();

  // Undo our changes from earlier.
  UDIEN |= (1 << SOFE);
  TIMSK0 |= (1 << TOIE0);
}

I am not sure how much power this will actually save, since the main clock will still be running. Are you able to measure it?

–David