diff --git a/Actuator.cpp b/Actuator.cpp new file mode 100644 index 0000000..d667116 --- /dev/null +++ b/Actuator.cpp @@ -0,0 +1,40 @@ +#include "Arduino.h" +#include "Actuator.h" + +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->failtarget = failtarget; // 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_SUCCESS; + break; + case ERR_WARN: //Set didn't go as planned, non-fatal + // DO NOT UPDATE STATE VALUES + break; + case ERR_FAIL: //Set failed catastrophically + state.debug = DS_DISABLED; + set(failtarget); + 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..37d7675 --- /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 failtarget; // what should we default to in case of failure? + Actuator(actuators_t actuator, arduino_t arduino, float failtarget); + 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..623ae26 --- /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_SUCCESS //NOT NULL, age == 0 +} debuglevel_t; + +#endif \ No newline at end of file diff --git a/Brakes/README.md b/Brakes/README.md new file mode 100644 index 0000000..957c0be --- /dev/null +++ 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 new file mode 100644 index 0000000..92130de --- /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.0) { + 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); // Engaged = digital low +} \ No newline at end of file diff --git a/Brakes/src/Brakes.h b/Brakes/src/Brakes.h new file mode 100644 index 0000000..6ceb5cd --- /dev/null +++ b/Brakes/src/Brakes.h @@ -0,0 +1,15 @@ +#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/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; 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; diff --git a/Template.ino b/Template.ino index 5aa5fc3..2f7cff8 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(); // Initial set to default target + _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