I'm calculating the acceleration magnitude vector from an accelerometer inside a thick PU mat. When the mat is hit, depending on the value I obtain, only one of two LEDs, later more, shall light up briefly. However, because the low(er) threshold(s) is(are) inevitably always crossed first, stronger hits mean both(all) LEDs light up, not only the single one that corresponds to the highest threshold crossed at the time. I hope the image explains the issue. Somehow, I would need to look ahead if, when a lower threshold is crossed, a higher one may be crossed right after, maybe an even higher one. How must I change/augment the code?
mAV = sqrt(ax * ax + ay * ay + az * az) - valueShift;
if (mAV < 0)
{
mAV = 0;
}
mAVEMA = (alphaEMA * mAV) + ((1 - alphaEMA) * mAVEMA);
Serial.print("mAVEMA:"); Serial.println(mAVEMA);
if (mAVEMA >= thresholdC && previousmAVEMA < thresholdC)
{
digitalWrite(pinLEDR, HIGH);
timeLEDROn = timeNow;
}
if (mAVEMA >= thresholdB && previousmAVEMA < thresholdB)
{
digitalWrite(pinLEDY, HIGH);
timeLEDYOn = timeNow;
}
previousmAVEMA = mAVEMA;
if (digitalRead(pinLEDY) == HIGH && timeNow - timeLEDYOn >= timeLEDOn)
{
digitalWrite(pinLEDY, LOW);
}
if (digitalRead(pinLEDR) == HIGH && timeNow - timeLEDROn >= timeLEDOn)
{
digitalWrite(pinLEDR, LOW);
}
Edit: Getting closer to the desired behaviour https://wokwi.com/projects/406459026144282625
const int pinAccel = A0; // simulate acceleration magnitude vector
const int pinsLED[] = {11, 12, 13}; // yellow, orange, red
const int threshold0 = 300;
const int threshold1 = 600;
const int threshold2 = 900;
const unsigned long timeSearch = 200;
const unsigned long timeLEDsOn = 500;
int mAVEMA = 0;
int active = -1;
unsigned long timersLED[] = {0, 0, 0};
void setup()
{
Serial.begin(9600);
for (byte i = 0; i < 3; i++)
{
pinMode(pinsLED[i], OUTPUT);
}
}
void loop()
{
unsigned long timeNow = millis();
mAVEMA = analogRead(pinAccel);
int threshold = checkThresholds(mAVEMA);
// only on rising signal
if (threshold == 0)
{
unsigned long timerStart = millis();
active = 0;
timersLED[active] = millis();
while (millis() - timerStart < timeSearch) // timeSearch user adjustable?
{
mAVEMA = analogRead(pinAccel);
threshold = checkThresholds(mAVEMA);
if (threshold == 1)
{
active = 1;
timersLED[active] = millis();
}
if (threshold == 2) // reset to 0 once one of the three LEDs was lit
{
active = 2;
timersLED[active] = millis();
}
}
digitalWrite(pinsLED[active], HIGH);
}
if (timeNow - timersLED[active] >= timeLEDsOn)
{
digitalWrite(pinsLED[active], LOW);
}
delay(10); // Only for serial monitor/plotter
}
int checkThresholds(int accel) // later floats for real accelerometer!
{
if (mAVEMA >= threshold2) return 2;
if (mAVEMA >= threshold1) return 1;
if (mAVEMA >= threshold0) return 0;
return -1;
}