Switched to task scheduler library for faster interrupt processing

This commit is contained in:
pyr0ball 2019-07-05 22:03:49 -07:00
parent 2b5d7e51f4
commit 0b1dbeb237
6 changed files with 200 additions and 285 deletions

View file

@ -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;
}
}

View file

@ -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

View file

@ -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:
<CMD, INT>
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;
}
}

View file

@ -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

View file

@ -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();
}
}
/*------------------------------------------------*/

View file

@ -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
#define HIGH 1
// Task scheduler instances
LightChrono mainLoop;