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