From cc58cb5f3b20c8e4bd7899b9e3bdeb757a90dc83 Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Sat, 10 Jul 2021 13:58:37 -0400 Subject: [PATCH 1/6] Actuator Base Class created helper header containing shared definitions --- Actuator.cpp | 39 +++++++++++++++++++++++++++++++++++++++ Actuator.h | 32 ++++++++++++++++++++++++++++++++ Base.h | 32 ++++++++++++++++++++++++++++++++ Sensor.h | 40 +--------------------------------------- 4 files changed, 104 insertions(+), 39 deletions(-) create mode 100644 Actuator.cpp create mode 100644 Actuator.h create mode 100644 Base.h diff --git a/Actuator.cpp b/Actuator.cpp new file mode 100644 index 0000000..f4a6b89 --- /dev/null +++ b/Actuator.cpp @@ -0,0 +1,39 @@ +#include "Arduino.h" +#include "Actuator.h" + +Actuator::Actuator(actuators_t actuator, arduino_t arduino, float nulltarget){ + this->actuator = actuator; + this->arduino = arduino; + state.error = ERR_NONE; + state.debug = DS_DISABLED; + state.target = this->nulltarget = nulltarget; // Default start target +} + +ActuatorState* Actuator::update(){ + if(state.error < ERR_FAIL && state.debug >= DS_INIT){ + state.error = set(state.target); + + switch(state.error){ + case ERR_NONE: //Success! + state.debug = DS_NEWREAD; + break; + case ERR_WARN: //Read didn't go as planned, non-fatal + // DO NOT UPDATE STATE VALUES + break; + case ERR_FAIL: //Read failed catastrophically + state.debug = DS_DISABLED; + break; + } + } + return &state; +} + +ActuatorState* Actuator::begin(){ + state.error = init(); + if(state.error > ERR_NONE){ + state.debug = DS_DISABLED; + } else { + state.debug = DS_INIT; + } + return &state; +} \ No newline at end of file diff --git a/Actuator.h b/Actuator.h new file mode 100644 index 0000000..cf7385e --- /dev/null +++ b/Actuator.h @@ -0,0 +1,32 @@ +#ifndef Actuator_H +#define Actuator_H + +#include "Base.h" + +// Actuator identifiers +typedef enum actuators_t { + A_BRAKES, + A_INVERTER +} actuators_t; + +typedef struct ActuatorState { + errorlevel_t error; + debuglevel_t debug; + float target; +} ActuatorState; + +class Actuator{ + protected: + virtual errorlevel_t set(float target) = 0; + virtual errorlevel_t init() = 0; + ActuatorState state; + public: + arduino_t arduino; + actuators_t actuator; + float nulltarget; // what should we default to in case of failure? + Actuator(actuators_t actuator, arduino_t arduino, float nulltarget); + ActuatorState* update(); + ActuatorState* begin(); +}; + +#endif \ No newline at end of file diff --git a/Base.h b/Base.h new file mode 100644 index 0000000..0d1b4fe --- /dev/null +++ b/Base.h @@ -0,0 +1,32 @@ +#ifndef BASE_H +#define BASE_H + +#include "Arduino.h" +#include "stdlib.h" + +// Arduino identifiers +typedef enum arduino_t { + ARDUINO_ONE, + ARDUINO_TWO, + ARDUINO_THREE +} arduino_t; + +// Degree of error occurred +// TODO: Maybe add more specific codes? (i.e. hardware/wiring fail, comms/protocol fail, etc.) +typedef enum errorlevel_t { + ERR_NONE, + ERR_WARN, + ERR_FAIL //NOTE: Implies debug level 'DISABLED' +} errorlevel_t; + +// General state - On fail != 0, what state did it last complete successfully? +typedef enum debuglevel_t { + //NOTE: The various debug states imply the value of cache.state.data as follows: + DS_DISABLED, //NULL + DS_INIT, //NULL + // DS_CALIBRATING, //NULL if first time, otherwise unknown + DS_WAITING, //NOT NULL, age > 0 + DS_NEWREAD //NOT NULL, age == 0 +} debuglevel_t; + +#endif \ No newline at end of file diff --git a/Sensor.h b/Sensor.h index 4885e95..0d7feeb 100644 --- a/Sensor.h +++ b/Sensor.h @@ -1,8 +1,7 @@ #ifndef Sensor_H #define Sensor_H -#include "Arduino.h" -#include "stdlib.h" +#include "Base.h" // Sensor identifiers typedef enum sensors_t { @@ -17,43 +16,6 @@ typedef enum sensors_t { S_CANBUS } sensors_t; -// Arduino identifiers -typedef enum arduino_t { - ARDUINO_ONE, - ARDUINO_TWO, - ARDUINO_THREE -} arduino_t; - -// Degree of error occurred -// TODO: Maybe add more specific codes? (i.e. hardware/wiring fail, comms/protocol fail, etc.) -typedef enum errorlevel_t { - ERR_NONE, - ERR_WARN, - ERR_FAIL //NOTE: Implies debug level 'DISABLED' -} errorlevel_t; - -// General state - On fail != 0, what state did it last complete successfully? -typedef enum debuglevel_t { - //NOTE: The various debug states imply the value of cache.state.data as follows: - DS_DISABLED, //NULL - DS_INIT, //NULL - // DS_CALIBRATING, //NULL if first time, otherwise unknown - DS_WAITING, //NOT NULL, age > 0 - DS_NEWREAD //NOT NULL, age == 0 -} debuglevel_t; - -// Unimplemented for now... -// typedef struct SensorError { -// errorlevel_t error, -// char* msg, -// uint8_t msglen -// } SensorError; -// typedef struct SensorDebug { -// debuglevel_t debug, -// char* msg, -// uint8_t msglen -// } SensorError; - // Single datapoint typedef struct t_datum { float data; From 7f3203a78450a79fab2a8590ccbc1ed142a35fa7 Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Sat, 10 Jul 2021 14:00:06 -0400 Subject: [PATCH 2/6] Refactored Debug, Error States --- Actuator.cpp | 2 +- Base.h | 2 +- Sensor.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Actuator.cpp b/Actuator.cpp index f4a6b89..a505f12 100644 --- a/Actuator.cpp +++ b/Actuator.cpp @@ -15,7 +15,7 @@ ActuatorState* Actuator::update(){ switch(state.error){ case ERR_NONE: //Success! - state.debug = DS_NEWREAD; + state.debug = DS_SUCCESS; break; case ERR_WARN: //Read didn't go as planned, non-fatal // DO NOT UPDATE STATE VALUES diff --git a/Base.h b/Base.h index 0d1b4fe..623ae26 100644 --- a/Base.h +++ b/Base.h @@ -26,7 +26,7 @@ typedef enum debuglevel_t { DS_INIT, //NULL // DS_CALIBRATING, //NULL if first time, otherwise unknown DS_WAITING, //NOT NULL, age > 0 - DS_NEWREAD //NOT NULL, age == 0 + DS_SUCCESS //NOT NULL, age == 0 } debuglevel_t; #endif \ No newline at end of file diff --git a/Sensor.cpp b/Sensor.cpp index 9c0f9ad..452c41e 100644 --- a/Sensor.cpp +++ b/Sensor.cpp @@ -59,7 +59,7 @@ SensorState* Sensor::update(){ switch(state.error){ case ERR_NONE: //Success! - state.debug = DS_NEWREAD; + state.debug = DS_SUCCESS; state.timestamp = lastread; free(state.data); state.data = buffer; From 13ae3fdf804178d1981be36ed3d1389ec4e64b4b Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Sat, 10 Jul 2021 14:14:47 -0400 Subject: [PATCH 3/6] Added Actuators to Template --- Template.ino | 61 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/Template.ino b/Template.ino index 5aa5fc3..8f4eaea 100644 --- a/Template.ino +++ b/Template.ino @@ -1,13 +1,20 @@ // Headers for each sensor type #include "YourSensorClass.h" //... +#include "YourActuatorClass.h" +#include "Base.h" #include "Sensor.h" +#include "Actuator.h" #define NUMSENSORS 1 //Or however many +#define NUMACTUATORS 1 //Or however many #define BAUDRATE 115200 +#define THISARDUINO ARDUINO_ONE // Objects for each sensor -SensorClass sensor(/*Arguments, arduino enum*/); +SensorClass sensor(/*Arguments, ...*/, THISARDUINO); +//... +ActuatorClass actuator(/*Arguments, arduino enum*/, THISARDUINO); //... Sensor* sensors[NUMSENSORS] = { @@ -16,6 +23,12 @@ Sensor* sensors[NUMSENSORS] = { //... }; +Actuator* actuators[NUMACTUATORS] = { + // Entry for each sensor object + &actuator, + //... +}; + // !#!#!#!--- EVERYTHING AFTER HERE DOES NOT NEED TO BE CHANGED FOR SENSOR IMPLEMENTATION ---!#!#!#! void setup(){ @@ -37,8 +50,34 @@ void setup(){ } success &= _success; } + for(int i = 0; i < NUMACTUATORS; i++){ + ActuatorState* state = actuators[i]->begin(); + // Print/send sensor post-setup state data here. For example: + bool _success = (state->error == ERR_NONE); + if(_success){ + Serial.print("Actuator "); + Serial.print(actuators[i]->actuator); + Serial.print(" initialized. "); + + state = actuators[i]->update(); + _success = (state->error == ERR_NONE); + if(_success){ + Serial.print("Set to "); + Serial.println(state->target); + } else { + Serial.print("\nActuator "); + Serial.print(sensors[i]->sensor); + Serial.println(" failed to set!"); + } + } else { + Serial.print("Actuator "); + Serial.print(sensors[i]->sensor); + Serial.println(" failed to initialize!"); + } + success &= _success; + } if(!success){ - Serial.println("POST failed on one or more sensors, freezing..."); + Serial.println("POST failed on one or more devices, freezing..."); while(1){delay(1000);} } } @@ -48,7 +87,7 @@ void loop(){ SensorState* state = sensors[i]->update(); // Print/send sensor post-setup state data here. For example: bool _success = (state->error == ERR_NONE); - bool _new = (state->debug == DS_NEWREAD); + bool _new = (state->debug == DS_SUCCESS); if(_success && _new){ Serial.print("Sensor "); Serial.print(sensors[i]->sensor); @@ -66,4 +105,20 @@ void loop(){ // TODO: Recover failed sensor? } } + for(int i = 0; i < NUMACTUATORS; i++){ + ActuatorState* state = actuators[i]->update(); + + bool _success = (state->error == ERR_NONE) && (state->debug == DS_SUCCESS); + if(_success){ + Serial.print("Actuator "); + Serial.print(actuators[i]->actuator); + Serial.print(" set success: "); + Serial.println(state->target); + } else { + Serial.print("Actuator "); + Serial.print(actuators[i]->actuator); + Serial.println(" failed to set!"); + // TODO: Recover failed sensor? + } + } } \ No newline at end of file From 5b4537d7f694fe73c5ca263f6b2773f76c1dff08 Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Mon, 12 Jul 2021 00:05:21 -0400 Subject: [PATCH 4/6] Braking Solenoid Class refactored nulltarget -> failtarget (more explicit about "failsafe" mechanism) --- Actuator.cpp | 9 ++-- Actuator.h | 4 +- Brakes/README.md | 0 Brakes/src/Brakes.cpp | 16 +++++++ Brakes/src/Brakes.h | 16 +++++++ Brakes/tests/Brakes_test.ino | 83 ++++++++++++++++++++++++++++++++++++ 6 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 Brakes/README.md create mode 100644 Brakes/src/Brakes.cpp create mode 100644 Brakes/src/Brakes.h create mode 100644 Brakes/tests/Brakes_test.ino diff --git a/Actuator.cpp b/Actuator.cpp index a505f12..d667116 100644 --- a/Actuator.cpp +++ b/Actuator.cpp @@ -1,12 +1,12 @@ #include "Arduino.h" #include "Actuator.h" -Actuator::Actuator(actuators_t actuator, arduino_t arduino, float nulltarget){ +Actuator::Actuator(actuators_t actuator, arduino_t arduino, float failtarget){ this->actuator = actuator; this->arduino = arduino; state.error = ERR_NONE; state.debug = DS_DISABLED; - state.target = this->nulltarget = nulltarget; // Default start target + state.target = this->failtarget = failtarget; // Default start target } ActuatorState* Actuator::update(){ @@ -17,11 +17,12 @@ ActuatorState* Actuator::update(){ case ERR_NONE: //Success! state.debug = DS_SUCCESS; break; - case ERR_WARN: //Read didn't go as planned, non-fatal + case ERR_WARN: //Set didn't go as planned, non-fatal // DO NOT UPDATE STATE VALUES break; - case ERR_FAIL: //Read failed catastrophically + case ERR_FAIL: //Set failed catastrophically state.debug = DS_DISABLED; + set(failtarget); break; } } diff --git a/Actuator.h b/Actuator.h index cf7385e..37d7675 100644 --- a/Actuator.h +++ b/Actuator.h @@ -23,8 +23,8 @@ class Actuator{ public: arduino_t arduino; actuators_t actuator; - float nulltarget; // what should we default to in case of failure? - Actuator(actuators_t actuator, arduino_t arduino, float nulltarget); + float failtarget; // what should we default to in case of failure? + Actuator(actuators_t actuator, arduino_t arduino, float failtarget); ActuatorState* update(); ActuatorState* begin(); }; diff --git a/Brakes/README.md b/Brakes/README.md new file mode 100644 index 0000000..e69de29 diff --git a/Brakes/src/Brakes.cpp b/Brakes/src/Brakes.cpp new file mode 100644 index 0000000..1e1c299 --- /dev/null +++ b/Brakes/src/Brakes.cpp @@ -0,0 +1,16 @@ +#include "Brakes.h" +#include "Actuator.h" + +Brakes::Brakes(uint8_t pin, arduino_t arduino) : Actuator(A_BRAKES, arduino, 1) { + this->pin = pin; + this->engaged = false; +} + +errorlevel_t Brakes::init() { + pinMode(pin, OUTPUT); +} + +errorlevel_t Brakes::set(float target) { + engaged |= (target != 0); //If engaged is true already, target doesn't matter (stay engaged) + digitalWrite(pin, engaged); +} \ No newline at end of file diff --git a/Brakes/src/Brakes.h b/Brakes/src/Brakes.h new file mode 100644 index 0000000..741f974 --- /dev/null +++ b/Brakes/src/Brakes.h @@ -0,0 +1,16 @@ +#ifndef BRAKES_H +#define BRAKES_H + +#include "Actuator.h" + +class Brakes : public Actuator { + public: + Brakes(uint8_t pin, arduino_t arduino); + private: + errorlevel_t set(float target) override; + errorlevel_t init() override; + uint8_t pin; + bool engaged = false; //Toggle-ON latch boolean (can only be turned ON) +}; + +#endif \ No newline at end of file diff --git a/Brakes/tests/Brakes_test.ino b/Brakes/tests/Brakes_test.ino new file mode 100644 index 0000000..cd7e596 --- /dev/null +++ b/Brakes/tests/Brakes_test.ino @@ -0,0 +1,83 @@ +/* + * ## Note to Testers ## + * + * FFT is by default OFF + * To turn FFT on, please refer to line 64 below, + * and refer to line 18-23 in src/MPU9250.h + */ + +// Headers for each sensor type +#include "src/MPU9250.h" +//... + +#include "src/Sensor.h" +#define NUMSENSORS 1 //Or however many +#define BAUDRATE 115200 +#define THISARDUINO ARDUINO_ONE + +// Objects for each sensor +MPU9250 mpu9250(THISARDUINO); +//... + +Sensor* sensors[NUMSENSORS] = { + // Entry for each sensor object + &mpu9250, + //... +}; + +// !#!#!#!--- EVERYTHING AFTER HERE DOES NOT NEED TO BE CHANGED FOR SENSOR IMPLEMENTATION ---!#!#!#! + +void setup(){ + Serial.begin(BAUDRATE); + + bool success = true; + for(int i = 0; i < NUMSENSORS; i++){ + SensorState* state = sensors[i]->begin(); + // Print/send sensor post-setup state data here. For example: + bool _success = (state->error == ERR_NONE); + if(_success){ + Serial.print("Sensor "); + Serial.print(sensors[i]->sensor); + Serial.println(" initialized."); + } else { + Serial.print("Sensor "); + Serial.print(sensors[i]->sensor); + Serial.println(" failed to initialize!"); + } + success &= _success; + } + if(!success){ + Serial.println("POST failed on one or more sensors, freezing..."); + while(1){delay(1000);} + } +} + +void loop(){ + for(int i = 0; i < NUMSENSORS; i++){ + SensorState* state = sensors[i]->update(); + // Print/send sensor post-setup state data here. For example: + bool _success = (state->error == ERR_NONE); + bool _new = (state->debug == DS_NEWREAD); + if(_success){ + if(_new){ + + // vv Recommend commenting this bit out to see FFT printout vv + Serial.print("Sensor "); + Serial.print(sensors[i]->sensor); + Serial.print(" read success: "); + for(int x = 0; x < state->numdata; x++){ + Serial.print(state->data[x].data); + Serial.print(' '); + Serial.print(state->data[x].units); + if(x < state->numdata-1){Serial.print(", ");}else{Serial.println();} + } + // ^^ ----------------------------------------------------- ^^ + } + } else { + Serial.print("Sensor "); + Serial.print(sensors[i]->sensor); + Serial.println(" failed to update!"); + // TODO: Recover failed sensor? + } + } +} From d181bfbe8024e627bae2cf65404fb7837f02d813 Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Mon, 12 Jul 2021 00:08:50 -0400 Subject: [PATCH 5/6] Brakes Readme, Fixed Normally Open deleted useless test script --- Brakes/README.md | 3 ++ Brakes/src/Brakes.cpp | 4 +- Brakes/src/Brakes.h | 1 - Brakes/tests/Brakes_test.ino | 83 ------------------------------------ 4 files changed, 5 insertions(+), 86 deletions(-) delete mode 100644 Brakes/tests/Brakes_test.ino diff --git a/Brakes/README.md b/Brakes/README.md index e69de29..957c0be 100644 --- a/Brakes/README.md +++ b/Brakes/README.md @@ -0,0 +1,3 @@ +# Brakes + +Engages brakes via digital output control of a MOSFET driving a solenoid (NORMALLY OPEN, i.e. engaged = digital low). Once engaged, brakes do not disengage. Fails to engaged. \ No newline at end of file diff --git a/Brakes/src/Brakes.cpp b/Brakes/src/Brakes.cpp index 1e1c299..92130de 100644 --- a/Brakes/src/Brakes.cpp +++ b/Brakes/src/Brakes.cpp @@ -1,7 +1,7 @@ #include "Brakes.h" #include "Actuator.h" -Brakes::Brakes(uint8_t pin, arduino_t arduino) : Actuator(A_BRAKES, arduino, 1) { +Brakes::Brakes(uint8_t pin, arduino_t arduino) : Actuator(A_BRAKES, arduino, 1.0) { this->pin = pin; this->engaged = false; } @@ -12,5 +12,5 @@ errorlevel_t Brakes::init() { errorlevel_t Brakes::set(float target) { engaged |= (target != 0); //If engaged is true already, target doesn't matter (stay engaged) - digitalWrite(pin, engaged); + digitalWrite(pin, !engaged); // Engaged = digital low } \ No newline at end of file diff --git a/Brakes/src/Brakes.h b/Brakes/src/Brakes.h index 741f974..6ceb5cd 100644 --- a/Brakes/src/Brakes.h +++ b/Brakes/src/Brakes.h @@ -2,7 +2,6 @@ #define BRAKES_H #include "Actuator.h" - class Brakes : public Actuator { public: Brakes(uint8_t pin, arduino_t arduino); diff --git a/Brakes/tests/Brakes_test.ino b/Brakes/tests/Brakes_test.ino deleted file mode 100644 index cd7e596..0000000 --- a/Brakes/tests/Brakes_test.ino +++ /dev/null @@ -1,83 +0,0 @@ -/* - * ## Note to Testers ## - * - * FFT is by default OFF - * To turn FFT on, please refer to line 64 below, - * and refer to line 18-23 in src/MPU9250.h - */ - -// Headers for each sensor type -#include "src/MPU9250.h" -//... - -#include "src/Sensor.h" -#define NUMSENSORS 1 //Or however many -#define BAUDRATE 115200 -#define THISARDUINO ARDUINO_ONE - -// Objects for each sensor -MPU9250 mpu9250(THISARDUINO); -//... - -Sensor* sensors[NUMSENSORS] = { - // Entry for each sensor object - &mpu9250, - //... -}; - -// !#!#!#!--- EVERYTHING AFTER HERE DOES NOT NEED TO BE CHANGED FOR SENSOR IMPLEMENTATION ---!#!#!#! - -void setup(){ - Serial.begin(BAUDRATE); - - bool success = true; - for(int i = 0; i < NUMSENSORS; i++){ - SensorState* state = sensors[i]->begin(); - // Print/send sensor post-setup state data here. For example: - bool _success = (state->error == ERR_NONE); - if(_success){ - Serial.print("Sensor "); - Serial.print(sensors[i]->sensor); - Serial.println(" initialized."); - } else { - Serial.print("Sensor "); - Serial.print(sensors[i]->sensor); - Serial.println(" failed to initialize!"); - } - success &= _success; - } - if(!success){ - Serial.println("POST failed on one or more sensors, freezing..."); - while(1){delay(1000);} - } -} - -void loop(){ - for(int i = 0; i < NUMSENSORS; i++){ - SensorState* state = sensors[i]->update(); - // Print/send sensor post-setup state data here. For example: - bool _success = (state->error == ERR_NONE); - bool _new = (state->debug == DS_NEWREAD); - if(_success){ - if(_new){ - - // vv Recommend commenting this bit out to see FFT printout vv - Serial.print("Sensor "); - Serial.print(sensors[i]->sensor); - Serial.print(" read success: "); - for(int x = 0; x < state->numdata; x++){ - Serial.print(state->data[x].data); - Serial.print(' '); - Serial.print(state->data[x].units); - if(x < state->numdata-1){Serial.print(", ");}else{Serial.println();} - } - // ^^ ----------------------------------------------------- ^^ - } - } else { - Serial.print("Sensor "); - Serial.print(sensors[i]->sensor); - Serial.println(" failed to update!"); - // TODO: Recover failed sensor? - } - } -} From 46f8c9031af35891066e84c9bbdd63314ea16d79 Mon Sep 17 00:00:00 2001 From: Jayden Lefebvre Date: Mon, 12 Jul 2021 00:09:44 -0400 Subject: [PATCH 6/6] Minor Comment --- Template.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Template.ino b/Template.ino index 8f4eaea..2f7cff8 100644 --- a/Template.ino +++ b/Template.ino @@ -59,7 +59,7 @@ void setup(){ Serial.print(actuators[i]->actuator); Serial.print(" initialized. "); - state = actuators[i]->update(); + state = actuators[i]->update(); // Initial set to default target _success = (state->error == ERR_NONE); if(_success){ Serial.print("Set to ");