I hardly know how to describe what I'm needing, and maybe there's some examples already, but I haven't found any.
This code kinda shows what I need to do. I don't know how else to word it. The commented out part tells what I need, but I'm at a loss.
boolean CheckPosNeg(int Val) {
timeRange = 1000; //within this time range
changeCount = 3; //number of changes to trigger flag
//if Val has changed from NEG to POS more than {changeCount}
//times in the past {timeRange} return TRUE
}
Define an array that contains time stamp values. Every time the signal changes (NEG to POS) save the current time in the array, and check whether there have been the required number of changes in the given time span.
This sounds like what I am envisioning, but I'm afraid it's over my head. I worked on it an hour, and was more confused than when I started. I'll give it another go another day.
Also, the input value it a constrained reading of an IMU. -30 to +30 are it's limits
I worked on it an hour, and was more confused than when I started. I'll give it another go another day.
Break the problem into parts. Can you detect when the sign changes? Can you determine when that happened? Can you determine the difference between when the event happened and a reference time (now, for example)? Don't try to solve the whole problem at once.
This is what I've got so far. Is it a good way to start?
boolean CheckPosNeg(int Val) {
if (Val == 0) return false; //when it's 0, it can be ignored
int timeRange = 1000; //within this time range
int changeCount = 3; //number of changes to trigger flag
static int lastVal; //the last value passed
static int countArray(changeCount); //I need to keep track of this many changes
static unsigned long timeArray(changeCount);//this will hold a time stamp for each change
if (Val > 0 && lastVal < 0) { //a change
…UGH!
}
}
Yeah that's looking OK, what units are time being measured in? I take it that the 1000 in
int timeRange = 1000;
is milliseconds?
If the goal is to know when more than 3 changes have happened, then the array may need to be timeArray(changeCount+1);
I'm not sure countArray is needed. What is needed is an index to timeArray, which will point to the most recent value stored.
timeArray conceptually needs to work in a circle ... a ring buffer. Another way to do it is to shift the whole array each time a new element is stored. This may be conceptually easier to envision, but is not as efficient, but for an array of four elements it probably doesn't make much difference.
So the last line, the if statement, is good. Next step, if the condition is true, save Val to lastVal and save the current time to timeArray and increment the index for next time.
Sorry for the stream of consciousness, just trying to give some ideas to chew on
Thanks. I think I got a loop set up. But I don't think it's working, but I must be close.
boolean CheckPosNeg(int Val) {
if (Val == 0) return false; //when it's 0, it can be ignored
int timeRange = 1000; //within this time range
const int changeCount = 3; //number of changes to trigger flag
static unsigned long lastVal; //the last value passed
static int countArray(changeCount); //I need to keep track of this many changes
static unsigned long timeArray[changeCount + 1];//this will hold a time stamp for each change {1,2,3}
if (Val > 0 && lastVal < 0) { //a change
for (int i=changeCount; i > 0; i--){
timeArray[i] = timeArray[i-1]; //move all the value up the line
}
timeArray[0] = millis();
lastVal = Val;
//now see if it's been longer than [timeRange] for the least recent timestamp
if (millis() - timeArray[changeCount] > timeRange) {
return true; //send up red sparks!
}
else return false; //all is well
}
}
...try moving that outside the if. Need to always preserve the last value no matter what, correct? Then take action (the if) only if the proper condition is met.
I'm a little puzzled as to why a zero can always be ignored.
The other thing to think through (and I haven't) is the boundary conditions at start-up, i.e. until timeArray is full of legit values, will everything work properly?
boolean CheckPosNeg(int Val) {
//return false;
const int ControlState = -2;
if (Val == ControlState) return false; //when it's 0, it can be ignored
int timeRange = 2000; //within this time range
const int changeCount = 3; //number of changes to trigger flag
static int lastVal; //the last value passed
static int countArray(changeCount); //I need to keep track of this many changes
static unsigned long timeArray[changeCount + 1];//this will hold a time stamp for each change {1,2,3}
//Serial.println(Val);
if (Val > ControlState) {
if(lastVal < ControlState) { //a change
for (int i=changeCount; i > 0; i--){
timeArray[i] = timeArray[i-1]; //move all the value up the line
}
timeArray[0] = millis(); //put the current one at the beginning
lastVal = Val; //update the lastVal
//now see if it's been longer than [timeRange] for the least recent timestamp
//Serial.println(timeArray[changeCount]);
if (millis() - timeArray[changeCount] < timeRange) {
Serial.println("Oscilate!");
return true; //send up red sparks!
}
else return false; //all is well
}
}
lastVal = Val;
return false;
}
You could use my statemachine library to keep track of polarities. It gives a little cleaner code.
The libray can be found here: Arduino Playground - HomePage
This seems to be working:
#include <SM.h>
SM PolCheck(Undet);//Polarity is unknown on first call
int _val;//must be to global to be reachable from states
unsigned long TimeStamp[4];
unsigned TimeIdx;
void setup(){}//setup()
void loop(){}//loop()
boolean CheckPosNeg(int Val){
_val = Val;//must be global to be reachable from SM
EXEC(PolCheck);//call apropiate state function
return millis()-TimeStamp[TimeIdx]<1000;
}//CheckPosNeg()
State Undet(){//first time call, polarity is unknown
//determine polarity
if(_val <0) PolCheck.Set(Neg); else PolCheck.Set(Pos);
TimeSet();//make timestamp
}//Undet[]
void TimeSet(){
TimeStamp[TimeIdx++] = millis();
TimeIdx %= 4;
}//TimeSet()
State Pos(){
if(_val < 0){//_val is negative, make timestamp and change state
PolCheck.Set(Neg);
TimeSet();
}//if _val is negative
}//pos()
State Neg(){
if(_val >= 0){//_val is positive, make timestamp and change state
PolCheck.Set(Pos);
TimeSet();
}//if _val is positive
}//Neg()