I have spent ages looking at the forum and I am sure the answer is there...somewhere.
I think I have a very simple problem but I just can not work it out.
I am building a robot that I want to have a pir sensor activate, then other sensors run for various things. I can get it all to work except I want to have the pir trigger the active state and then keep that state active until no movement has occurred for a period of time. Is this interupts, or boolean or what?
Thanks for any help.
I just can't see it. My brain is so toasted it makes no sense as to how I am meant to put that in my code. Please be kind, I am a humble chemist after all.
ibdunne:
I just can't see it. My brain is so toasted it makes no sense as to how I am meant to put that in my code. Please be kind, I am a humble chemist after all.
Do you understand how it works? Did you play with the code to see what happens when you change things?
You have a pen and paper to write down times and a stopwatch that counts seconds for you, how would you do it?
How would YOU execute some chemical process for some defined period of time? When you start, you note the time. You start doing stuff. Periodically, you see if it is time to stop. If it is, you do.
The millis() function is the Arduino equivalent of your watch. Unsigned long variables are the equivalent to the scratch paper you wrote the start time down on. Each execution through loop() (or through your looping function) is "periodically". Starting and stopping should be fairly obvious.
Without knowing what "the active state" means, we really can't offer more help.
I have tried to simplify my problem in a hope of understanding what I am doing wrong. I have tried to get a pir to fire a led flashing and sound a tone. The flashing should go on for 10 seconds but it lasts for 4 or 5. I am sure my mistake will be obvious to those more experienced than me. Is it my placing of backets? Timing or what?
/* Pir to trigger led flash and sound tone
for a time after the pir is activated
*/
const int ledPin = 12; // the number of the LED pin
const int pirPin = A5; //pir pin
long previousPirTriggerMillis = 0; // will store last time pir was triggered
int pirState = LOW;
long liveTime = 10000; // interval for which pir state to stay on when activated
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
pinMode(pirPin, INPUT);
}
void loop()
{
if(digitalRead(pirPin)==HIGH)//if pir is activated
flashntone(); //flash and tone function
unsigned long currentMillis = millis();//saves time as current time
if(currentMillis - previousPirTriggerMillis < liveTime) //if time since last trigger
//is less than liveTime
pirState = HIGH; //keep pirState High
previousPirTriggerMillis = currentMillis;
{if (currentMillis - previousPirTriggerMillis> liveTime)
pirState = LOW;
Serial.print (pirState);
Serial.println ();
}
}
void flashntone()
{
digitalWrite(ledPin, HIGH);
delay (500);
tone (8,440);
digitalWrite(ledPin, LOW);
delay (500);
noTone (8);
}
You may have added some blink without delay code, but it's doing absolutely nothing for your program. This entire portion could be removed and not affect the functionailty:
unsigned long currentMillis = millis();//saves time as current time
if(currentMillis - previousPirTriggerMillis < liveTime) //if time since last trigger
//is less than liveTime
pirState = HIGH; //keep pirState High
previousPirTriggerMillis = currentMillis;
{if (currentMillis - previousPirTriggerMillis> liveTime)
pirState = LOW;
Why are you setting the state of an input variable? pirState should only be assigned using a digitalRead(), or it should be renamed because as it is, it makes no sense. Explain what you are expecting this code to do.
Fundamentally, for this bit, the best model for what I want is a pir controlled security light. If there is movement detected it goes on for a set time, at the end of that time, if no more movement, no more light, if movement is detected in that time, it stays on. I want the pir to wake the arduino so that it will be able to pay attention to other sensors and when movement has stopped it goes back to sleep.
ibdunne:
Fundamentally, for this bit, the best model for what I want is a pir controlled security light. If there is movement detected it goes on for a set time, at the end of that time, if no more movement, no more light, if movement is detected in that time, it stays on. I want the pir to wake the arduino so that it will be able to pay attention to other sensors and when movement has stopped it goes back to sleep.
Hardware is so much easier.
I meant explain what you you are expecting out of that portion of code that I quoted.
What you're looking to do requires just a few things:
(1) Record the time at which the transition occurred from "no movement detected" to "movement detected". This is typically done by comparing the last read value of a sensor with it's current. "Record" means use the result from millis() to assign a value to a variable.
(2) Keep checking the time you recorded against the current time. If it's over a certain value, do some other action such as turning a light off.
(3) If you are looking at doing something in between (1) and (2), either use the else portion of the conditional in (2), or use a state variable.
(4) Don't try and code it all at once; that only leads to frustration, especially if you are not very experienced with programming logic.
I want that section of code would do your points one and two. Why doesn't it?
I am trying to break my lack of understanding down into nice byte size pieces but these things are very binary, either work or not!!
Let's clean it up a bit so it will be easier to see the error:
unsigned long currentMillis = millis();//saves time as current time
if(currentMillis - previousPirTriggerMillis < liveTime) //if time since last trigger
pirState = HIGH; //keep pirState High
previousPirTriggerMillis = currentMillis;
if (currentMillis - previousPirTriggerMillis> liveTime)
pirState = LOW;
You never do a digital read to check the state of the PIR, nor do you keep track of the last state that you read, so (1) is out of the question.
For (2), look at the middle assignment and the last if. Can you see why that if will NEVER fire?
You give variables meaningful name: pirSesnorPin, pirSensorState, lastPirSensorState, ledPin, ledState, etc...
how to summon them and get them to do anything
You don't summon variables; you either declare them:
int pirSensorPin;
Assign something to them:
pirSensorPin = 2;
or use their values in an experession or function call:
pirSensorState = digitalRead(pirSensorPin);
is it something to do with sacrificing chickens?
Now you're just being facetious.
It seems like it might be prudent for you to go through some of the examples first so that you can get a baseline understanding of programming concepts such as variables, assignments, selections and iterations.
I was trying to be humorous. There seems to be a degree of dark arts about this, at least to the uninitiated.
I meant you are being mean by directing me back to your previous reply, when I don't understand how to do point 1 or 2,
(1) Record the time at which the transition occurred from "no movement detected" to "movement detected". This is typically done by comparing the last read value of a sensor with it's current. "Record" means use the result from millis() to assign a value to a variable.
(2) Keep checking the time you recorded against the current time. If it's over a certain value, do some other action such as turning a light off.
I thought I had told it to do that in the code but obviously not.
Telling me it is wrong but not why or what to do is not an effective teaching trick. But telling people the same thing in several diferent ways is very useful
I can get the machine to do all sorts of things but not this. Where do you suggest I start?
I meant you are being mean by directing me back to your previous reply, when I don't understand how to do point 1 or 2,
I wouldn't expect you to after only an hour, and most of it was probably spent posting and waiting for replies instead of trying to figure it out. Short of writing the code for you, I don't know what else I can do for you; some of this stuff you just have to actually play around with to figure out.
ibdunne:
Where do you suggest I start?
For (1), take a look at the StateChangeDetection example under "02. Digital" in the Arduino IDE. Get it to print out the current time on the state changes for the PIR sensor. That's where you should be starting.
So think of it as hardware. You'd use a retriggerable monstable timer, right? It has a "trigger" input, and a "Q" output. When you trigger it, the Q output goes "true" for some time, and then goes false again. So what does it take to do that in software? Rather than have an RC circuit gradually charging or discharging a cap until it reaches a certain voltage level, software will monitor the current time (via millis()) until that reaches a certain value.
static const mono_time = 5000; // Out "time constant" is 5000 milliseconds. This is "built in."
/*
* Implement a "monostable" timer. If "trigger" is true, set the end time.
* Regardless of "trigger", return true if the timeout has not expired.
*/
boolean monostable(boolean trigger)
{
static unsigned long start_time; // The millis() time when we were triggered
unsigned long elapsed_time;
if (trigger) {
/* We received a trigger. Record the time. */
start_time = millis();
}
/* Now calculate how long it's been since the last trigger */
elapsed_time = millis() - start_time;
/* if the elapsed time is smaller than our desired timer value, our
* output should be true. */
if (elapsed_time < mono_time) {
return true;
}
/* Otherwise our output is false */
return false;
}
Then in your main code, if you see PIR activity, you call "monostable(true)"
and later, you check the value by calling "monostable(false)" to see if your light should turn off:
void loop()
{
if (pir_active()) { // motion detected?
light_on(); // turn on the light
monostable(true); // and fire our monostable.
}
// (other stuff ?)
if (monostable(false) == false) { // check if the monostable has expired
light_off(); // if so, turn the light off again.
}
// more other stuff ?
}