From 0b1dbeb2379575af45a0b81dbfe441237a20794a Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Fri, 5 Jul 2019 22:03:49 -0700 Subject: [PATCH] Switched to task scheduler library for faster interrupt processing --- .../Pyr0_Piezo_Sensor_v2.x.x/LightChrono.cpp | 67 ++++++ .../Pyr0_Piezo_Sensor_v2.x.x/LightChrono.h | 72 ++++++ .../Pyr0_Piezo_Sensor_v2.x.x.ino | 95 ++++---- .../Pyr0_Piezo_Sensor_v2.x.x/pP_function.h | 21 +- .../Pyr0_Piezo_Sensor_v2.x.x/pP_functions.h | 223 ------------------ .../Pyr0_Piezo_Sensor_v2.x.x/pP_volatile.h | 7 +- 6 files changed, 200 insertions(+), 285 deletions(-) create mode 100644 firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.cpp create mode 100644 firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.h delete mode 100644 firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_functions.h diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.cpp b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.cpp new file mode 100644 index 0000000..14b719b --- /dev/null +++ b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.cpp @@ -0,0 +1,67 @@ +/* + * Lightweight chronometer class. + * Simple chronometer/stopwatch class that counts the time passed since started. + * + * (c) 2015 Sofian Audry :: info(@)sofianaudry(.)com + * (c) 2015 Thomas O Fredericks :: tof(@)t-o-f(.)info + * + * The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include "LightChrono.h" + +LightChrono::LightChrono() +{ + restart(); +} + +void LightChrono::start() { restart(); } + +void LightChrono::restart() +{ + _startTime = millis(); +} + +LightChrono::chrono_t LightChrono::elapsed() const { + return (millis() - _startTime); +} + +bool LightChrono::hasPassed(LightChrono::chrono_t timeout) const +{ + return (elapsed() >= timeout); +} + +bool LightChrono::hasPassed(LightChrono::chrono_t timeout, bool restartIfPassed) { + if (hasPassed(timeout)) { + if (restartIfPassed) + restart(); + return true; + } + else { + return false; + } +} + + diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.h b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.h new file mode 100644 index 0000000..1060a3b --- /dev/null +++ b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/LightChrono.h @@ -0,0 +1,72 @@ +/* + * Lightweight chronometer class. + * Simple chronometer/stopwatch class that counts the time passed since started. + * + * (c) 2015 Sofian Audry :: info(@)sofianaudry(.)com + * (c) 2015 Thomas O Fredericks :: tof(@)t-o-f(.)info + * + * The MIT License (MIT) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef LIGHT_CHRONO_H_ +#define LIGHT_CHRONO_H_ + +/* + * Example code: + * + * LightChrono myLightChrono; // chronometer automatically starts at creation + * // ... + * myLightChrono.restart(); // you can start (restart) it later + * while (!myLightChrono.hasPassed(2000)) // a 2000 ms loop + * Serial.println(myLightChrono.elapsed()); // current time + * // do something + * // ... + */ +class LightChrono +{ +public: +#if defined(ARDUINO_ARC32_TOOLS) + typedef uint64_t chrono_t; +#else + typedef unsigned long chrono_t; +#endif + +private: + chrono_t _startTime; // keeps track of start time (in milliseconds) + +public: + /// Constructor. + LightChrono(); + + // Starts/restarts the chronometer. + void start(); + void restart(); + + /// Returns the elapsed time since start (in milliseconds). + chrono_t elapsed() const; + + /// Returns true iff elapsed time has passed given timeout. + bool hasPassed(chrono_t timeout) const; + bool hasPassed(chrono_t timeout, bool restartIfPassed); +}; + +#endif + + diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/Pyr0_Piezo_Sensor_v2.x.x.ino b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/Pyr0_Piezo_Sensor_v2.x.x.ino index 79677df..fb1ccaf 100644 --- a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/Pyr0_Piezo_Sensor_v2.x.x.ino +++ b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/Pyr0_Piezo_Sensor_v2.x.x.ino @@ -5,7 +5,7 @@ The sense pin is tied to an interrupt, which is pulled high by internal pullup resistor. When the piezo touches the bed, the amplification circuit will draw the interrupt pin low and the atmega will output a pulse based on the programmed trigger duration - + * PD2 INT0 (Piezo In 'D2') * D7 PCINT23 (Trigger OUT 'D7') * PC0 ADC0 (Voltage Reference Check 'A0') @@ -38,7 +38,7 @@ To change sensor input pullup vRef low threshold: VADJ [float value] To change comparator trigger high threshold: VCOMP [float value] -These commands should be wrapped in this format: +These commands should be wrapped in this format: Examples: @@ -73,6 +73,7 @@ int Hyst = 20; // Hysteresis value for ADC measurements //#define VERBOSE true // Headers, variables, and functions +#include "LightChrono.h" #include "pP_pins.h" #include "pP_volatile.h" #include "pP_function.h" @@ -104,51 +105,51 @@ void setup() { /*------------------------------------------------*/ void loop() { - - // Blink LED's on init - if (BlinkCount > 0) { - BlinkState = !BlinkState; - digitalWrite(ERR_LED, BlinkState); - digitalWrite(TRG_OUT, BlinkState); - delay(LOOP_DUR); - --BlinkCount; - } + if (mainLoop.haspassed(LOOP_DUR)) { + mainLoop.restart(); + // Blink LED's on init + if (BlinkCount > 0) { + BlinkState = !BlinkState; + digitalWrite(ERR_LED, BlinkState); + digitalWrite(TRG_OUT, BlinkState); + --BlinkCount; + } - // Get Serial Input - serialInput(); - - // Set any new parameters from serial input - updateParams(); - - // Set the amplification gain factor - adjustGain(); - - // Check voltage of first and second stages and compare against thresholds - adjustVin(); - VComp = analogRead(VCOMP_SENSE_PIN); - VAdj = analogRead(V_FOLLOW_PIN); - - // Voltage Follower adjustment - if (VLast > Hyst || VLast < -Hyst) { - adjustFollow(); - } - - // Voltage Comparator adjustment - if (VLast > Hyst || VLast < -Hyst) { - adjustComp(); - } + // Get Serial Input + serialInput(); - // Alert the user that auto-calibration is ongoing - calibrateAlert(); - - // Check for error state - checkError(); - - // Reply with status - serialReply(); - - // Sets trigger output state to false after completing loop - delay(LOOP_DUR); - digitalWrite(TRG_OUT, HIGH); - sensorHReading = 0; + // Set any new parameters from serial input + updateParams(); + + // Set the amplification gain factor + adjustGain(); + + // Check voltage of first and second stages and compare against thresholds + adjustVin(); + VComp = analogRead(VCOMP_SENSE_PIN); + VAdj = analogRead(V_FOLLOW_PIN); + + // Voltage Follower adjustment + if (VLast > Hyst || VLast < -Hyst) { + adjustFollow(); + } + + // Voltage Comparator adjustment + if (VLast > Hyst || VLast < -Hyst) { + adjustComp(); + } + + // Alert the user that auto-calibration is ongoing + calibrateAlert(); + + // Check for error state + checkError(); + + // Reply with status + serialReply(); + + // Sets trigger output state to false after completing loop + digitalWrite(TRG_OUT, HIGH); + sensorHReading = 0; + } } diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_function.h b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_function.h index a3533da..a1de50a 100644 --- a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_function.h +++ b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_function.h @@ -34,13 +34,13 @@ long readVcc() { ADMUX = _BV(MUX3) | _BV(MUX2); #else ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); - #endif + #endif delay(2); // Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring - uint8_t low = ADCL; // must read ADCL first - it then locks ADCH + uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; @@ -48,9 +48,9 @@ long readVcc() { result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts } - + /*------------------------------------------------*/ - + void adjustVin() { VOld = Vin; Vin = readVcc(), DEC; @@ -81,16 +81,16 @@ void adjustComp() { analogWrite(VCOMP_PWM, ADJ_COMP); } - + /*------------------------------------------------*/ - + void calibrateAlert() { VLast = VOld - Vin; if (VLast > Hyst || VLast < -Hyst ) { ERR_STATE = 1; } } - + /*------------------------------------------------*/ void adjustGain() { @@ -129,7 +129,7 @@ void adjustGain() { ERR_STATE = 0; } } - + /*------------------------------------------------*/ void checkError () { @@ -142,8 +142,3 @@ void checkError () { digitalWrite(ERR_LED, BlinkState); } } - -/*------------------------------------------------*/ - - -// #endif diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_functions.h b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_functions.h deleted file mode 100644 index 4c14c42..0000000 --- a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_functions.h +++ /dev/null @@ -1,223 +0,0 @@ - -/*------------------------------------------------*/ - -void pulse() { - digitalWrite(TRG_OUT, LOW); - sensorHReading = 1; - delay(TRG_DUR); - digitalWrite(TRG_OUT, HIGH); -} - -/*------------------------------------------------*/ - -void adjustFollow() { - /* Compares diffs of threshold vs read value - if positive, adjusts the follower to within - the range set above*/ - if (diffAdjL > 0) { - ADJ_FOLLOW += diffAdjL / 12; - } - if (diffAdjH > 0) { - ADJ_FOLLOW -= diffAdjH / 12; - } - - // Analog output (PWM) of duty cycle - analogWrite(V_FOL_PWM, ADJ_FOLLOW); -} - -/*------------------------------------------------*/ - -void adjustComp() { - if (diffCompL > 0) { - ADJ_COMP += diffCompL / 12; - } - if (diffCompH > 0) { - ADJ_COMP -= diffCompH / 12; - } - - analogWrite(VCOMP_PWM, ADJ_COMP); -} - -void calibrateAlert() { - if (diffAdjL > 0.0 || diffAdjH > 0.0 || diffCompL > 0.0 || diffCompH > 0.0) { - ERR_STATE = 1; - } -} - -/*------------------------------------------------*/ - -void adjustGain() { - - if (GAIN_FACTOR == 0) { - pinMode(GADJ_R3, INPUT); - pinMode(GADJ_R2, INPUT); - pinMode(GADJ_R1, INPUT); - pinMode(GADJ_R0, INPUT); - ERR_STATE = 0; - } - else if (GAIN_FACTOR > 0) { - pinMode(GADJ_R3, OUTPUT); - digitalWrite(GADJ_R3, LOW); - pinMode(GADJ_R2, INPUT); - pinMode(GADJ_R1, INPUT); - pinMode(GADJ_R0, INPUT); - ERR_STATE = 0; - } - else if (GAIN_FACTOR > 1) { - pinMode(GADJ_R2, OUTPUT); - digitalWrite(GADJ_R2, LOW); - pinMode(GADJ_R1, INPUT); - pinMode(GADJ_R0, INPUT); - ERR_STATE = 0; - } - else if (GAIN_FACTOR > 2) { - pinMode(GADJ_R1, OUTPUT); - digitalWrite(GADJ_R1, LOW); - pinMode(GADJ_R0, INPUT); - ERR_STATE = 0; - } - else if (GAIN_FACTOR > 3) { - pinMode(GADJ_R0, OUTPUT); - digitalWrite(GADJ_R0, LOW); - ERR_STATE = 0; - } -} - -/*------------------------------------------------*/ - -void checkError () { - if (ERR_STATE == 1) { - digitalWrite(ERR_LED, BlinkState); - BlinkState = !BlinkState; - } - else if (ERR_STATE == 0) { - BlinkState = LOW; - digitalWrite(ERR_LED, BlinkState); - } -} - -/*------------------------------------------------*/ - -void parseData() { - - // split the data into its parts - - char * strtokIndx; // this is used by strtok() as an index - - strtokIndx = strtok(inputBuffer,","); // get the first part - the string - strcpy(serialMessageIn, strtokIndx); // copy it to serialMessageIn - - strtokIndx = strtok(NULL, ","); // this continues where the previous call left off - serialInt = atoi(strtokIndx); // convert this part to an integer - - strtokIndx = strtok(NULL, ","); - serialFloat = atof(strtokIndx); // convert this part to a float - -} -/*------------------------------------------------*/ - -void identifyMarkers() { - - char x = Serial.read(); -// char y = Wire.read(); - - if (x == endMarker) { - readInProgress = false; - serialIncoming = true; - inputBuffer[bytesRecvd] = 0; - parseData(); - } - - else if(readInProgress) { - inputBuffer[bytesRecvd] = x; - bytesRecvd ++; - if (bytesRecvd == buffSize) { - bytesRecvd = buffSize - 1; - } - } - - else if (x == startMarker) { - bytesRecvd = 0; - readInProgress = true; - } - #ifdef I2C - if (y == endMarker) { - readInProgress = false; - serialIncoming = true; - inputBuffer[bytesRecvd] = 0; - parseData(); - } - - if(readInProgress) { - inputBuffer[bytesRecvd] = y; - bytesRecvd ++; - if (bytesRecvd == buffSize) { - bytesRecvd = buffSize - 1; - } - } - - if (y == startMarker) { - bytesRecvd = 0; - readInProgress = true; - } - #endif -} - -/*------------------------------------------------*/ - -void updateTrigDuration() { - if (serialInt >= 0) { - TRG_DUR = serialInt; - } -} -/*------------------------------------------------*/ - -void updateGainFactor() { - if (serialInt >= 0) { - GAIN_FACTOR = serialInt; - } -} -/*------------------------------------------------*/ - -void updateVComp() { - if (serialInt >= 0) { - compInt = (serialFloat * 1024) / Vin; - //senseInt = compInt; // syncing these params til #24 is fixed - } -} -/*------------------------------------------------*/ - -void updateVAdj() { - if (serialInt >= 0) { - senseInt = (serialFloat * 1024) / Vin; - //compInt = senseInt; // syncing these params til #24 is fixed - } -} -/*------------------------------------------------*/ - -void updateHysteresis() { - if (serialInt >= 0) { - Hyst = serialInt; - } -} -/*------------------------------------------------*/ - -/*------------------------------------------------*/ - -void updateParams() { - if (strcmp(serialMessageIn, "TRG_D") == 0) { - updateTrigDuration(); - } - else if (strcmp(serialMessageIn, "GAIN_F") == 0) { - updateGainFactor(); - } - else if (strcmp(serialMessageIn, "VCOMP") == 0) { - updateVComp(); - } - else if (strcmp(serialMessageIn, "VADJ") == 0) { - updateVAdj(); - } -} - - -/*------------------------------------------------*/ diff --git a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_volatile.h b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_volatile.h index b9011a9..a5a78f8 100644 --- a/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_volatile.h +++ b/firmware/AVR-Source/Pyr0_Piezo_Sensor_v2.x.x/pP_volatile.h @@ -20,7 +20,7 @@ int diffCompL = VComp - compInt; int diffCompH = compInt - VComp; // Voltage Follower Adjustment parameters -int VAdj = 0; +int VAdj = 0; int diffAdjL = VAdj - senseInt; int diffAdjH = senseInt - VAdj; @@ -40,4 +40,7 @@ char serialMessageIn[buffSize] = {0}; int serialInt = 0; #define LOW 0 -#define HIGH 1 \ No newline at end of file +#define HIGH 1 + +// Task scheduler instances +LightChrono mainLoop;