So I am working on a project that requires a piston to be driven up and down by a DC motor (currently controlled by two relays, will change to a better controller soon but the general coding shouldn't change) between two hall effect sensors that read LOW when the piston (and magnet) are under them.
I have it working great so far, my issue comes with that I need the piston to stop at either end for a predetermined amount of time before returning. For the life of me I cannot get this to happen. Any ideas would be greatly appreciated.
Thanks for the help!
Here's my code so far that works great, just runs "flat out" if you will, and I need a delay at each end without overshooting.
#define forward 7 //define pin 7 as forward relay pin
#define back 8 //define pin 8 as backward relay pin
const int FrontHallPin = 3; //define pin 3 as front hall effect pin
const int RearHallPin = 2; //define pin 2 as rear hall effect pin
int FrontHallState = 0; //Create FrontHallState variable with 0 initial value
int RearHallState = 0; //Create RearHallState variable with 0 initial value
void setup() {
pinMode(back, OUTPUT); //Set backward relay pin as output
pinMode(forward, OUTPUT); //Set forward relay pin as output
pinMode(FrontHallPin, INPUT); //Set front hall signal pin as input
pinMode(RearHallPin, INPUT); //Set rear hall signal pin as input
if (RearHallState == HIGH or FrontHallState == LOW){ //If piston is anywhere but under
digitalWrite(back, LOW); //the rear sensor, send it back
digitalWrite(forward, HIGH);
}
}
void loop(){
RearHallState = digitalRead(RearHallPin); //Create rear hall state variable
FrontHallState = digitalRead(FrontHallPin); //Create front hall state variable
if (RearHallState == LOW){ //If the piston is under the rear sensor,
goforward(); //Send it forwards
}
if(FrontHallState == LOW){ //If the piston is under the front sensor,
goback(); //Send it back
}
}
void goforward(){ //Create the function of the piston going forward
digitalWrite(forward, LOW);
digitalWrite(back, HIGH);
}
void goback(){ //Create the function of the piston going backward
digitalWrite(back, LOW);
digitalWrite(forward, HIGH);
}
Well, let me ask you how are you able to stop a DC motor at a specific position? When you can answer this, you will know how to get your project to do the same.
Oh, you are not able to do this? Perhaps you need to rethink your project. Can you add an electric brake to the motor? Could you replace the motor with a stepper motor that would give precise position control and allow the motor rotation to be stopped at any position? Could you reverse the power to the motor until it stopped? Not a very accurate method.
A really simple solution if your code will never do anything else is to add delay() before you reverse the direction.
However, as Paul_KD7HB hints, you may find that the motor 'coasts' to a stop, overshooting the end mark. You may be better getting a motor controller board (dead cheap on eBay, probably cheaper than the relays) that have forward, reverse, stop and brake functions. Look for LM298 or similar ICs, rated for the current into your motors.
If you later intend the code to be doing more, it may pay to switch the coding style to a Finite State Machine and create a delay state that uses the same technique as the BlinkWithoutDelay example to time the passing of the waiting delay without blocking.
This is a job for a State Machine. It's not complex. You want to add a delay when each sensor is triggered but only when it's initially triggered, not when it has been in that position for some time.
So your program needs to remember the state of that sensor the last time it looked at it and then delay when it changes.
void loop(){
static int PrevRearState = LOW; //initial values correspond to known starting position, set by setup()
static int PrevFrontState = HIGH;
RearHallState = digitalRead(RearHallPin); //Create rear hall state variable
FrontHallState = digitalRead(FrontHallPin); //Create front hall state variable
if (RearHallState == LOW){ //If the piston is under the rear sensor,
if(RearHallState != PrevRearState) {
//this is the first time we have seen it go LOW
stop();
delay(RearDelaytimePeriod);
} else {
goforward(); //Send it forwards
}
}
if(FrontHallState == LOW){ //If the piston is under the front sensor,
if(FrontHallState != PrevFrontState) {
//this is the first time we have seen it go LOW
stop();
delay(FrontDelayTimePeriod);
} else {
goback(); //Send it back
}
}
PrevFrontState = FrontHallState; //remember for next time
PrevRearState = RearHallState;
}