PROBLEM: force sensor -margins

Hey guys,
I have a problem with the code. The project is to turn the vibration motors after 30 s when the force sensor is pressed in value bigge than 30. the problem is that the timer should reset itself if the value dicreases/increases more than 5. So, let say, thw timwer goes on:

1 second - 40
2 s -41
3 s -41
4 s -40
5 s - 44
6 s - 59 (here the code should reset the timer, but it goes on whenever value is bigger than 30)

can someone help?

int sensorPin = A0; // select the input pin for the force sensor
int firstMotorPin = 13; // select the pin for the motor
int secondMotorPin = 12; // select the pin for the motor
int sensorValue = 0; // variable to store the value coming from the sensor

int bottomSensorMargin = 0; // initialize a bottom margin
int upperSensorMargin = 0; // initialize a upper margin
int timer = 0; // initialize a timer

void setup() {
Serial.begin(9600);

// declare the motor pins as an OUTPUT
pinMode(firstMotorPin, OUTPUT);
pinMode(secondMotorPin, OUTPUT);
}

void loop() {
// read the value from the sensor
sensorValue = analogRead(sensorPin);

// set a bottom and upper margin based on the sensorValue when somebody is lying on the pillow
if (sensorValue >30 ) {
bottomSensorMargin = sensorValue - 5;
upperSensorMargin = sensorValue + 5;
}

// wait
delay(1000);

// increment the timer if the sensorValue is within thresholds
if (sensorValue > bottomSensorMargin && sensorValue < upperSensorMargin) {
timer++;
}

// reset the timer
else {
timer = 0;
}

// start vibrating when the timer hits its threshold
if (timer > 30) {
// turn the motors on
digitalWrite(firstMotorPin, HIGH);
digitalWrite(secondMotorPin, HIGH);
// wait
delay (1000);
// turn the motors off
digitalWrite(firstMotorPin, LOW);
digitalWrite(secondMotorPin, LOW);
// wait
delay (500);
// turn the motors on
digitalWrite(firstMotorPin, HIGH);
digitalWrite(secondMotorPin, HIGH);
// wait
delay (1000);
// turn the motors off
digitalWrite(firstMotorPin, LOW);
digitalWrite(secondMotorPin, LOW);
delay (500);
// turn the motors on
digitalWrite(firstMotorPin, HIGH);
digitalWrite(secondMotorPin, HIGH);
// wait
delay (1000);
// turn the motors off
digitalWrite(firstMotorPin, LOW);
digitalWrite(secondMotorPin, LOW);
}

// print all the values so we know what is going on
Serial.print("sensorValue ");
Serial.println(sensorValue);
Serial.print("bottomSensorMargin ");
Serial.println(bottomSensorMargin);
Serial.print("upperSensorMargin ");
Serial.println(bottomSensorMargin);
Serial.print("timer “);
Serial.println(timer);
Serial.println(” ");
}

Key problem is here:

sensorValue = analogRead(sensorPin);

// set a bottom and upper margin based on the sensorValue when somebody is lying on the pillow
if (sensorValue >30 ) {
bottomSensorMargin = sensorValue - 5;
upperSensorMargin = sensorValue + 5;
}

// wait
delay(1000);

// increment the timer if the sensorValue is within thresholds
if (sensorValue > bottomSensorMargin && sensorValue < upperSensorMargin) {
timer++;
}

This will always be true, because you haven’t refreshed sensorValue since you set the bottom and upper margins.

Also, take a look over the blink-without-delay example - that is probably a better way to do what you’re doing, vs using delay() like that. There are many threads with in-depth explanations of this here if you want more detail

what do you mean by refreshng the sensorValue? (sorry I'm kind of new in this)

void loop() {
// read the value from the sensor
sensorValue = analogRead(sensorPin);

// set a bottom and upper margin based on the sensorValue when somebody is lying on the pillow
if (sensorValue > 45) {
bottomSensorMargin = sensorValue - 5;
upperSensorMargin = sensorValue + 5;
}

// wait
delay(1000);

// increment the timer if the sensorValue is within thresholds
if (sensorValue > bottomSensorMargin && sensorValue < upperSensorMargin) {
timer++;
}
// reset the timer
else if (bottomSensorMargin << sensorValue - 5) {
timer = 0;
}
//reset the timer if value decreases more than 5
else if (upperSensorMargin >> sensorValue + 5) {
timer=0;
}
//reset the timer if value increases more than 5
else {
timer = 0;
}

hey I modified the code but it doesn’t work neither. I tried to describe hose changing margins, they are read by serial monitor but the timer doesn’t reset. please, does anyone mind to help?

your question is ambiguous:

the problem is that the timer should reset itself if the value dicreases/increases more than 5. So, let say, thw timwer goes on:
(here the code should reset the timer, but it goes on whenever value is bigger than 30)

you state that the timer should reset after delta > 5 and later when val > 30

but OK, I did a rewrite of the sketch to remove the delay() so the code would become more responsive.
further made an explicit state for vibrating/not.

have a look and see if it is in the direction you want it?

#define VIBMAX 10

int forceSensorPin = A0;
int firstMotorPin = 13;
int secondMotorPin = 12;
int sensorValue = 0;

int bottomSensorMargin = 0;
int upperSensorMargin = 0;
int timer = 0;

bool vibrating = false;
int vibrCount = 0;
int motorState = LOW;
unsigned long lastMeasure = 0;
unsigned long lastVibrate = 0;
unsigned long lastPrint = 0;

void setup()
{
  Serial.begin(9600);

  pinMode(firstMotorPin, OUTPUT);
  pinMode(secondMotorPin, OUTPUT);

  // SET INITIAL MARGINS AT START
  sensorValue = analogRead(forceSensorPin);
  bottomSensorMargin = sensorValue - 5;
  upperSensorMargin = sensorValue + 5;

}


void loop()
{
  // measure once per second
  if (millis() - lastMeasure >= 1000)
  {
    lastMeasure = millis();

    sensorValue = analogRead(forceSensorPin);
    // increment the timer if the sensorValue is within thresholds
    if ( (sensorValue > bottomSensorMargin) && (sensorValue < upperSensorMargin) )
    {
      timer++;
    }
    else
    {
      timer = 0;
    }
  }

  // start vibrating when the timer hits its threshold
  if (timer > 30)
  {
    vibrating = true;
  }
  

  // HANLDE VIBRATING
  if (millis() - lastVibrate > 250)
  {
    lastVibrate = millis();
    
    if (vibrating)
    {
      digitalWrite(firstMotorPin, motorState);
      digitalWrite(secondMotorPin, motorState);
      motorState = (motorState == HIGH)? LOW:HIGH; // shorthand if ...  else  ...
     
      vibrCount++;
      if (vibrCount == VIBMAX)  // vibrate VIBMAX times
      {
        vibrCount = 0;
        vibrating = false;
      }
    }
  }

  // HANDLE PRINT
  if (millis() - lastPrint >= 1000)
  {
    lastPrint = millis();
    
    Serial.print("sensorValue ");
    Serial.println(sensorValue);
    Serial.print("bottomSensorMargin ");
    Serial.println(bottomSensorMargin);
    Serial.print("upperSensorMargin ");
    Serial.println(bottomSensorMargin);
    Serial.print("timer ");
    Serial.println(timer);
    Serial.println();
  }
}

Hey, the one you sent me reads values and reacts diffrently. From what you wrote- the timer goes on when the pressure is 0, whenever it's bigger, it resets the timer. also the vibration motors work all the time.

I am trying to make it work in the way: the timer can start counting when the pressure value is > 30 and the amplitude is not bigger than +/-5

in the previous code I enclosured, the serial monitor reads the values and margings correctly(e.g. pressure value is 48, the margins are 43 and 53), but the timer doesn't react to those changes (it doesn't reset when the change between pressure value is bigger than +/- 5

This is the serial monitor reading, when the diffrence between sensorValues is more than 5, the timer should restart

else if (bottomSensorMargin << sensorValue - 5) {
timer = 0;
}
//reset the timer if value decreases more than 5
else if (upperSensorMargin >> sensorValue + 5) {
timer=0;
}

<< is something else then < in C/C++

lets get the requirements right

1) if the force sensor reads UNDER 45 there is no one on the cushion? 2) if the force sensor reads ABOVE 45 it should set the upper and lower border? 3) every subsequent read BETWEEN these borders should increment the timer 4) a subsequent read OUTSIDE the borders should reset the timer to zero 5) if timer is above 30 vibrating should start for X seconds.

there are possibly more but req. 1 to 4 are the basis of your project ?

Question: Is there a difference in req 4. between the ABOVE and the UNDER case? I can imagine that if the sensorValue is below 10 or so the system should be reset to the initial condition?

did a quick rewrite from existing snippets…
introducing a state variable - sensorMarginsSet - that monitors if the margins have been set or not.

int forceSensorPin = A0;
int firstMotorPin = 13;
int secondMotorPin = 12;
int sensorValue = 0;

int bottomSensorMargin = 0;
int upperSensorMargin = 0;
int timer = 0;

bool sensorMarginsSet = false;

unsigned long lastMeasure = 0;
unsigned long lastPrint = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("starting v0.1");

  pinMode(firstMotorPin, OUTPUT);
  pinMode(secondMotorPin, OUTPUT);
}


void loop()
{
  // measure once per second
  if (millis() - lastMeasure >= 1000)
  {
    lastMeasure = millis();
    sensorValue = analogRead(forceSensorPin);

    if (sensorMarginsSet == false) // sensorMargins not set
    {
      if (sensorValue > 45)
      {
        bottomSensorMargin = sensorValue - 5;
        upperSensorMargin = sensorValue + 5;
        sensorMarginsSet = true;
      }
    }
    else // sensorMargins set
    {
      if ( (sensorValue > bottomSensorMargin) && (sensorValue < upperSensorMargin) )
      {
        timer++;
      }
      else  // sensor outside the margins => reset timer....
      {
        timer = 0;
        if (sensorValue < 10)  // reset state so a new margin can be set..
        {
          sensorMarginsSet = false;
        }
      }
    }
  }

  if (timer > 30)
  {
    // turn the motors on
    digitalWrite(firstMotorPin, HIGH);
    digitalWrite(secondMotorPin, HIGH);
    // wait
    delay (1000);
    // turn the motors off
    digitalWrite(firstMotorPin, LOW);
    digitalWrite(secondMotorPin, LOW);
    // wait
    delay (500);
    // turn the motors on
    digitalWrite(firstMotorPin, HIGH);
    digitalWrite(secondMotorPin, HIGH);
    // wait
    delay (1000);
    // turn the motors off
    digitalWrite(firstMotorPin, LOW);
    digitalWrite(secondMotorPin, LOW);
    delay (500);
    // turn the motors on
    digitalWrite(firstMotorPin, HIGH);
    digitalWrite(secondMotorPin, HIGH);
    // wait
    delay (1000);
    // turn the motors off
    digitalWrite(firstMotorPin, LOW);
    digitalWrite(secondMotorPin, LOW);
  }

  // HANDLE PRINT
  if (millis() - lastPrint >= 1000)
  {
    lastPrint = millis();

    Serial.print("sensorValue ");
    Serial.println(sensorValue);
    Serial.print("bottomSensorMargin ");
    Serial.println(bottomSensorMargin);
    Serial.print("upperSensorMargin ");
    Serial.println(bottomSensorMargin);
    Serial.print("timer ");
    Serial.println(timer);
    Serial.println();
  }
}