Good day, I am new to Arduino, but have made some nice projects work. I have a n issue with a Auto fish feeder. I have used a servo that I modified to run 360. I am having a issue when the Nano board starts. It runs the time I have set between feeds, and then it stops. If I set it to feed every 10 sec, it starts up and run for 10sec and then the LED flashes and it stops. From there it works perfect. But if I lose power and it comes back, its going to feed for 10sec and that will kill the fish.
Here is my sketch attached I am using now, please can someone look at it and tell me where I am going wrong. I just want it not to run when it starts up, or just for the to that it feeds, not continues like now for 10sec, or 12 hours !!!
//--Setting Vars
//Fish Feeder Vars.
int pinOutMotor = 3;
int pinOutLed = 5;
int pinInButton = 2;
int MotorRunDuration = 1000;
float AutoWaitDurationHours = 0.;
//--Program Vars
unsigned long currentMsSinceStart = 0;
unsigned long msValueAtLastRun = 0;
float HoursSinceLastRun = 0;
int buttonValue = 0;
void setup() {
Serial.begin(9600); //Turns on serial monitor.
pinMode(pinOutMotor, OUTPUT); //Is controlled by a 3906 npn transistor to switch the motor off and on. When program started I need to add a line to turn off motor when program was started.
pinMode(pinInButton, INPUT); //Manual feed.
pinMode(pinOutLed, OUTPUT); //Shows motor is on when lite.
}
void loop() {
//HoursSinceLastRun = AutoWaitDurationHours - 0.05; //this will make it run 3 minutes after turned on.
//Fish Feeder
//get miliseconds since program start and calc.
currentMsSinceStart = millis();
HoursSinceLastRun = (currentMsSinceStart - msValueAtLastRun) / 43200000; //10000 millis= 10 seconds. To change the time to vary feeding times set for 12hrs type in 43200000 or 6hrs tyoe in 21600000.
//check for button press
buttonValue = digitalRead(pinInButton);
if(buttonValue == HIGH){ //had to change state because of button from LOW to HIGH.
//run motor for button press.
RunMotor();
Serial.println("Feed Fish Manually"); //serial print funtion completed by button
} else if(HoursSinceLastRun > AutoWaitDurationHours){
RunMotor();
msValueAtLastRun = currentMsSinceStart;
Serial.println("Feed Fish Auto"); //serial print funtion completed by auto wait duration hours
}
//slow the loop down so it isn't running at full CPU Utilization for nothing.
delay(50); //delay 1/20th of a second.
}
void RunMotor(){
analogWrite(pinOutMotor, 0); // turn on motor
analogWrite(pinOutLed, 80); // turn on green led to show motor is on.
delay(MotorRunDuration); // wait for motor run duration to expire
analogWrite(pinOutMotor, 255); // turn off motor
analogWrite(pinOutLed, 0); // turn off green led to show motor is off.
}
UKHeliBob:
Do you need to use a continuous rotation "servo" ?
depending the way the feeder works, it might be driving a worm screw that drives the flakes into the water, so basically it's just a motor that has to spin, no need for a servo
J-M-L:
depending the way the feeder works, it might be driving a worm screw that drives the flakes into the water, so basically it's just a motor that has to spin, no need for a servo
Yes this is 100% the same, I did this project from Thingiverse
Everything works, its just the start, its runs for the time that should be delayed between feeds first. In my sketch its 10sec, if I make it 20sec, the servo runs for 20sec before it goes to the first feed. I need to have feed as the first action and then delay
Loeikie:
I am really green an do not know what it should be.......
well your code in the loop reads like this
//get miliseconds since program start and calc.
currentMsSinceStart = millis();
HoursSinceLastRun = (currentMsSinceStart - msValueAtLastRun) / 43200000;
//check for button press
buttonValue = digitalRead(pinInButton);
if(buttonValue == HIGH){
//run motor for button press.
RunMotor();
Serial.println("Feed Fish Manually");
} else if([color=red]HoursSinceLastRun > AutoWaitDurationHours[/color]){
RunMotor();
msValueAtLastRun = currentMsSinceStart;
Serial.println("Feed Fish Auto");
}
after a few milliseconds (the loop spins quickly) what do you think the result of the test HoursSinceLastRun > AutoWaitDurationHours will be given HoursSinceLastRun is a floating point value and AutoWaitDurationHours is worth 0
//check for button press
buttonValue = digitalRead(pinInButton);
if(buttonValue == HIGH){
//run motor for button press.
RunMotor();
Serial.println("Feed Fish Manually");
} else if(HoursSinceLastRun > AutoWaitDurationHours){
RunMotor();
msValueAtLastRun = currentMsSinceStart;
Serial.println("Feed Fish Auto");
}
after a few milliseconds (the loop spins quickly) what do you think the result of the test HoursSinceLastRun > AutoWaitDurationHours will be given HoursSinceLastRun is a floating point value and AutoWaitDurationHours is worth 0
forget what I said, the math (currentMsSinceStart - msValueAtLastRun) / 43200000 is done in unsigned long as those values are not float - only where you store the result. so indeed you get an integral value regardless of the fact that you store the result in a float, so the if does not trigger (I had assumed that very quickly HoursSinceLastRun would become 0,0000001 and thus the if would trigger)
Issue might be elsewhere: do you have a pull down on your button?
J-M-L:
forget what I said, the math (currentMsSinceStart - msValueAtLastRun) / 43200000 is done in unsigned long as those values are not float - only where you store the result. so indeed you get an integral value regardless of the fact that you store the result in a float, so the if does not trigger (I had assumed that very quickly HoursSinceLastRun would become 0,0000001 and thus the if would trigger)
Issue might be elsewhere: do you have a pull down on your button?
J-M-L I feel very dumb at the moment, I have no idea what you mean by " a pull down on your button" ?
If an input pin is not held at either HIGH or LOW at all times it is susceptible to picking up stray voltages causing the Arduino to act as if the button has been pressed. A pulldown resistor connecting the pin to GND would keep the pin in a known LOW state until the button is pressed to connect it to 5V to take it HIGH
UKHeliBob:
If an input pin is not held at either HIGH or LOW at all times it is susceptible to picking up stray voltages causing the Arduino to act as if the button has been pressed. A pulldown resistor connecting the pin to GND would keep the pin in a known LOW state until the button is pressed to connect it to 5V to take it HIGH
Ahh !!!! I have removed the Button ! and the res, so you are saying that it may not read this correctly then ?
The simplest way to deal with the need to keep digital input pins in a known state is to use
pinMode(pin, INPUT_PULLUP);
which turns on the built in pullup resistor. The button needs to be wired to take the pin LOW when pressed and any logic in the program needs to match the "LOW equals pressed, HIGH equals not pressed" model.