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;
}
