So I am trying to write some code based on a PNP sensor to turn a relay on and off. I had some initial code that used delay to run the loop, but I am trying to use millis instead. I am fairly green to writing code so I am still attempting understand all of this.
My goal is to use the PNP sensor to either turn the relay on or off, but the big hiccup is that I want the relay to stay on for 10 seconds once the sensor goes low. Eventually I would like to make this time variable between 0-10 seconds but I am starting small first.
With the code below I can get the relay to turn off and on but the pause is not working correctly and if the sensor turns on and off quickly then it runs the relay for about 7 seconds, but if the sensor stays high for a few seconds it only keeps the relay on for a few seconds. Thanks for the help.
Here is an example of my layout, but I won't have the motor that is in the picture. I am using the relay to short to comm pins on a pump.
int motor=13; //
int inpin=2; // proximity sensor connected with the pin 2
int val=0; // this variable will read the value from the sensor
unsigned long sensorAir = 0;
const unsigned long running = 10000; // how long the pump will run after seeing air
void setup()
{
pinMode(motor,OUTPUT);
pinMode(inpin,INPUT);
}
void loop()
{
val=digitalRead(inpin);
unsigned long currentMillis = millis();
if(val==HIGH)
{
digitalWrite(motor,HIGH);
}
if (val==LOW)
{
if (currentMillis - sensorAir >= running) {
sensorAir = currentMillis;
digitalWrite(motor,LOW);
}
}
}
You are correct alto777. I changed that code around and now it will keep the relay on for 10 seconds regardless of how long the signal stays high. I appreciate it.
Now the harder part that I am wanting to do is use a potentiometer to adjust the timer from 0-10. Anyone have a good resource for trying to work this into the code?
will work better as it will not give you 10 discrete times over the range but so many it will seem continuous.
Unless it is that you want 10 discrete steps. map() isn't too good at that, it would need some handling so being on a threshold wouldn't randomly give you, say, either 5 or 6 seconds.
to make sure it is the solution. TBC - to see if just moving the timer setting line was enough as you said.
I ended up just multiplying the analogRead() value by 3 - life too short for ten seconds testing!
I tried the map stuff, it's just one line in there if you want to try a few things yourself. No account needed, change the sketch and whatever.
int motor = 6; //
int inpin = 7; // proximity sensor connected with the pin 2
int val = 0; // this variable will read the value from the sensor
unsigned long sensorAir = 0;
unsigned long running = 2777; // how long the pump will run after seeing air
void setup()
{
Serial.begin(9600);
pinMode(motor, OUTPUT);
pinMode(inpin, INPUT_PULLUP);
}
void loop()
{
delay(10); // just to cut down on printing.
val = !digitalRead(inpin); // ! so val true == pressed
unsigned long currentMillis = millis();
running = analogRead(A0) * 3;
if (val == HIGH) {
digitalWrite(motor, HIGH);
sensorAir = currentMillis;
Serial.println(running);
}
else {
if (currentMillis - sensorAir >= running)
digitalWrite(motor, LOW);
}
}
That seems to work perfectly. I will play with it to see if I can get it tweaked to work with an input that will send pin 7 high instead of pulling it to ground, but worst case is I can get a NPN sensor instead of a PNP sensor. Thanks a lot for the help and I will have to remember that site so I can work on circuits before making a real one.
So I tweaked it a little to see if I understand what I am doing and with the code below I can get similar results but I have found that sometimes the inpin remains high after the button is let go. Still trying to get a grasp for all of this but I will keep reading and keep testing. In the code below i changed the inpin to an input and not input_pullup. I also changed the layout for the button to be fed power and when pressed would drive pin 7 high.
int motor = 6; //
int inpin = 7; // proximity sensor connected with the pin 2
int val = 0; // this variable will read the value from the sensor
unsigned long sensorAir = 0;
unsigned long running = 2777; // how long the pump will run after seeing air
void setup()
{
Serial.begin(9600);
pinMode(motor, OUTPUT);
pinMode(inpin, INPUT);
}
void loop()
{
delay(10); // just to cut down on printing.
val = digitalRead(inpin); // ! so val true == pressed
unsigned long currentMillis = millis();
running = analogRead(A0) * 3;
if (val == HIGH) {
digitalWrite(motor, HIGH);
sensorAir = currentMillis;
Serial.println(running);
}
else {
if (currentMillis - sensorAir >= running)
digitalWrite(motor, LOW);
}
}
Just wanted to update that all seems to work on the prototype I threw together. The weird issues on the website simulation didn't transfer over to the actual project. Thanks again for all the help.
If you would care to elaborate or repeat anything you said about weird issues in the wokwi, I am sure I would like to confirm and then pass anything valid along to Uri and his boys over at wokwi.
I have found the simulator to be 99.99 percent faithful. There are some issues, but fewer as they get spotted, usually fixed very quickly.