interrupts vs. watchdog vs. readVCC()

Hi you SIFU

I have a bit of a weird problem. I was reading like hell and playing around with the readVCC() function (you can find that approach several times online) and an interrupt and a watchdog timer.
Everything is working fine but when I through everything together the readVCC() just delivers -1
I have tried many things like giving the arduino (or actually the Atmega328p-pu standalone) enough time to settle down before reading VCC (10sec should do the deal I assume) or placing the function in different spots.
Whenever I put in in my if else if else statement it delivers -1, all other spots seems to work.

Where do I have my mistake? I just crack my head around it but can’t figure it out.
Please point me…

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

#define LED 13

volatile bool door1=false;
int counter = 1;

// interrupt service routine for when button pressed
void wake ()                            
{
  wdt_disable();  // disable watchdog
  noInterrupts (); // avoid wake up by trigger until done 
}  // end of wake

void door_open()
{
//run on pin change D2
//create double flash rather than single
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
door1 = true;
wake ();  
}

// watchdog interrupt
ISR (WDT_vect) 
{
  wake ();
}  // end of WDT_vect

void myWatchdogEnable (const byte interval) 
{ 
  MCUSR = 0;                          // reset various flags
  WDTCSR |= 0b00011000;               // see docs, set WDCE, WDE
  WDTCSR =  0b01000000 | interval;    // set WDIE, and appropriate delay
  wdt_reset();
  
  byte adcsra_save = ADCSRA;
  byte prr_save = PRR;

  ADCSRA = 0;  // disable ADC
  PRR = 0xFF; // turn off various modules
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
  attachInterrupt (0, door_open, CHANGE);   // allow grounding pin 2 to wake us up 
  sleep_mode ();            // now goes to Sleep and waits for the interrupt
  ADCSRA = adcsra_save; // stop power reduction
  PRR = prr_save;
}  // end of myWatchdogEnable

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  

  delay(2); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
  uint8_t high = ADCH; // unlocks both

  long result = (high<<8) | low;

  result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

void setup ()
{
  digitalWrite (2, HIGH);    // pull-up on button
  //allow serial print for debugging, can be deleted for standalone version
  Serial.begin(57600);
  Serial.println("\n\rDoorsensor Example\n\r\n\r");
}  // end of setup

void loop()
{
  if (door1 == true)
    {
    if (digitalRead(2) == HIGH)
      Serial.println("                                                                      Door 1 is [/ (open)");
    else
      Serial.println("                                                                      Door 1 is [| (closed)");  
    delay(50); 
    //double fast blink the LED, than sleep again!
    pinMode (LED, OUTPUT);
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    delay (50);
    digitalWrite (LED, HIGH);
    delay (50);
    digitalWrite (LED, LOW);
    door1 = false;
    counter = 1;
    }
  else if ( counter > 2 ) // WDT triggered often enough, slow blink once, 2 for testing, later high number to archive 10minutes or similar
    {
    Serial.print("                                      Statusreport: ");
    Serial.println( readVcc(), DEC );
    delay(100);
    pinMode (LED, OUTPUT);
    digitalWrite (LED, HIGH);
    delay (100);
    digitalWrite (LED, LOW);
    counter = 1;  
    }  // WDT triggered, slow blink once
  else //WDT triggered but do nothing
    {
    Serial.print(counter);
    Serial.println(" WDT skipped");
    delay(50);
    counter++; 
    }
interrupts(); // we are done, allow more interrupts
delay(50);
  // sleep again for 1 second or interrupt
  myWatchdogEnable (0b000110);  // 1 second

}  // end of loop

very confusing code IMHO,

your function wake() disables interrupts, they are never enabled again until the end of loop(). This may lead to problems with mills(), delay() and serial output.

your function myWatchdogEnable() puts the processor to sleep as well, why not name it apropriately?

If I understand your description correctly, then readVcc() works in other spots, but not from where it is called now. Try removing ADCSRA = 0;. I suspect the ADC is not enabled again when you wake from sleep although you seem to restore it.

Thanks so much, now it entlighted me Makes somehow sense that an read of an input screws if the ADC is still sleeping.

I take your remark as well for the confusing part. I have to admit some copy and paste was involved without me 100% understanding what each line does. Will do a lot more reading on each flag used and guess from there can reengineer the approach. Will post my outcome and code again once the homework part on this is done.

Thanks a lot. That was an eye opener!