MH-ET Live Tiny88 energy saving battery powered automatic trash bin lid

Hello,

I am working on battery powered project with Attiny88 - trash bin automatic lid opener.
I am trying to make it as energy efficient as possible, I am using Reed switch as a sensor, connected to interrupt pin. I have found that normally open state of the interrupt pin uses ~100uA less energy in sleep mode compared to NC. I am also using transistor to cut-off the power supply of the servo, when not in use - that saves ~5mA.
I have done following optimizations of the board:

  • Desolder 78L05 to save 6mA.
  • Desolder 16MHz clock oscillator (EN pin is shorted underneath to VCC so have to desolder) to save 2mA.
  • Desolder or cut green PWR LED 5V trace between regulator and RST PU resistor to save 3mA.
  • Desolder or cut USB_D- 1K PU resistor 5V trace between resistor and 5V to save 1.7mA (after this you have to program using ISP because the micronucleus USB won't work without this resistor and the external clock oscillator).

At the moment in PWR_DOWN mode the consumption is below 250uA, which is great.

I have also tried to incorporate battery voltage measurement in the code, to prevent over discharge of the battery, using that approach - https://ww1.microchip.com/downloads/en/Appnotes/00002447A.pdf

However, it seems I am doing something wrong in the code, because I can not make all that work together. No matter the state of the REED switch, the servo moves to the same position when I change its state or I reset the board.
The circuitry is not an issue, because it works just fine with simplified code where it only moves the servo, triggered by switch state change.

Can someone help?

#include <Servo.h>      // include the Servo library
#include <avr/sleep.h>  // include the sleep library
#include <avr/power.h>  // include the power management library

Servo myservo;  // create a servo object
float Vcc_value = 0;
float batteryLow = 3.4;

#define reedPin 3   // the pin the reed is connected to
int reedState = 0;  // variable to store the reed's state
#define LED 13      // LED pin
#define servoPower 4
#define servoPin 9

void setup() {
  myservo.attach(servoPin);        // attach the servo to servoPin
  pinMode(reedPin, INPUT_PULLUP);  // set the Reed pin as an input with an internal pull-up resistor
  pinMode(LED, OUTPUT);            // set the LED pin as an output
  pinMode(servoPower, OUTPUT);     // set the Servo power control pin as an output
  digitalWrite(servoPower, LOW);
  WDT_OFF();     // turn off WDT
  power_twi_disable();     // turn off Twin wire interface
  power_spi_disable();     // turn off SPI


  // set up the external interrupt on INT1 (pin 3)
  attachInterrupt(INT1, WAKE, CHANGE);  // attach the interrupt service routine to interrupt 1

  ADMUX = (0x00 << REFS0) /* AVCC with external capacitor at AREF pin */
          | (0 << ADLAR)  /* Left Adjust Result: disabled */
          | (0x0e << MUX0) /* Internal Reference (VBG) */;
  ADCSRA |= (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);  // Enable ADC, set prescaler to 128
}

void loop() {
  // Measure battery voltage - Start conversion
  ADCSRA |= (1 << ADSC);
  while (!(ADCSRA & (1 << ADIF)));
  Vcc_value = (0x400 * 1.1) / (ADCL + (ADCH << 8));

  if (Vcc_value <= batteryLow) {  // if the voltage is below the battery low limit flash LED 5 times
    for (int i = 0; i < 5; i++) {
      digitalWrite(LED, HIGH);
      delay(120);
      digitalWrite(LED, LOW);
      delay(120);
    }
  }

  reedState = digitalRead(reedPin);
  if (reedState == LOW && Vcc_value > batteryLow) {
    digitalWrite(servoPower, HIGH); // set the transistor HIGH in order to supply voltage to the servo
    delay(150); // wait for the voltage to stabilize
    myservo.write(0);  // rotate the servo to 0 degrees
  }
  if (reedState == HIGH && Vcc_value > batteryLow) {
    digitalWrite(servoPower, HIGH); // set the transistor HIGH in order to supply voltage to the servo
    delay(150);  // wait for the voltage to stabilize
    myservo.write(130);  // rotate the servo to 130 degrees
  }
  digitalWrite(servoPower, LOW); // turn off the power supply to the Sero to safe power
  WDT_OFF(); // turn Watch dog timer off
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // set the sleep mode to power-down
  sleep_mode();
}


// interrupt service routine
void WAKE() {
  sleep_disable();  // disable sleep mode
  
}

void WDT_OFF(void) {
  MCUSR &= ~(1 << WDRF);
  /* Write logical one to WDCE and WDE */
  /* Keep old prescaler setting to prevent unintentional time-out */
  WDTCSR |= (1 << WDCE) | (1 << WDE);
  /* Turn off WDT */
  WDTCSR = 0x00;
}

Tapping the controller 5 volt pin for servo power is not good. It's not designed for that. What's the voltage of the battery? Connected to 5 volt in USB plug?

I am not powering it up from the board, I have updated the schematics, as I said the issue is not in the circuit, as it works fine with different code.

I am using 1x18650 battery cell. I have experimentally found that it works fine up until it reach ~3.3V, therefore I set the cut-off voltage to 3.4V.

That wiring lacks GND connection between battery and controller.

Thanks for pointing out!
But as I said the issue is not in the circuit. This one is only illustrative, the physical one, of course have a common ground with the board and it is even powering up the board through 5V pin.
I cannot draw the same circuit as the one that I use, simply because Thinkerkad does not provide the opportunity to choose MH-ET Live Tiny88 as a board, neither 18650 battery.
But the circuit works fine with different code, which means the issue is with the code that I am trying to execute rather than the hardware/circuit.

Since you have lost the ability to debug your program, do you have a spare pin you can attach to a LED and resistor? Add a line of code to turn the LED on the first program compare to see if your logic got that far. If the LED turns on. Move to then next compare or other possible bug spot.
Yes, lots of steps and lots of compiles and uploads, but what other debug method do you have?

Thanks for suggestion!
I am not able to use Serial monitor with this board anyway, so I haven't really loose that functionality. I am planning however to try to use Software serial with CH340 programmer to add some debugging lines.
I am pretty sure that the issue is coming from the Vcc measurement and I was hoping that someone else would have more experience with that functionality and would be able to help...