ADC readings after waking up from POWER-DOWN

Hello, I want to read and analog input before and after going into power-down mode. Without the sleeping function, it works like it should. However, as soon as the power-down mode is integrated, the ADC readings are garbage, and the serial monitor spits out garbage.

I do understand, that waking up from power-down requires setup-time of the clocks, and that once the ADC is turned off and on, the first ADC conversion is extended to 25 clock cycles.
But how can I fix this? How can I get reliable ADC readings after waking up from power-down? And more importantly why is this even happening?

I hope someone can give me some advice.

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

void WatchDogSetup() {
  MCUSR = 0; // Set all MCU Status Register Flags to 0 (incl. WDFR)
  WDTCSR = bit(WDCE) | bit(WDE); 
  WDTCSR =  bit(WDIE) | bit(WDP3) | bit(WDP0); // | bit(WDP0) 
}

void sleeping() {
  ADCSRA &= ~ (1 << ADEN);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu();
  sleep_disable();                 
  ADCSRA |= (1 << ADEN);
  }

void setup() {
  Serial.begin(9600);
  WatchDogSetup();
}


void loop() {
int value = analogRead(A0); 
Serial.print("First value: ");
Serial.println(value);
sleeping();
int new_value = analogRead(A0);
Serial.print("Second: Value");
Serial.println(new_value); 
}

ISR(WDT_vect) {
}

On my 328P based setup, I seem to recall that after coming out of sleep, I had to take an ADC reading and discard it, then take the next reading as required.

Try doing 2 reads of A0 when you come out of sleep.

Thanks for the suggestion. I have adjusted the loop like so:

void loop() {
int value = analogRead(A0);
value = analogRead(A0);
Serial.print("First value: ");
Serial.println(value);
sleeping();
int new_value = analogRead(A0);
new_value = analogRead(A0);
Serial.print("Second: Value");
Serial.println(new_value); 
}

This is the output on the serial monitor:

��Z�.␗���Օ� 518
Second:␀���Օ�18
First value: 521
Second:␀���Օ�15

Interestingly, if I pot both analogReads into separate for-loops of length 5 e.g., most of the readings are sensible. Perhaps there is some setup time that I'm unaware of?

Edit:
In an earlier version of the same project, I simply added some delay(10) before each ADC reading which also gave me reasonable readings.

I will take a SWAG and say you are using a ESP processor that has not yet changed back to the user's baud. You will have to switch to that baud ( The default baud rate is 460800) or delay until it settles. It is also good practice to some dummy reads when waking up an A/D. Posting an annotated schematic would help.

Turns out, the ADC readings are not at all the problem. Since there is no other way to debug the ADC readings other than serial communication, a delay must be used.

I independently tried transmitting random text over serial communication without delay before and after going into power-down, and it's garbage. A delay must be added to ensure proper transmission. This delay varies with the length of the message, as well as the serial baud rate I presume.

I am using an Arduino MEGA, but I did investigate playing around with delays and baud rate and realized that it's not the ADC readings that are messed up, but rather the serial transmission. After adding some short delay it worked as intended

1 Like

I can confirm that you need to delay before you go to sleep if your previous statement was a print

Have you tried Serial.flush() before sleep?

Serial.flush() before sleeping indeed works! Seems like a much better alternative rather than putting a random delay.

Edited: Do you happen to know why both delay works as well though? Are we basically hoping that serial communication completes while the MCU is delaying?

Exactly.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.