Pages: [1]   Go Down
Author Topic: Using previous state to trigger an action  (Read 913 times)
0 Members and 1 Guest are viewing this topic.
Toronto
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino beginner.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So here's what I'm attempting:
Have the arduino tweet when a door is opened, and then tweet to tell me it has been closed.

I have a magnetic sensor connected to the door, when the door is closed, it sends 5V to pinA0. When the door is opened, it sends around 1V to pinA0. By defining a threshold, the arduino knows when the voltage drops below that threshold and senses the door has been opened and sends a tweet.

What I need to know is the programming for when the voltage's previous state was 1V and has risen to 5V (the door was open and has now been shut) and then send a tweet.

Here's a snippet if code so far:
Code:
// Front door TWEET setup
  int sensorValue = analogRead(A0); // read the input on analog pin 0 and name it sensorValue
  float voltage = sensorValue * (5.0 / 1023.0); // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  if (voltage < threshold) { // if voltage drops below threshold
  { tweet(dooropen); delay(2000); } // tweet that door is open

I can't just say that if voltage > threshold then tweet since I will be getting tweets every second the door is shut! lol.

Any help would be great, thanks.
« Last Edit: December 22, 2012, 09:45:22 pm by eastyork3 » Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
[code]Simple:

[code]
  static unsigned short sensor_prev=0; //previous sensor value
  unsigned short sensor=analogRead(sensor); //read the sensor now
  if ((sensor > THRESHOLD_CLOSE) && (sensor_prev < THRESHOLD_OPEN)) tweet_now(); //door is closed now
  sensor_prev = sensor; //save the sensor value

The obvious issue with this is what if sensor value falls between _OPEN and _CLOSE? It will never trigger a tweet.

A better approach is this:
[/code]
  static unsigned char tweet=0; //0=not yet tweeted. 1=tweet
  unsigned short sensor=analogRead(sensor); //read the sensor now
  if ((sensor > THRESHOLD_CLOSE) && (tweet==0)) {
    tweet_now(); //door is closed now and haven't tweeted yet
    tweet = 1; //set tweet
  } else if (sensor < THRESHOLD_OPEN) tweet = 0; //reset tweet
[/code]

Adjust the two thresholds to your liking. No need to do anything in floating point math land.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 27372
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Use some flags to keep track of when something has happened.
You can use the analogRead() values directly, skip the float part:
Code:
if (analogRead(pin)<200 && lowvoltage_flag ==0){
lowvoltage_flag = 1;
highvoltage_flag = 0;
}

if(analogRead(pin)>800 && highvoltage_flag == 0){
highvoltage_flag  = 1;
lowvoltage_flag = 0;
}

Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 644
Posts: 50452
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What you have is a classic edge detection case. You want to know when the door has transitioned from open to closed or closed to open.

The only way to detect that is to keep track of the previous value.

CrossRoads' suggestion to get rid of the conversion to voltage and just use the analogRead() value is good, but the flag idea is far too complicated. At most, one flag is needed.

Simply keep track of the current and previous states, like so:

Code:
int currState;
int prevState = 0;

void loop()
{
   int currValue = analogRead(thePin);
   if(currValue > threshold)
      currState = 1;
   else
      currState = 0;

   if(currState != prevState)
   {
      // Hey, the door moved
      if(currState == 1)
      {
         // Door is now open
      }
      else
      {
         // Door is now closed
      }
   }
   prevState = currState;
}
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 27372
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I was thinking there would be some indeterminate zone between open & close.  With just 1 switch that doesn't really happen - it's either closed, or it's not.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Toronto
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino beginner.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the responses guy, I really appreciate it.

I am a little confused with the code.

I was understanding PaulS, but then got lost. Bare with me please:

From your code I read if the current value is greater than the threshold, the door is closed and call that state 1, if the current value is less than the threshold, the door is open and call that state 0. All good so far.

Here's where I get confused:

if(currState != prevState)
   {
      // Hey, the door moved

isnt this line just saying that if the current state is not 0 (open) then the door is shut?

     
« Last Edit: December 23, 2012, 11:17:56 pm by eastyork3 » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 644
Posts: 50452
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
isnt this line just saying that if the current state is not 0 (open) then the door is shut?
On the first pass through loop, yes. You need to set the initial value of prevState to reflect the state that the door will be in when the Arduino starts.

On subsequent passes, because of the prevState = currState assignment later on, the test is for whether the door is in the same state as it was on the last pass through loop.
Logged

Toronto
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino beginner.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gotcha, that makes total sense. How does this look?

Code:
void loop() {
 
// Front door TWEET setup
  int currValue = analogRead(A0);
  if (currValue > threshold)  // if voltage is above threshold (door is closed)
      currState = 1; // call that state 1 (door closed)
  else
      currState = 0; // otherwise call it state 0 (door open)
 
  if (currState != prevState)  // if state is not 0 (door closed)
{
  if (currState == 1)

  { tweet(dooropen); delay(2000); } // tweet that door is open
  digitalWrite(led, HIGH); //turn LED on
} else
  { tweet(doorshut); delay(2000); } // tweet that door is shut
  digitalWrite(led, LOW); //turn LED off
}
  prevState = currState;
}
Logged

California
Offline Offline
Faraday Member
**
Karma: 92
Posts: 3442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gotcha, that makes total sense. How does this look?
Like it will grow into a nightmare.

Put each curly brace on it's own line and use Tools > Auto Format to fix the indentation.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 644
Posts: 50452
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Like it will grow into a nightmare.
Also, the values in currState and prevState are HIGH or LOW, not 0 or 1. Yes, I know that they are the same values, but HIGH and LOW have inherent meaning. 0 and 1 do not.
Logged

Toronto
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino beginner.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gotcha, that makes total sense. How does this look?
Like it will grow into a nightmare.

Put each curly brace on it's own line and use Tools > Auto Format to fix the indentation.

Will do, it does need some cleaning up.

PaulS - didn't know they were High and LOW, I was just following your previous code, which helped a lot. Thanks guys.
Logged

Pages: [1]   Go Up
Jump to: