Using previous state to trigger an action

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:

// 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.

[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.

Use some flags to keep track of when something has happened.
You can use the analogRead() values directly, skip the float part:

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;
}

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:

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;
}

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.

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?

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.

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

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;
}

eastyork3:
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.

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.

Arrch:

eastyork3:
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.