Hi all! Im having a bit of trouble programming a 'timer' into my if statement. Essentially, I want a force sensitive resistor to be above threshold for 5 seconds, before my Arduino tells the two DC pumps that I have connected to it what to do. I was able to look around the forum and find some guidance based on a project done with water levels, but I seem to be missing a critical step to get my code to work.
I am able to get the pumps to turn on if I just use the threshold level as my condition, but I need the FSR to be above threshold for 5 seconds before the pumps do anything. I have attached my code for assistance. Thank you.
I am using an Arduino Uno R3 with an Adafruit Motorshield V2. The DC motors are 12 V DC Vacuum pumps from Karlson Robotics. I have a square FSR from interlink electronics connected to my Arduino with a 10 K pull down resistor.
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *inflate = AFMS.getMotor(1);
// You can also make another motor on port M2
Adafruit_DCMotor *deflate = AFMS.getMotor(2);
int fsrPin = 0;
int fsrValue = 0;
bool standing = false; //create boolean operator for standing
unsigned long firstMillis;
unsigned long interval = 5000; //5 second threshold for standing still
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Adafruit Motorshield v2 - DC Motor test!");
AFMS.begin(); // create with the default frequency 1.6KHz
// Set the speed to start, from 0 (off) to 255 (max speed)
inflate->setSpeed(255);
deflate->setSpeed(255);
}
void loop() {
unsigned long currentMillis = millis();
fsrValue = analogRead(A0);
Serial.println(fsrValue);
if (fsrValue > 20 && standing == false){ //change the 20 value depending on the pressure readings and maybe even add range for sitting
firstMillis = millis();
standing = true;
}
else{
standing = false;
}
if(millis() - firstMillis >= interval && standing){
deflate->run(RELEASE);
inflate->run(FORWARD);
delay(18000);
inflate->run(RELEASE);
deflate->run(FORWARD);
delay(8000);
}
else{
inflate->run(RELEASE);
deflate->run(RELEASE);
}
}
I'd introduce a boolean called say timingStarted, initialised false.
If timingStarted is false and the fsr is over the threshold, make a note of the start time into a variable and make timigStarted true.
Then each time through loop() if fsr is over threshold AND timingStarted is true, check to see if the 5 seconds has passed. If it has, turn on pumps and make timingStarted false.
If timigStarted is true but fsr is under the threshold, then just make timingStarted false.
Okay, this is what I did in response to your post, and I still cant get the motors to activate.
include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *inflate = AFMS.getMotor(1);
// You can also make another motor on port M2
Adafruit_DCMotor *deflate = AFMS.getMotor(2);
int fsrPin = 0;
int fsrValue = 0;
bool standing = false; //create boolean operator for standing
bool timingStarted = false;
unsigned long firstMillis;
unsigned long interval = 5000; //5 second threshold for standing still
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Adafruit Motorshield v2 - DC Motor test!");
AFMS.begin(); // create with the default frequency 1.6KHz
// Set the speed to start, from 0 (off) to 255 (max speed)
inflate->setSpeed(255);
deflate->setSpeed(255);
}
void loop() {
unsigned long currentMillis = millis();
fsrValue = analogRead(A0);
Serial.println(fsrValue);
if (fsrValue > 20 && timingStarted == false){ //change the 20 value depending on the pressure readings and maybe even add range for sitting
firstMillis = millis();
standing = true;
timingStarted = true;
}
else{
standing = false;
timingStarted = false;
}
if(millis() - firstMillis >= interval && standing && timingStarted){
Serial.print("tick");
deflate->run(RELEASE);
inflate->run(FORWARD);
delay(18000);
Serial.print("tock");
inflate->run(RELEASE);
deflate->run(FORWARD);
delay(8000);
}
else{
Serial.print("tack");
inflate->run(RELEASE);
deflate->run(RELEASE);
}
}
Okay new problem. If I press the FSR over threshold for less than 5 seconds, the motors still turn on. My code is essentially acting as a huge delay function as long as the pressure sensor is over threshold for any amount of time. I need the pressure sensor to be over threshold for those 5 seconds before the pumps turn on.
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *inflate = AFMS.getMotor(1);
// You can also make another motor on port M2
Adafruit_DCMotor *deflate = AFMS.getMotor(2);
int fsrPin = 0;
int fsrValue = 0;
bool timingStarted = false;
unsigned long firstMillis;
unsigned long interval = 5000; //5 second threshold for standing still
void setup() {
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Adafruit Motorshield v2 - DC Motor test!");
AFMS.begin(); // create with the default frequency 1.6KHz
// Set the speed to start, from 0 (off) to 255 (max speed)
inflate->setSpeed(255);
deflate->setSpeed(255);
}
void loop() {
unsigned long currentMillis = millis();
fsrValue = analogRead(A0);
Serial.println(fsrValue);
if (fsrValue > 20 && timingStarted == false){ //change the 20 value depending on the pressure readings and maybe even add range for sitting
firstMillis = millis();
timingStarted = true;
}
else{
inflate->run(RELEASE);
deflate->run(RELEASE);
}
if(millis() - firstMillis >= interval && timingStarted){
deflate->run(RELEASE);
inflate->run(FORWARD);
delay(18000);
inflate->run(RELEASE);
deflate->run(FORWARD);
delay(8000);
timingStarted = false;
}
}
I haven't time to look properly right now, and while I'm not saying that my "model" above is the only way to do this, it doesn't look like your code follows my steps.
Here's a re-statement of what I said earlier, in pseudocode:
//pseudocode
if fsr>threshold AND timingstarted false
starttime=millis
timingstared true
if fsr>threshold AND timingstarted true
if millis-starttime > interval
startmotors
timingstarted false
if timingstarted true AND fsr< threshold
timingstarted false
I've tried the code you suggested, and it seems that it is just acting as a timer after the first timepoint once the FSR is over threshold. Its not forcing the sensor to be above threshold for the whole interval. As long as there are two "over threshold" points greater than the length of the interval, the motors will activate.