Automatic toilet flusher killing battery when not in use

I made an automatic toilet flusher and it works great, but the 9v battery im using dies within 2-3 hours.

Heres the code im using not sure if this is the issue or not. Any help much appreciated!

int servoPin = 4;
int buttonPin = 6;
int stat = 1;
int pulse90 = 2400;
int pulse0 = 500;
int imThere = 0;
int moving = 0;
int servoStat = 0;

void setup()
{
  pinMode(servoPin, OUTPUT);

  pinMode(buttonPin, INPUT);

  Serial.begin(9600);
    moveReset();

}
void move()

{
  int i=0;
  for(i=0;i<16;i++)  //runs move 17 times to get servo to 180 degrees
  {                 
    digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse90);
    digitalWrite(servoPin, LOW);
    delay(50);
  } 
}

void moveReset()

{
  int i=0;
  for(i=0;i<16;i++)     // resets servo to 0 degrees
  {
   digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse0);
    digitalWrite(servoPin,LOW);
    delay(50);
  }
}
void stop()
{
  
}

void loop()
{
  
  stat = digitalRead(buttonPin);
  if ((stat == 1)&& moving == 1)  // if button is not pressed reset to 0
  {
    moveReset();
    moving = 0;

  }
  if ((stat == 0)&& moving == 0)  //if button is pressed move to 180 degrees
  {
      move();
      delay(2000);      
      moving = 1;
  }

  Serial.println(stat);
}

If your 9v battery is one of those tiny PP3 things then get shot of that immediately. They have a minute charge capacity and very low current capacity, and since they're much higher voltage than the Arduino uses most of that precious energy will be thrown away as heat in the voltage regulator anyway.

You don't say whether the same battery is also powering the servo, but if it is then it's mildly surprising that it's lasting even that long.

What you want for the Arduino is a battery box with four NiMh or similar rechargeable batteries - these will put out around 5V total which means you can connect directly to the 5V line and not waste power in the voltage regulator. Various sizes are available but AA are nice and compact, they don't hold a huge charge but it will be massively more than those tiny PP3 things.

I don't know how you're powering the servo or how much power it's going to take, but a servo can take a substantial amount of current and could flatten a small battery quite quickly, so if this is intended for long term use you might find you need quite a hefty battery, or some way to recharge it regularly.

Which Arduino are you using? You should change your code so that it is asleep when it is not doing anything. Change buttonPin to pin 2 or 3, either of which can be attached to an interrupt, so that your code can be asleep unless the button is pushed. Read Nick Gammon's website about saving power with sleep modes on the Arduino http://www.gammon.com.au/forum/?id=11497

Pete

Thank for the quick replys!
Im using the UNO and thanks for the website will definitely check it out.

Im not sure what you mean by PP3 but its a normal 9 volt battery and yes the servo is running off of it. Should i set up a completely different power source fore the servo? or if i switch to the AAs will that increase my overall battery life?

Here’s my updated code.

#include <avr/sleep.h>

int servoPin = 4;
int buttonPin = 3;
int stat = 1;
int pulse90 = 2400;
int pulse0 = 500;
int imThere = 0;
int moving = 0;
int servoStat = 0;
int sleepStatus = 0;

void setup()
{
  pinMode(servoPin, OUTPUT);

  pinMode(buttonPin, INPUT);

  Serial.begin(9600);
  
  attachInterrupt(0, wakeNow, LOW);
    moveReset();

}
void move()

{
  int i=0;
  for(i=0;i<16;i++)  //runs move 17 times to get servo to 180 degrees
  {                 
    digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse90);
    digitalWrite(servoPin, LOW);
    delay(50);
  } 
}

void moveReset()

{
  int i=0;
  for(i=0;i<16;i++)     // resets servo to 0 degrees
  {
   digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse0);
    digitalWrite(servoPin,LOW);
    delay(50);
    sleepNow();
   
  }
}
void sleepNow()
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  attachInterrupt(0, wakeNow, LOW);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);
 
}
void wakeNow()
{
 
}


void loop()
{
  
  stat = digitalRead(buttonPin);
  if ((stat == 1)&& moving == 1)  // if button is not pressed reset to 0
  {
    moveReset();
    moving = 0; 

  }
  if ((stat == 0)&& moving == 0)  //if button is pressed move to 180 degrees
  {
      move();
      delay(2000);      
      moving = 1;
  }

  Serial.println(stat);
}

attachInterrupt(0,..) is for pin 2. Change buttonPin to 2.

You also don't need to read the button state in loop(). You can specify CHANGE in the attachInterrupt instead of LOW and then read the state of buttonPin in the interrupt routine. That way you get an interrupt when the button is pressed (and set state to zero) and when it is released (and set state to 1).

Pete

I'm not sure what you mean as i am fairly new to coding if you could give me an example or try to clarify please? Thanks!

Fix up the button value:

int buttonPin = 2;

and change this piece of code:

void wakeNow()
{
}
void loop()
{ 
  stat = digitalRead(buttonPin);

to this:

void wakeNow()
{
  stat = digitalRead(buttonPin);
}
void loop()
{

Pete

Ok thats what i thought and i did that but now its not reading anything. No servo action, and no serial printout. any ideas?

I forgot this:

  attachInterrupt(0, wakeNow, CHANGE);

Pete

I changed that as well its working now, however it works periodically then stops and wont work again for about a minute. and it only moves small stuttering steps when the button is pushed and released it does return to 0 degrees correctly once it reaches 180 degrees after several button presses to get it there. Can you point me in the right direction? I really appreciate the help!

Also is there a way to tell if the arduino is asleep?

Update: I removed sleepNow from moveReset and it works both ways now i just have no way of knowing if the arduino is actually asleep or not.

heres my current code

#include <avr/sleep.h>

int servoPin = 4;
int buttonPin = 2;
int stat = 1;
int pulse90 = 2400;
int pulse0 = 500;
int imThere = 0;
int moving = 0;
int servoStat = 0;
int sleepStatus = 0;

void setup()
{
  pinMode(servoPin, OUTPUT);

  pinMode(buttonPin, INPUT);

  Serial.begin(9600);
  
  attachInterrupt(0, wakeNow, CHANGE);
    moveReset();

}
void move()

{
  int i=0;
  for(i=0;i<16;i++)  //runs move 17 times to get servo to 180 degrees
  {                 
    digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse90);
    digitalWrite(servoPin, LOW);
    delay(50);
  } 
}

void moveReset()

{
  int i=0;
  for(i=0;i<16;i++)     // resets servo to 0 degrees
  {
   digitalWrite(servoPin, HIGH);
    delayMicroseconds(pulse0);
    digitalWrite(servoPin,LOW);
    delay(50);
    
   
  }
}
void sleepNow()
{
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  attachInterrupt(0, wakeNow, CHANGE);
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);
 
}
void wakeNow()
{
 stat = digitalRead(buttonPin);
 Serial.println(stat);
}


void loop()
{
  
  stat = digitalRead(buttonPin);
  if ((stat == 1)&& moving == 1)  // if button is not pressed reset to 0
  {
    moveReset();
    moving = 0; 
    sleepNow();

  }
  if ((stat == 0)&& moving == 0)  //if button is pressed move to 180 degrees
  {
      move();
      delay(2000);      
      moving = 1;
      sleepNow();
  }

  
}

rampartpeak: Im not sure what you mean by PP3 but its a normal 9 volt battery and yes the servo is running off of it.

I don't know what you think a 'normal' 9v battery is. PP3 is a standard battery package. If you don't know what a PP3 battery looks like, google is your friend.

rampartpeak: Should i set up a completely different power source fore the servo? or if i switch to the AAs will that increase my overall battery life?

PP3 is a terrible choice for powering a servo. It only has a miniscule charge capacity and also very low current capacity and they are also relatively expensive. Replace that PP3 with four rechargeable AA batteries and you will get a massive increase in battery life. For the final product, I suggest you work out how long you need a battery to last for and then see whether the life of your AAs is sufficient - depending what you're trying to achieve it may be necessary to go to bigger batteries. Those tiny PP3s are a waste of time and money, though - get rid of that right away.

Why aren't you using the Servo library to move your servo?

The move() and moveReset() functions are nearly identical. The only difference is the delay time. Make that an argument to one of the functions, and get rid of the other one.

Serial output in an interrupt service routine is not a good idea. Interrupts are disabled in an ISR, and Serial output happens using interrupts.

moving should be a boolean. You are either moving or not, right?

Your sleepNow function isn't correct. It shouldn't detach the interrupt. Try this:

void sleepNow(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  cli();
  sleep_enable();
  sei();
  sleep_cpu();
  sleep_disable();
}

Pete