diff --git a/Inverter/Code Overview - Map.png b/Inverter/Code Overview - Map.png
new file mode 100644
index 0000000..84a5cb6
Binary files /dev/null and b/Inverter/Code Overview - Map.png differ
diff --git a/Inverter/Inverter.ino b/Inverter/Inverter.ino
new file mode 100644
index 0000000..0fca4f9
--- /dev/null
+++ b/Inverter/Inverter.ino
@@ -0,0 +1,129 @@
+// Headers for each sensor type
+#include "src/InverterDebug.h"
+//...
+#include "src/Inverter.h"
+
+#include "src/Serial_CAN_Module.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
+
+#define CANBAUD 9600
+#define CANTX 10
+#define CANRX 11
+
+Serial_CAN canbus();
+
+// Objects for each sensor
+InverterDebug inverterDebug(&canbus, THISARDUINO);
+//...
+Inverter inverter(&canbus, THISARDUINO);
+//...
+
+Sensor* sensors[NUMSENSORS] = {
+ &inverterDebug
+};
+
+Actuator* actuators[NUMACTUATORS] = {
+ &inverter
+};
+
+// !#!#!#!--- EVERYTHING AFTER HERE DOES NOT NEED TO BE CHANGED FOR SENSOR IMPLEMENTATION ---!#!#!#!
+
+void setup(){
+ Serial.begin(BAUDRATE);
+ canbus.begin(CANTX, CANRX, CANBAUD);
+
+ 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;
+ }
+ 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 devices, 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_SUCCESS);
+ if(_success && _new) {
+ 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 if (!_success) {
+ Serial.print("Sensor ");
+ Serial.print(sensors[i]->sensor);
+ Serial.println(" failed to update!");
+ // 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
diff --git a/Inverter/README.md b/Inverter/README.md
new file mode 100644
index 0000000..eab40f8
--- /dev/null
+++ b/Inverter/README.md
@@ -0,0 +1,68 @@
+# Serial CAN Bus
+
+> Documentation for the **Serial CAN Bus** can be found [here](https://drive.google.com/drive/folders/1rzmLET68QOWb4At4mAyN4rDsj-VGBLyh?usp=sharing).
+
+
+## Todo
+
+- [ ] Setup, testing, and expected output documentation (screenshot, pictures, logs/stack traces, etc.);
+- [ ] A list of dependencies (and links to those);
+- [ ] Everything else that is listed under [the master `README`](../README.md).
+
+
+
+# PM100 Inverter/Controller CAN Bus Message Reference
+
+> Prepared by Adam Pietrewicz, adapted to Markdown by Jayden Lefebvre (@JLefebvre55)
+>
+> Last Updated - July 14th 2021
+
+***
+
+## Broadcast Messages
+
+> CAN ID: `0x0A0-0x0AF`. See doc for example implementation (pgs. 4-5) and per-byte breakdown (pgs. 5-11).
+
+| Address | Frequency | Content | CAN Active Messages (Low Word) |
+|-----------|---------------|---------------------------------------------------------|----------------------------------|
+| `0x0A0` | Slow/10Hz | Temperatures #1 | `0x0001` |
+| `0x0A1` | Slow/10Hz | Temperatures #2 | `0x0002` |
+| `0x0A2` | Slow/10Hz | Temperatures #3 | `0x0004` |
+| `0x0A3` | Fast/100Hz | Analog Inputs Voltages | `0x0008` |
+| `0x0A4` | Fast/100Hz | Digital Input Status | `0x0010` |
+| `0x0A5` | Fast/100Hz | Motor Position Information | `0x0020` |
+| `0x0A6` | Fast/100Hz | Current Information | `0x0040` |
+| `0x0A7` | Fast/100Hz | Voltage Information | `0x0080` |
+| `0x0A8` | Fast/100Hz | Flux Information | `0x0100` |
+| `0x0A9` | Slow/10Hz | Internal Voltages | `0x0200` |
+| `0x0AA` | Fast/100Hz | Internal States | `0x0400` |
+| `0x0AB` | Fast/100Hz | Fault Codes | `0x0800` |
+| `0x0AC` | Fast/100Hz | Torque & Timer Information | `0x1000` |
+| `0x0AD` | Fast/100Hz | Modulation Index & Flux Weakening
Output Information | `0x2000` |
+| `0x0AE` | Slow/10Hz | Firmware Information | `0x4000` |
+| `0x0AF` | 100Hz (fixed) | Diagnostic Data | `0x8000` |
+
+***
+## Command Messages
+
+> CAN ID: `0x0C0`. See doc for example implementation (pgs. 2-3).
+
+| Byte(s) | Name | Format | Description |
+|----------|------------------------|------------------|------------------------------------------------------------------------------------------------------------------------|
+| 0, 1 | Torque Command | Torque | Torque command used when in torque mode. |
+| 2, 3 | Speed Command | Angular Velocity | Speed command used when in speed mode. |
+| 4 | Direction Command | Boolean | `0` - "Reverse", `1` - "Forward" (See Section 2.3.2.2) |
+| 5: Bit 0 | Inverter Enable | Boolean | `0` - Inverter Off, `1` - Inverter On |
+| 5: Bit 1 | Inverter Discharge | Boolean | `0` - Disable Discharge, `1` - Enable Discharge |
+| 5, 2 | Speed Mode Enable | Boolean | `0` - Do not override mode, `1` - Overrides from torque
mode to speed mode ONLY (See "Using Speed Mode" in manual) |
+| 6, 7 | Commanded Torque Limit | Torque | Motor and Regen Torque limits. If set to `0`, default
torque limit from EEPROM is used. |
+
+***
+## Parameter Messages
+
+> Sets EEPROM parameters.
+
+**CAN ID `0x0C1`** - Used to send message *to* controller.
+
+**CAN ID `0x0C2`** - Response *from* controller.
+***
\ No newline at end of file
diff --git a/Inverter/old/BROADCAST_FAULTS.cpp b/Inverter/old/BROADCAST_FAULTS.cpp
new file mode 100644
index 0000000..ee2e6df
--- /dev/null
+++ b/Inverter/old/BROADCAST_FAULTS.cpp
@@ -0,0 +1,270 @@
+//#include
+//#include
+//#include
+#include
+#include
+//#include
+#include
+#include
+
+using namespace std;
+
+PM100_FAULT_CODE FAULT_CODE_ARRAY[65] = {
+ //POST FAULTS
+ //Byte 0
+ Hardware_Gate_Desaturation_Fault,
+ HW_Over_current_Fault,
+ Accelerator_Shorted,
+ Accelerator_Open,
+ Current_Sensor_Low,
+ Current_Sensor_High,
+ Module_Temperature_Low,
+ Module_Temperature_High,
+ //Byte 1
+ Control_PCB_Temperature_Low,
+ Control_PCB_Temperature_High,
+ Gate_Drive_PCB_Temperature_Low,
+ Gate_Drive_PCB_Temperature_High,
+ Sense_Voltage_Low_5V,
+ Sense_Voltage_High_5V,
+ Sense_Voltage_Low_12V,
+ Sense_Voltage_High_12V,
+ //Byte 2
+ Sense_Voltage_Low_2_5V,
+ Sense_Voltage_High_2_5V,
+ Sense_Voltage_Low_1_5V,
+ Sense_Voltage_High_1_5V,
+ DC_Bus_Voltage_High,
+ DC_Bus_Voltage_Low,
+ Pre_charge_Timeout,
+ Pre_charge_Voltage_Failure,
+ //Byte 3
+ EEPROM_Checksum_Invalid,
+ EEPROM_Data_Out_of_Range,
+ EEPROM_Update_Required,
+ RESERVED_1,
+ RESERVED_2,
+ RESERVED_3,
+ Brake_Shorted,
+ Brake_Open,
+ //Byte 4
+ //RUN FAULTS
+ Motor_Over_speed_Fault,
+ Over_current_Fault,
+ Over_voltage_Fault,
+ Inverter_Over_temperature_Fault,
+ Accelerator_Input_Shorted_Fault,
+ Accelerator_Input_Open_Fault,
+ Direction_Command_Fault,
+ Inverter_Response_Time_out_Fault,
+ //Byte 5
+ Hardware_Gate_Desaturation_RUN_Fault,
+ Hardware_Over_current_Fault,
+ Under_voltage_Fault,
+ CAN_Command_Message_Lost_Fault,
+ Motor_Over_temperature_Fault,
+ RESERVED_4,
+ RESERVED_5,
+ RESERVED_6,
+ //Byte 6
+ Brake_Input_Shorted_Fault,
+ Brake_Input_Open_Fault,
+ Module_A_Over_temperature_Fault,
+ Module_B_Over_temperature_Fault,
+ Module_C_Over_temperature_Fault,
+ PCB_Over_temperature_Fault,
+ Gate_Drive_Board_1_Over_temperature_Fault,
+ Gate_Drive_Board_2_Over_temperature_Fault,
+ //Byte 7
+ Gate_Drive_Board_3_Over_temperature_Fault,
+ Current_Sensor_Fault,
+ RESERVED_7,
+ Hardware_Over_Voltage_Fault,
+ RESERVED_8,
+ RESERVED_9,
+ Resolver_Not_Connected,
+ Inverter_Discharge_Active,
+
+ //Finally, error if the CAN mssg is NOT for fault codes
+ NOT_FAULT_CAN_MSSG
+
+};
+
+
+std::ostream& operator<<(std::ostream& lhs, PM100_FAULT_CODE fault) {
+
+ switch(fault) {
+
+ case Hardware_Gate_Desaturation_Fault: lhs << "Hardware_Gate_Desaturation_Fault"; break;
+ case HW_Over_current_Fault: lhs << "HW_Over_current_Fault"; break;
+ case Accelerator_Shorted: lhs << "Accelerator_Shorted"; break;
+ case Accelerator_Open: lhs << "Accelerator_Open"; break;
+ case Current_Sensor_Low: lhs << "Current_Sensor_Low"; break;
+ case Current_Sensor_High: lhs << "Current_Sensor_High"; break;
+ case Module_Temperature_Low: lhs << "Module_Temperature_Low"; break;
+ case Module_Temperature_High: lhs << "Module_Temperature_High"; break;
+ case Control_PCB_Temperature_Low: lhs << "Control_PCB_Temperature_Low"; break;
+ case Control_PCB_Temperature_High: lhs << "Control_PCB_Temperature_High"; break;
+ case Gate_Drive_PCB_Temperature_Low: lhs << "Gate_Drive_PCB_Temperature_Low"; break;
+ case Gate_Drive_PCB_Temperature_High: lhs << "Gate_Drive_PCB_Temperature_High"; break;
+ case Sense_Voltage_Low_5V: lhs << "Sense_Voltage_Low_5V"; break;
+ case Sense_Voltage_High_5V: lhs << "Sense_Voltage_High_5V"; break;
+ case Sense_Voltage_Low_12V: lhs << "Sense_Voltage_Low_12V"; break;
+ case Sense_Voltage_High_12V: lhs << "Sense_Voltage_High_12V"; break;
+ case Sense_Voltage_Low_2_5V: lhs << "Sense_Voltage_Low_2_5V"; break;
+ case Sense_Voltage_High_2_5V: lhs << "Sense_Voltage_High_2_5V"; break;
+ case Sense_Voltage_Low_1_5V: lhs << "Sense_Voltage_Low_1_5V"; break;
+ case Sense_Voltage_High_1_5V: lhs << "Sense_Voltage_High_1_5V"; break;
+ case DC_Bus_Voltage_High: lhs << "DC_Bus_Voltage_High"; break;
+ case DC_Bus_Voltage_Low: lhs << "DC_Bus_Voltage_Low"; break;
+ case Pre_charge_Timeout: lhs << "Pre_charge_Timeout"; break;
+ case Pre_charge_Voltage_Failure: lhs << "Pre_charge_Voltage_Failure"; break;
+ case EEPROM_Checksum_Invalid: lhs << "EEPROM_Checksum_Invalid"; break;
+ case EEPROM_Data_Out_of_Range: lhs << "EEPROM_Data_Out_of_Range"; break;
+ case EEPROM_Update_Required: lhs << "EEPROM_Update_Required"; break;
+ case RESERVED_1: lhs << "RESERVED_1"; break;
+ case RESERVED_2: lhs << "RESERVED_2"; break;
+ case RESERVED_3: lhs << "RESERVED_3"; break;
+ case Brake_Shorted: lhs << "Brake_Shorted"; break;
+ case Brake_Open: lhs << "Brake_Open"; break;
+ case Motor_Over_speed_Fault: lhs << "Motor_Over_speed_Fault"; break;
+ case Over_current_Fault: lhs << "Over_current_Fault"; break;
+ case Over_voltage_Fault: lhs << "Over_voltage_Fault"; break;
+ case Inverter_Over_temperature_Fault: lhs << "Inverter_Over_temperature_Fault"; break;
+ case Accelerator_Input_Shorted_Fault: lhs << "Accelerator_Input_Shorted_Fault"; break;
+ case Accelerator_Input_Open_Fault: lhs << "Accelerator_Input_Open_Fault"; break;
+ case Direction_Command_Fault: lhs << "Direction_Command_Fault"; break;
+ case Inverter_Response_Time_out_Fault: lhs << "Inverter_Response_Time_out_Fault"; break;
+ case Hardware_Gate_Desaturation_RUN_Fault: lhs << "Hardware_Gate_Desaturation_RUN_Fault"; break;
+ case Hardware_Over_current_Fault: lhs << "Hardware_Over_current_Fault"; break;
+ case Under_voltage_Fault: lhs << "Under_voltage_Fault"; break;
+ case CAN_Command_Message_Lost_Fault: lhs << "CAN_Command_Message_Lost_Fault"; break;
+ case Motor_Over_temperature_Fault: lhs << "Motor_Over_temperature_Fault"; break;
+ case RESERVED_4: lhs << "RESERVED_4"; break;
+ case RESERVED_5: lhs << "RESERVED_5"; break;
+ case RESERVED_6: lhs << "RESERVED_6"; break;
+ case Brake_Input_Shorted_Fault: lhs << "Brake_Input_Shorted_Fault"; break;
+ case Brake_Input_Open_Fault: lhs << "Brake_Input_Open_Fault"; break;
+ case Module_A_Over_temperature_Fault: lhs << "Module_A_Over_temperature_Fault"; break;
+ case Module_B_Over_temperature_Fault: lhs << "Module_B_Over_temperature_Fault"; break;
+ case Module_C_Over_temperature_Fault: lhs << "Module_C_Over_temperature_Fault"; break;
+ case PCB_Over_temperature_Fault: lhs << "PCB_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_1_Over_temperature_Fault: lhs << "Gate_Drive_Board_1_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_2_Over_temperature_Fault: lhs << "Gate_Drive_Board_2_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_3_Over_temperature_Fault: lhs << "Gate_Drive_Board_3_Over_temperature_Fault"; break;
+ case Current_Sensor_Fault: lhs << "Current_Sensor_Fault"; break;
+ case RESERVED_7: lhs << "RESERVED_7"; break;
+ case Hardware_Over_Voltage_Fault: lhs << "Hardware_Over_Voltage_Fault"; break;
+ case RESERVED_8: lhs << "RESERVED_8"; break;
+ case RESERVED_9: lhs << "RESERVED_9"; break;
+ case Resolver_Not_Connected: lhs << "Resolver_Not_Connected"; break;
+ case Inverter_Discharge_Active: lhs << "Inverter_Discharge_Active"; break;
+ case NOT_FAULT_CAN_MSSG: lhs << "ERROR - This CAN Message is NOT for FAULT CODES!"; break;
+ }
+
+ return lhs;
+}
+
+
+int return_fault_index_val( PM100_FAULT_CODE fault ){
+
+ int index_value = fault;
+ return index_value;
+}
+
+
+
+std::vector broadcast_message::read_fault_codes_VER_2( int CAN_mssg[9] ){
+
+ //extract the CAN ID & define return vector of fault codes
+ int CAN_ID = CAN_mssg[0];
+ vector faults_found;
+ PM100_FAULT_CODE fault;
+
+ //check if CAN message is FAULT message
+ if( CAN_ID != 0x0AB ){
+ cout << NOT_FAULT_CAN_MSSG;
+ faults_found.push_back( NOT_FAULT_CAN_MSSG );
+ }
+ else if( CAN_ID == 0x0AB ){
+
+ int fault_code_index = 0; //var used for indexing fault code array
+
+ //here we'll loop 8 times, analyze each CAN data byte
+ for( int i = 1; i < 9; i++ ){
+
+ int byte_i = CAN_mssg[i];
+ cout << "Byte " << i << " Faults: " << endl;
+
+ //vars to check each bit of current byte
+ int current_bit;
+ int int_to_binary = byte_i;
+ for( int i = 0; i < 8; i++ ){
+
+ current_bit = int_to_binary % 2;
+ int_to_binary = int_to_binary / 2;
+
+ if( current_bit ){
+ fault = FAULT_CODE_ARRAY[ fault_code_index + i ];
+ cout << " " << fault << " -- Fault #" << return_fault_index_val( fault ) << endl;
+ faults_found.push_back( fault );
+ }
+ }
+
+ fault_code_index = fault_code_index + 8;
+ }
+
+ }
+
+ return faults_found;
+}
+
+
+
+
+
+
+int main(){
+
+ cout << "----------------------------------------------------------------" << endl;
+ cout << "- -" << endl;
+ cout << "- CAN PM100 -" << endl;
+ cout << "- Fault Code Function Testing -" << endl;
+ cout << "- -" << endl;
+ cout << "- -" << endl;
+ cout << "- -" << endl;
+ cout << "----------------------------------------------------------------\n" << endl;
+
+ cout << "< Hello there! Here we'll test out reading Fault Codes from the PM100 >" << endl;
+ cout << "< >" << endl;
+ cout << "< >" << endl;
+ cout << "< >\n" << endl;
+
+ cout << "< The CAN message we're testing is: >" << endl;
+
+ broadcast_message testing_class;
+ int test_message_2[9] = { 0x0AB, 128, 32, 0, 0, 0, 0, 2, 0 };
+
+ cout << "< {";
+ for ( int i = 0; i < 8; i++ ){
+ /*
+ if(i == 0){
+ cout << " 0x0" << hex << test_message_2[i] << ",";
+ continue;
+ }
+ */
+ cout << " " << test_message_2[i] << ",";
+ }
+ cout << " }\n" << endl;
+
+
+
+ vector returned_faults_vector;
+ returned_faults_vector = testing_class.read_fault_codes_VER_2( test_message_2 );
+
+
+
+
+
+}
+
diff --git a/Inverter/old/BROADCAST_FAULTS.h b/Inverter/old/BROADCAST_FAULTS.h
new file mode 100644
index 0000000..9a39ec2
--- /dev/null
+++ b/Inverter/old/BROADCAST_FAULTS.h
@@ -0,0 +1,118 @@
+#ifndef BROADCAST_FAULTS_H
+#define BROADCAST_FAULTS_H
+
+#include
+//#include
+#include
+#include
+//types of CAN messages
+typedef enum fault_code {
+ //POST FAULTS
+ //Byte 0
+ Hardware_Gate_Desaturation_Fault,
+ HW_Over_current_Fault,
+ Accelerator_Shorted,
+ Accelerator_Open,
+ Current_Sensor_Low,
+ Current_Sensor_High,
+ Module_Temperature_Low,
+ Module_Temperature_High,
+ //Byte 1
+ Control_PCB_Temperature_Low,
+ Control_PCB_Temperature_High,
+ Gate_Drive_PCB_Temperature_Low,
+ Gate_Drive_PCB_Temperature_High,
+ Sense_Voltage_Low_5V,
+ Sense_Voltage_High_5V,
+ Sense_Voltage_Low_12V,
+ Sense_Voltage_High_12V,
+ //Byte 2
+ Sense_Voltage_Low_2_5V,
+ Sense_Voltage_High_2_5V,
+ Sense_Voltage_Low_1_5V,
+ Sense_Voltage_High_1_5V,
+ DC_Bus_Voltage_High,
+ DC_Bus_Voltage_Low,
+ Pre_charge_Timeout,
+ Pre_charge_Voltage_Failure,
+ //Byte 3
+ EEPROM_Checksum_Invalid,
+ EEPROM_Data_Out_of_Range,
+ EEPROM_Update_Required,
+ RESERVED_1,
+ RESERVED_2,
+ RESERVED_3,
+ Brake_Shorted,
+ Brake_Open,
+ //Byte 4
+ //RUN FAULTS
+ Motor_Over_speed_Fault,
+ Over_current_Fault,
+ Over_voltage_Fault,
+ Inverter_Over_temperature_Fault,
+ Accelerator_Input_Shorted_Fault,
+ Accelerator_Input_Open_Fault,
+ Direction_Command_Fault,
+ Inverter_Response_Time_out_Fault,
+ //Byte 5
+ Hardware_Gate_Desaturation_RUN_Fault,
+ Hardware_Over_current_Fault,
+ Under_voltage_Fault,
+ CAN_Command_Message_Lost_Fault,
+ Motor_Over_temperature_Fault,
+ RESERVED_4,
+ RESERVED_5,
+ RESERVED_6,
+ //Byte 6
+ Brake_Input_Shorted_Fault,
+ Brake_Input_Open_Fault,
+ Module_A_Over_temperature_Fault,
+ Module_B_Over_temperature_Fault,
+ Module_C_Over_temperature_Fault,
+ PCB_Over_temperature_Fault,
+ Gate_Drive_Board_1_Over_temperature_Fault,
+ Gate_Drive_Board_2_Over_temperature_Fault,
+ //Byte 7
+ Gate_Drive_Board_3_Over_temperature_Fault,
+ Current_Sensor_Fault,
+ RESERVED_7,
+ Hardware_Over_Voltage_Fault,
+ RESERVED_8,
+ RESERVED_9,
+ Resolver_Not_Connected,
+ Inverter_Discharge_Active,
+
+ //Finally, error if the CAN mssg is NOT for fault codes
+ NOT_FAULT_CAN_MSSG
+
+
+} PM100_FAULT_CODE;
+
+
+
+using namespace std;
+
+
+
+class broadcast_message{
+
+ public:
+
+ message_type command_message;
+
+ friend ostream& operator<<( ostream& lhs, PM100_FAULT_CODE fault );
+
+ friend int return_fault_index_val( PM100_FAULT_CODE fault );
+
+ vector read_fault_codes_VER_2( int CAN_mssg[9] );
+
+
+
+
+
+
+
+
+};
+
+#endif
diff --git a/Inverter/old/BROADCAST_MESSAGE.cpp b/Inverter/old/BROADCAST_MESSAGE.cpp
new file mode 100644
index 0000000..8edc713
--- /dev/null
+++ b/Inverter/old/BROADCAST_MESSAGE.cpp
@@ -0,0 +1,539 @@
+#include
+#include
+#include
+//#include
+#include
+
+using namespace std;
+
+std::ostream &operator<<(std::ostream &lhs, vsm_state state)
+{
+ switch (state) {
+ case VSM_START: lhs << "VSM Start State"; break;
+ case PRE_CHARGE_INIT: lhs << "Pre-Charge Init State"; break;
+ case PRE_CHARGE_ACTIVE: lhs << "Pre-Charge Active State"; break;
+ case PRE_CHARGE_COMPLETE: lhs << "Pre-Charge Complete State"; break;
+ case VSM_WAIT: lhs << "VSM Wait State"; break;
+ case VSM_READY: lhs << "VSM Ready State"; break;
+ case MOTOR_RUNNING: lhs << "Motor Running State"; break;
+ case BLINK_FAULT_CODE: lhs << "Blink Fault Code State"; break;
+ case SHUTDOWN_IN_PROGRESS: lhs << "Shutdown in Process"; break;
+ case RECYCLE_POWER: lhs << "Recycle Power State"; break;
+ case NOT_A_VSM_STATE: lhs << "ERROR - NOT a VSM State - Invalid Value"; break;
+ }
+
+ return lhs;
+}
+
+int return_vsm_state_val(vsm_state state)
+{
+ int index_value = state;
+ return index_value;
+}
+
+vsm_state broadcast_message::read_vsm_state(int CAN_mssg[9])
+{
+ vsm_state state;
+
+ if (CAN_mssg[0] != 0x0AA)
+ {
+ cout << "Message CAN ID is not 0x0AA, this is NOT a VSM message" << endl;
+ return state = NOT_A_VSM_STATE;
+ }
+
+ switch (CAN_mssg[2])
+ {
+ case 0:
+ cout << "VSM State: VSM Start State";
+ state = VSM_START; break;
+ case 1:
+ cout << "VSM State: Pre-charge Init State";
+ state = PRE_CHARGE_INIT; break;
+ case 2:
+ cout << "VSM State: Pre-charge Active State";
+ state = PRE_CHARGE_ACTIVE; break;
+ case 3:
+ cout << "VSM State: Pre-charge Complete State";
+ state = PRE_CHARGE_COMPLETE; break;
+ case 4:
+ cout << "VSM State: VSM Wait State";
+ state = VSM_WAIT; break;
+ case 5:
+ cout << "VSM State: VSM Ready State";
+ state = VSM_READY; break;
+ case 6:
+ cout << "VSM State: Motor Running State";
+ state = MOTOR_RUNNING; break;
+ case 7:
+ cout << "VSM State: Blink Fault Code State";
+ state = BLINK_FAULT_CODE; break;
+ case 14:
+ cout << "VSM State: Shutdown in Process";
+ state = SHUTDOWN_IN_PROGRESS; break;
+ case 15:
+ cout << "VSM State: Recycle Power State";
+ state = RECYCLE_POWER; break;
+ default:
+ cout << "Invalid VSM State";
+ state = NOT_A_VSM_STATE;
+ }
+
+ return state;
+}
+
+std::ostream &operator<<(std::ostream &lhs, inverter_state state)
+{
+ switch (state) {
+ case POWER_ON: lhs << "Power On State"; break;
+ case STOP: lhs << "Stop State"; break;
+ case OPEN_LOOP: lhs << "Open Loop State"; break;
+ case CLOSED_LOOP: lhs << "Closed Loop State"; break;
+ case WAIT: lhs << "Wait State"; break;
+ case IDLE_RUN: lhs << "Idle Run State"; break;
+ case IDLE_STOP: lhs << "Idle Stop State"; break;
+ case NOT_AN_INVERTER_STATE: lhs << "ERROR - NOT an Inverter State - Invalid Value"; break;
+ }
+
+ return lhs;
+}
+
+int return_inverter_state_val(inverter_state state)
+{
+ int index_value = state;
+ return index_value;
+}
+
+inverter_state broadcast_message::read_inverter_state(int CAN_mssg[9])
+{
+ inverter_state state;
+
+ if (CAN_mssg[0] != 0x0AA)
+ {
+ cout << "Message CAN ID is not 0xAA" << endl;
+ return state = NOT_AN_INVERTER_STATE;
+ }
+
+ switch (CAN_mssg[3])
+ {
+ case 0:
+ cout << "Inverter State: Power on State" << endl;
+ state = POWER_ON; break;
+ case 1:
+ cout << "Inverter State: Stop State" << endl;
+ state = STOP; break;
+ case 2:
+ cout << "Inverter State: Open Loop State" << endl;
+ state = OPEN_LOOP; break;
+ case 3:
+ cout << "Inverter State: Closed Loop State" << endl;
+ state = CLOSED_LOOP; break;
+ case 4:
+ cout << "Inverter State: Wait State" << endl;
+ state = WAIT; break;
+ case 8:
+ cout << "Inverter State: Idle Run State" << endl;
+ state = IDLE_RUN; break;
+ case 9:
+ cout << "Inverter State: Idle Stop State" << endl;
+ state = IDLE_STOP; break;
+ default:
+ cout << "Invalid Inverter State" << endl;
+ state = NOT_AN_INVERTER_STATE; break;
+ }
+
+ return state;
+}
+
+/* Disable one or more messages at a time
+ * Example usage: disable_broadcast_message(test_msg, TEMPERATURE_2 | CURRENT_INFORMATION | DIAG_DATA);
+ */
+void disable_broadcast_message(int CAN_mssg[9], int listOfMsgs)
+{
+ if (CAN_mssg[0] != 0x0C1) // CAN ID
+ {
+ cout << "Message CAN Address is not 0x0C1" << endl;
+ return;
+ }
+
+ if (CAN_mssg[1] != 148) // Data Byte 0
+ {
+ cout << "Message Parameter Address is not 148" << endl;
+ return;
+ }
+
+ int loWord = (CAN_mssg[6] << 8) | CAN_mssg[5]; // loWord = [6] concatenated with [5]
+
+ if ((TEMPERATURE_1 & listOfMsgs) == TEMPERATURE_1)
+ loWord &= ~(1U);
+ if ((TEMPERATURE_2 & listOfMsgs) == TEMPERATURE_2)
+ loWord &= ~(1U << 1);
+ if ((TEMPERATURE_3 & listOfMsgs) == TEMPERATURE_3)
+ loWord &= ~(1U << 2);
+ if ((ANALOG_INPUT_VOLTAGES & listOfMsgs) == ANALOG_INPUT_VOLTAGES)
+ loWord &= ~(1U << 3);
+ if ((DIGITAL_INPUT_STATUS & listOfMsgs) == DIGITAL_INPUT_STATUS)
+ loWord &= ~(1U << 4);
+ if ((MOTOR_POSITION_INFORMATION & listOfMsgs) == MOTOR_POSITION_INFORMATION)
+ loWord &= ~(1U << 5);
+ if ((CURRENT_INFORMATION & listOfMsgs) == CURRENT_INFORMATION)
+ loWord &= ~(1U << 6);
+ if ((VOLTAGE_INFORMATION & listOfMsgs) == VOLTAGE_INFORMATION)
+ loWord &= ~(1U << 7);
+
+ if ((FLUX_INFORMATION & listOfMsgs) == FLUX_INFORMATION)
+ loWord &= ~(1U << 8);
+ if ((INTERNAL_VOLTAGES & listOfMsgs) == INTERNAL_VOLTAGES)
+ loWord &= ~(1U << 9);
+ if ((INTERNAL_STATES & listOfMsgs) == INTERNAL_STATES)
+ loWord &= ~(1U << 10);
+ if ((FAULT_CODES & listOfMsgs) == FAULT_CODES)
+ loWord &= ~(1U << 11);
+ if ((TORQUE_AND_TIMER_INFORMATION & listOfMsgs) == TORQUE_AND_TIMER_INFORMATION)
+ loWord &= ~(1U << 12);
+ if ((MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO & listOfMsgs) == MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO)
+ loWord &= ~(1U << 13);
+ if ((FIRMWARE_INFORMATION & listOfMsgs) == FIRMWARE_INFORMATION)
+ loWord &= ~(1U << 14);
+ if ((DIAG_DATA & listOfMsgs) == DIAG_DATA)
+ loWord &= ~(1U << 15);
+
+ // Separate loWord back into two bytes
+ CAN_mssg[5] = loWord & 0xFF;
+ CAN_mssg[6] = (loWord >> 8) & 0xFF;
+}
+
+
+
+
+//Fault Code Functions and Array defined below
+
+PM100_FAULT_CODE FAULT_CODE_ARRAY[65] = {
+ //POST FAULTS
+ //Byte 0
+ Hardware_Gate_Desaturation_Fault,
+ HW_Over_current_Fault,
+ Accelerator_Shorted,
+ Accelerator_Open,
+ Current_Sensor_Low,
+ Current_Sensor_High,
+ Module_Temperature_Low,
+ Module_Temperature_High,
+ //Byte 1
+ Control_PCB_Temperature_Low,
+ Control_PCB_Temperature_High,
+ Gate_Drive_PCB_Temperature_Low,
+ Gate_Drive_PCB_Temperature_High,
+ Sense_Voltage_Low_5V,
+ Sense_Voltage_High_5V,
+ Sense_Voltage_Low_12V,
+ Sense_Voltage_High_12V,
+ //Byte 2
+ Sense_Voltage_Low_2_5V,
+ Sense_Voltage_High_2_5V,
+ Sense_Voltage_Low_1_5V,
+ Sense_Voltage_High_1_5V,
+ DC_Bus_Voltage_High,
+ DC_Bus_Voltage_Low,
+ Pre_charge_Timeout,
+ Pre_charge_Voltage_Failure,
+ //Byte 3
+ EEPROM_Checksum_Invalid,
+ EEPROM_Data_Out_of_Range,
+ EEPROM_Update_Required,
+ RESERVED_1,
+ RESERVED_2,
+ RESERVED_3,
+ Brake_Shorted,
+ Brake_Open,
+ //Byte 4
+ //RUN FAULTS
+ Motor_Over_speed_Fault,
+ Over_current_Fault,
+ Over_voltage_Fault,
+ Inverter_Over_temperature_Fault,
+ Accelerator_Input_Shorted_Fault,
+ Accelerator_Input_Open_Fault,
+ Direction_Command_Fault,
+ Inverter_Response_Time_out_Fault,
+ //Byte 5
+ Hardware_Gate_Desaturation_RUN_Fault,
+ Hardware_Over_current_Fault,
+ Under_voltage_Fault,
+ CAN_Command_Message_Lost_Fault,
+ Motor_Over_temperature_Fault,
+ RESERVED_4,
+ RESERVED_5,
+ RESERVED_6,
+ //Byte 6
+ Brake_Input_Shorted_Fault,
+ Brake_Input_Open_Fault,
+ Module_A_Over_temperature_Fault,
+ Module_B_Over_temperature_Fault,
+ Module_C_Over_temperature_Fault,
+ PCB_Over_temperature_Fault,
+ Gate_Drive_Board_1_Over_temperature_Fault,
+ Gate_Drive_Board_2_Over_temperature_Fault,
+ //Byte 7
+ Gate_Drive_Board_3_Over_temperature_Fault,
+ Current_Sensor_Fault,
+ RESERVED_7,
+ Hardware_Over_Voltage_Fault,
+ RESERVED_8,
+ RESERVED_9,
+ Resolver_Not_Connected,
+ Inverter_Discharge_Active,
+
+ //Finally, error if the CAN mssg is NOT for fault codes
+ NOT_FAULT_CAN_MSSG
+
+};
+
+
+std::ostream& operator<<(std::ostream& lhs, PM100_FAULT_CODE fault)
+{
+ switch(fault)
+ {
+ case Hardware_Gate_Desaturation_Fault: lhs << "Hardware_Gate_Desaturation_Fault"; break;
+ case HW_Over_current_Fault: lhs << "HW_Over_current_Fault"; break;
+ case Accelerator_Shorted: lhs << "Accelerator_Shorted"; break;
+ case Accelerator_Open: lhs << "Accelerator_Open"; break;
+ case Current_Sensor_Low: lhs << "Current_Sensor_Low"; break;
+ case Current_Sensor_High: lhs << "Current_Sensor_High"; break;
+ case Module_Temperature_Low: lhs << "Module_Temperature_Low"; break;
+ case Module_Temperature_High: lhs << "Module_Temperature_High"; break;
+ case Control_PCB_Temperature_Low: lhs << "Control_PCB_Temperature_Low"; break;
+ case Control_PCB_Temperature_High: lhs << "Control_PCB_Temperature_High"; break;
+ case Gate_Drive_PCB_Temperature_Low: lhs << "Gate_Drive_PCB_Temperature_Low"; break;
+ case Gate_Drive_PCB_Temperature_High: lhs << "Gate_Drive_PCB_Temperature_High"; break;
+ case Sense_Voltage_Low_5V: lhs << "Sense_Voltage_Low_5V"; break;
+ case Sense_Voltage_High_5V: lhs << "Sense_Voltage_High_5V"; break;
+ case Sense_Voltage_Low_12V: lhs << "Sense_Voltage_Low_12V"; break;
+ case Sense_Voltage_High_12V: lhs << "Sense_Voltage_High_12V"; break;
+ case Sense_Voltage_Low_2_5V: lhs << "Sense_Voltage_Low_2_5V"; break;
+ case Sense_Voltage_High_2_5V: lhs << "Sense_Voltage_High_2_5V"; break;
+ case Sense_Voltage_Low_1_5V: lhs << "Sense_Voltage_Low_1_5V"; break;
+ case Sense_Voltage_High_1_5V: lhs << "Sense_Voltage_High_1_5V"; break;
+ case DC_Bus_Voltage_High: lhs << "DC_Bus_Voltage_High"; break;
+ case DC_Bus_Voltage_Low: lhs << "DC_Bus_Voltage_Low"; break;
+ case Pre_charge_Timeout: lhs << "Pre_charge_Timeout"; break;
+ case Pre_charge_Voltage_Failure: lhs << "Pre_charge_Voltage_Failure"; break;
+ case EEPROM_Checksum_Invalid: lhs << "EEPROM_Checksum_Invalid"; break;
+ case EEPROM_Data_Out_of_Range: lhs << "EEPROM_Data_Out_of_Range"; break;
+ case EEPROM_Update_Required: lhs << "EEPROM_Update_Required"; break;
+ case RESERVED_1: lhs << "RESERVED_1"; break;
+ case RESERVED_2: lhs << "RESERVED_2"; break;
+ case RESERVED_3: lhs << "RESERVED_3"; break;
+ case Brake_Shorted: lhs << "Brake_Shorted"; break;
+ case Brake_Open: lhs << "Brake_Open"; break;
+ case Motor_Over_speed_Fault: lhs << "Motor_Over_speed_Fault"; break;
+ case Over_current_Fault: lhs << "Over_current_Fault"; break;
+ case Over_voltage_Fault: lhs << "Over_voltage_Fault"; break;
+ case Inverter_Over_temperature_Fault: lhs << "Inverter_Over_temperature_Fault"; break;
+ case Accelerator_Input_Shorted_Fault: lhs << "Accelerator_Input_Shorted_Fault"; break;
+ case Accelerator_Input_Open_Fault: lhs << "Accelerator_Input_Open_Fault"; break;
+ case Direction_Command_Fault: lhs << "Direction_Command_Fault"; break;
+ case Inverter_Response_Time_out_Fault: lhs << "Inverter_Response_Time_out_Fault"; break;
+ case Hardware_Gate_Desaturation_RUN_Fault: lhs << "Hardware_Gate_Desaturation_RUN_Fault"; break;
+ case Hardware_Over_current_Fault: lhs << "Hardware_Over_current_Fault"; break;
+ case Under_voltage_Fault: lhs << "Under_voltage_Fault"; break;
+ case CAN_Command_Message_Lost_Fault: lhs << "CAN_Command_Message_Lost_Fault"; break;
+ case Motor_Over_temperature_Fault: lhs << "Motor_Over_temperature_Fault"; break;
+ case RESERVED_4: lhs << "RESERVED_4"; break;
+ case RESERVED_5: lhs << "RESERVED_5"; break;
+ case RESERVED_6: lhs << "RESERVED_6"; break;
+ case Brake_Input_Shorted_Fault: lhs << "Brake_Input_Shorted_Fault"; break;
+ case Brake_Input_Open_Fault: lhs << "Brake_Input_Open_Fault"; break;
+ case Module_A_Over_temperature_Fault: lhs << "Module_A_Over_temperature_Fault"; break;
+ case Module_B_Over_temperature_Fault: lhs << "Module_B_Over_temperature_Fault"; break;
+ case Module_C_Over_temperature_Fault: lhs << "Module_C_Over_temperature_Fault"; break;
+ case PCB_Over_temperature_Fault: lhs << "PCB_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_1_Over_temperature_Fault: lhs << "Gate_Drive_Board_1_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_2_Over_temperature_Fault: lhs << "Gate_Drive_Board_2_Over_temperature_Fault"; break;
+ case Gate_Drive_Board_3_Over_temperature_Fault: lhs << "Gate_Drive_Board_3_Over_temperature_Fault"; break;
+ case Current_Sensor_Fault: lhs << "Current_Sensor_Fault"; break;
+ case RESERVED_7: lhs << "RESERVED_7"; break;
+ case Hardware_Over_Voltage_Fault: lhs << "Hardware_Over_Voltage_Fault"; break;
+ case RESERVED_8: lhs << "RESERVED_8"; break;
+ case RESERVED_9: lhs << "RESERVED_9"; break;
+ case Resolver_Not_Connected: lhs << "Resolver_Not_Connected"; break;
+ case Inverter_Discharge_Active: lhs << "Inverter_Discharge_Active"; break;
+ case NOT_FAULT_CAN_MSSG: lhs << "ERROR - This CAN Message is NOT for FAULT CODES!"; break;
+ }
+
+ return lhs;
+}
+
+
+
+int return_fault_index_val( PM100_FAULT_CODE fault )
+{
+ int index_value = fault;
+ return index_value;
+}
+
+
+
+std::vector broadcast_message::read_fault_codes_VER_2( int CAN_mssg[9] )
+{
+ //extract the CAN ID & define return vector of fault codes
+ int CAN_ID = CAN_mssg[0];
+ vector faults_found;
+ PM100_FAULT_CODE fault;
+
+ //check if CAN message is FAULT message
+ if( CAN_ID != 0x0AB )
+ {
+ cout << NOT_FAULT_CAN_MSSG;
+ faults_found.push_back( NOT_FAULT_CAN_MSSG );
+ }
+ else if( CAN_ID == 0x0AB )
+ {
+ int fault_code_index = 0; //var used for indexing fault code array
+
+ //here we'll loop 8 times, analyze each CAN data byte
+ for( int i = 1; i < 9; i++ )
+ {
+ int byte_i = CAN_mssg[i];
+ cout << "Byte " << i << " Faults: " << endl;
+
+ //vars to check each bit of current byte
+ int current_bit;
+ int int_to_binary = byte_i;
+ for( int i = 0; i < 8; i++ )
+ {
+ current_bit = int_to_binary % 2;
+ int_to_binary = int_to_binary / 2;
+
+ if( current_bit )
+ {
+ fault = FAULT_CODE_ARRAY[ fault_code_index + i ];
+ cout << " " << fault << " -- Fault #" << return_fault_index_val( fault ) << endl;
+ faults_found.push_back( fault );
+ }
+ }
+
+ fault_code_index = fault_code_index + 8;
+ }
+ }
+
+ return faults_found;
+}
+
+
+
+int main()
+{
+ cout << "Testing print_vms_state function: " << endl;
+
+ broadcast_message testing_class;
+ vsm_state CAN_MSSG_VSM_STATE;
+
+ int test_CAN_message[9] = {0x0AA, 0, 1, 0, 0, 0, 0, 0, 0};
+
+ cout << "CAN Message--------------------" << endl;
+ cout << "{";
+ for (int i = 0; i < 9; i++)
+ {
+
+ cout << " " << test_CAN_message[i];
+ if (i != 8)
+ {
+ cout << ",";
+ }
+ }
+ cout << " }\n" << endl;
+
+ CAN_MSSG_VSM_STATE = testing_class.read_vsm_state(test_CAN_message);
+ cout << "\n\nThe VSM State retrieved from the CAN Message is: " << CAN_MSSG_VSM_STATE << endl;
+ cout << "Value of VSM State: " << return_vsm_state_val(CAN_MSSG_VSM_STATE) << endl;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ cout << "\n\n\nTesting print_inverter_state function: " << endl;
+ inverter_state CAN_MSSG_INVERTER_STATE;
+
+ int test_CAN_message_2[9] = {0x0AA, 0, 0, 2, 0, 0, 0, 0, 0};
+
+ cout << "CAN Message--------------------" << endl;
+ cout << "{";
+ for (int i = 0; i < 9; i++)
+ {
+
+ cout << " " << test_CAN_message_2[i];
+ if (i != 8)
+ {
+ cout << ",";
+ }
+ }
+ cout << " }\n" << endl;
+
+ CAN_MSSG_INVERTER_STATE = testing_class.read_inverter_state(test_CAN_message_2);
+ cout << "\nThe Inverter State retrieved from the CAN Message is: " << CAN_MSSG_INVERTER_STATE << endl;
+ cout << "Value of Inverter State: " << return_inverter_state_val(CAN_MSSG_INVERTER_STATE) << endl;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ cout << "\n\n\nTesting disable_broadcast_message function: " << endl;
+
+ int test_msg[9] = {0x0C1, 148, 0, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF};
+
+ cout << "CAN Message--------------------" << endl;
+ cout << "{ " << test_msg[0];
+ for (int i = 1; i < 9; i++)
+ cout << ", " << test_msg[i];
+ cout << " }\n" << endl;
+
+ disable_broadcast_message(test_msg, TEMPERATURE_2 | DIAG_DATA);
+
+ cout << "New CAN Message--------------------" << endl;
+ cout << "{ " << test_msg[0];
+ for (int i = 1; i < 9; i++)
+ cout << ", " << test_msg[i];
+ cout << " }\n" << endl;
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ cout << "----------------------------------------------------------------" << endl;
+ cout << "- -" << endl;
+ cout << "- CAN PM100 -" << endl;
+ cout << "- Fault Code Function Testing -" << endl;
+ cout << "- -" << endl;
+ cout << "- -" << endl;
+ cout << "- -" << endl;
+ cout << "----------------------------------------------------------------\n" << endl;
+
+ cout << "< Hello there! Here we'll test out reading Fault Codes from the PM100 >" << endl;
+ cout << "< >" << endl;
+ cout << "< >" << endl;
+ cout << "< >\n" << endl;
+
+ cout << "< The CAN message we're testing is: >" << endl;
+
+ broadcast_message testing_class;
+ int test_message_2[9] = { 0x0AB, 128, 32, 0, 0, 0, 0, 2, 0 };
+
+ cout << "< {";
+ for ( int i = 0; i < 8; i++ )
+ {
+ /*
+ if(i == 0)
+ {
+ cout << " 0x0" << hex << test_message_2[i] << ",";
+ continue;
+ }
+ */
+ cout << " " << test_message_2[i] << ",";
+ }
+ cout << " }\n" << endl;
+
+ vector returned_faults_vector;
+ returned_faults_vector = testing_class.read_fault_codes_VER_2( test_message_2 );
+
+
+}
diff --git a/Inverter/old/BROADCAST_MESSAGE.h b/Inverter/old/BROADCAST_MESSAGE.h
new file mode 100644
index 0000000..1ce598a
--- /dev/null
+++ b/Inverter/old/BROADCAST_MESSAGE.h
@@ -0,0 +1,183 @@
+#ifndef BROADCAST_MESSAGE_H
+#define BROADCAST_MESSAGE_H
+
+//#include
+#include
+#include
+#include
+
+// Reference 0x0AA - Internal States, Byte #0,1
+typedef enum vsm_state
+{
+ VSM_START,
+ PRE_CHARGE_INIT,
+ PRE_CHARGE_ACTIVE,
+ PRE_CHARGE_COMPLETE,
+ VSM_WAIT,
+ VSM_READY,
+ MOTOR_RUNNING,
+ BLINK_FAULT_CODE,
+ SHUTDOWN_IN_PROGRESS = 14,
+ RECYCLE_POWER,
+ NOT_A_VSM_STATE
+} vsm_state;
+
+// Reference 0x0AA - Internal States, Byte #2
+typedef enum inverter_state
+{
+ POWER_ON,
+ STOP,
+ OPEN_LOOP,
+ CLOSED_LOOP,
+ WAIT,
+ IDLE_RUN = 8,
+ IDLE_STOP,
+ NOT_AN_INVERTER_STATE = 13
+} inverter_state;
+
+// Reference Param Address 148
+typedef enum can_active_messages_lo_word
+{
+ // Data Byte 4
+ TEMPERATURE_1 = 0x0001,
+ TEMPERATURE_2 = 0x0002,
+ TEMPERATURE_3 = 0x0004,
+ ANALOG_INPUT_VOLTAGES = 0x0008,
+ DIGITAL_INPUT_STATUS = 0x0010,
+ MOTOR_POSITION_INFORMATION = 0x0020,
+ CURRENT_INFORMATION = 0x0040,
+ VOLTAGE_INFORMATION = 0x0080,
+ // Data Byte 5
+ FLUX_INFORMATION = 0x0100,
+ INTERNAL_VOLTAGES = 0x0200,
+ INTERNAL_STATES = 0x0400,
+ FAULT_CODES = 0x0800,
+ TORQUE_AND_TIMER_INFORMATION = 0x1000,
+ MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO = 0x2000,
+ FIRMWARE_INFORMATION = 0x4000,
+ DIAG_DATA = 0x8000
+} can_active_messages_lo_word;
+
+// Reference Param Address 148, should always be enabled (default)
+typedef enum can_active_messages_hi_word
+{
+ // Data Byte 6
+ SLAVE_MODE_COMMAND_MESSAGE = 6,
+ BMS_COMMAND_MESSAGE,
+ // Data Byte 7
+ OBD2_GENERAL_QUERY,
+ OBD2_SPECIFIC_QUERY,
+ OBD2_RESPONSE,
+ U2C_TX_MESSAGE,
+ U2C_RX_MESSAGE,
+ PARAMETER_RESPONSE_MESAGE,
+ PARAMETER_COMMAND_MESSAGE,
+ CAN_COMMAND_MESSAGE
+} can_active_messages_hi_word;
+
+//All types of Fault Codes
+typedef enum fault_code
+{
+ //POST FAULTS
+ //Byte 0
+ Hardware_Gate_Desaturation_Fault,
+ HW_Over_current_Fault,
+ Accelerator_Shorted,
+ Accelerator_Open,
+ Current_Sensor_Low,
+ Current_Sensor_High,
+ Module_Temperature_Low,
+ Module_Temperature_High,
+ //Byte 1
+ Control_PCB_Temperature_Low,
+ Control_PCB_Temperature_High,
+ Gate_Drive_PCB_Temperature_Low,
+ Gate_Drive_PCB_Temperature_High,
+ Sense_Voltage_Low_5V,
+ Sense_Voltage_High_5V,
+ Sense_Voltage_Low_12V,
+ Sense_Voltage_High_12V,
+ //Byte 2
+ Sense_Voltage_Low_2_5V,
+ Sense_Voltage_High_2_5V,
+ Sense_Voltage_Low_1_5V,
+ Sense_Voltage_High_1_5V,
+ DC_Bus_Voltage_High,
+ DC_Bus_Voltage_Low,
+ Pre_charge_Timeout,
+ Pre_charge_Voltage_Failure,
+ //Byte 3
+ EEPROM_Checksum_Invalid,
+ EEPROM_Data_Out_of_Range,
+ EEPROM_Update_Required,
+ RESERVED_1,
+ RESERVED_2,
+ RESERVED_3,
+ Brake_Shorted,
+ Brake_Open,
+ //Byte 4
+ //RUN FAULTS
+ Motor_Over_speed_Fault,
+ Over_current_Fault,
+ Over_voltage_Fault,
+ Inverter_Over_temperature_Fault,
+ Accelerator_Input_Shorted_Fault,
+ Accelerator_Input_Open_Fault,
+ Direction_Command_Fault,
+ Inverter_Response_Time_out_Fault,
+ //Byte 5
+ Hardware_Gate_Desaturation_RUN_Fault,
+ Hardware_Over_current_Fault,
+ Under_voltage_Fault,
+ CAN_Command_Message_Lost_Fault,
+ Motor_Over_temperature_Fault,
+ RESERVED_4,
+ RESERVED_5,
+ RESERVED_6,
+ //Byte 6
+ Brake_Input_Shorted_Fault,
+ Brake_Input_Open_Fault,
+ Module_A_Over_temperature_Fault,
+ Module_B_Over_temperature_Fault,
+ Module_C_Over_temperature_Fault,
+ PCB_Over_temperature_Fault,
+ Gate_Drive_Board_1_Over_temperature_Fault,
+ Gate_Drive_Board_2_Over_temperature_Fault,
+ //Byte 7
+ Gate_Drive_Board_3_Over_temperature_Fault,
+ Current_Sensor_Fault,
+ RESERVED_7,
+ Hardware_Over_Voltage_Fault,
+ RESERVED_8,
+ RESERVED_9,
+ Resolver_Not_Connected,
+ Inverter_Discharge_Active,
+
+ //Finally, error if the CAN mssg is NOT for fault codes
+ NOT_FAULT_CAN_MSSG
+
+} PM100_FAULT_CODE;
+
+
+
+class broadcast_message
+{
+public:
+ message_type broadcast_message;
+
+ vsm_state read_vsm_state(int message_arr[9]);
+ friend std::ostream &operator<<(std::ostream &lhs, vsm_state state);
+ friend int return_vsm_state_val(vsm_state state);
+
+ inverter_state read_inverter_state(int message_arr[9]);
+ friend std::ostream &operator<<(std::ostream &lhs, inverter_state state);
+ friend int return_inverter_state_val(inverter_state state);
+
+ void disable_broadcast_message(int CAN_mssg[9], int listOfMsgs);
+
+ vector read_fault_codes_VER_2( int CAN_mssg[9] );
+ friend ostream& operator<<( ostream& lhs, PM100_FAULT_CODE fault );
+ friend int return_fault_index_val( PM100_FAULT_CODE fault );
+};
+
+#endif
diff --git a/Inverter/old/COMMAND_MESSAGE.cpp b/Inverter/old/COMMAND_MESSAGE.cpp
new file mode 100644
index 0000000..05f9027
--- /dev/null
+++ b/Inverter/old/COMMAND_MESSAGE.cpp
@@ -0,0 +1,215 @@
+//#include
+//#include
+//#include
+#include
+#include
+//#include
+#include
+
+using namespace std;
+
+
+//given all inverter parameters, this creates an int array of the CAN message data bytes
+int* command_message::create_command_message ( message_type command_message,
+ float torque_val, //Value in N.m
+ float speed_val, //RPM
+ inverter_direction direction_command,
+ inverter_enable enable_command ){
+
+ //All necessary variables for CAN Message (data bytes)
+ int inverter_torque_val;
+ int data_high_byte;
+ int data_low_byte;
+ int direction_byte;
+ int enable_byte;
+
+ //There are 2 types of CAN Command Messages to generate:
+ //Torque Message code below
+ if( command_message == COMMAND_TOURQUE_M ){
+
+ //Calculate the int values for byte 0 & byte 1 (torque data)
+ //PM100 requires (Torque Val * 10) to be sent through CAN
+ if( torque_val > 0 ){
+ inverter_torque_val = int(torque_val * 10);
+ data_low_byte = inverter_torque_val % 256;
+ data_high_byte = inverter_torque_val / 256;
+ }
+ else if( torque_val < 0 ){
+ inverter_torque_val = int(torque_val * 10);
+ data_low_byte = ( inverter_torque_val & 255 );
+ data_high_byte = ( inverter_torque_val & 65280 ) >> 8;
+ }
+
+
+ //Set direction command byte accordingly
+ if( direction_command == REVERSE ){ direction_byte = 0; }
+ else if( direction_command == FORWARD ){ direction_byte = 1; }
+ else{
+ //SHOULD NOT BE HERE, raise ERROR
+ cout << "--ERROR-- Un-identified Inverter Direction Command" << endl;
+ }
+
+ //Set inverter enable byte accordingly
+ if( enable_command == ENABLE ){ enable_byte = 1; }
+ else if( enable_command == DISABLE ){ enable_byte = 0; }
+ else{
+ //SHOULD NOT BE HERE, raise ERROR
+ cout << "--ERROR-- Un-identified Inverter Enable Command" << endl;
+ }
+
+
+ //Finally, format the CAN message data bytes
+ //Represented as int array
+ static int can_data_bytes[8] = { data_low_byte, data_high_byte, 0, 0, direction_byte, enable_byte, 0, 0 };
+
+ /* DEBUG---PRINT OUT CAN DATA BYTES----------------------------------
+ cout << "Printintg CAN Message inside the function here:..." << endl;
+ for ( int i = 0; i < 8; i++ ) {
+ cout << can_data_bytes[i] << endl;
+ }-------------------------------------------------------------------
+ */
+
+ return can_data_bytes;
+ }
+
+
+
+
+
+
+ else if( command_message == COMMAND_SPEED_M ){
+
+
+ data_low_byte = int(speed_val) % 256;
+ data_high_byte = speed_val / 256;
+
+
+ if( direction_command == REVERSE ){ direction_byte = 0; }
+ else if( direction_command == FORWARD ){ direction_byte = 1; }
+ else{
+ //SHOULD NOT BE HERE, raise ERROR
+ cout << "--ERROR-- Un-identified Inverter Direction Command" << endl;
+ }
+
+ if( enable_command == ENABLE ){ enable_byte = 1; }
+ else if( enable_command == DISABLE ){ enable_byte = 0; }
+ else{
+ //SHOULD NOT BE HERE, raise ERROR
+ cout << "--ERROR-- Un-identified Inverter Enable Command" << endl;
+ }
+
+
+ //Finally, format the CAN message data bytes
+ static int can_data_bytes[8] = { 0, 0, data_low_byte, data_high_byte, direction_byte, enable_byte, 0, 0 };
+
+ /* DEBUG---PRINT OUT CAN DATA BYTES----------------------------------
+ cout << "Printintg CAN Message inside the function here:..." << endl;
+ for ( int i = 0; i < 8; i++ ) {
+ cout << can_data_bytes[i] << endl;
+ }-------------------------------------------------------------------
+ */
+
+
+ return can_data_bytes;
+ }
+
+
+
+}
+
+
+
+int main(){
+
+ char speed_or_torque;
+ char inv_direction;
+ float torque_val = 0;
+ float speed_val = 0;
+
+ //These variables are all custom made
+ command_message test_message; //message class
+ message_type test_type;
+ inverter_direction test_direction;
+ inverter_enable test_enable = ENABLE; //inverter enable
+
+
+ //BITWISE TESTING (ADAM)
+ /*
+ int test_int = 100;
+ int bitwise_not = ~test_int + 1;
+
+ cout << "test int: " << test_int << endl;
+ cout << "bitwise NOT: " << bitwise_not << endl;
+
+ cout << "binary of test int: " << bitset<16>(test_int) << endl;
+ cout << "binary of bitwise NOT: " << bitset<16>(bitwise_not) << endl;
+
+ int low_byte = ( bitwise_not & 255 );
+ int high_byte = ( bitwise_not & 65280 ) >> 8;
+ cout << "low byte: " << low_byte << endl;
+ cout << "high byte: " << high_byte << endl;
+ */
+
+
+ cout << "-----------------------------------------------------------------------------" << endl;
+ cout << "| PM100 CAN Bus Message Generator (TESTING) |" << endl;
+ cout << "| |" << endl;
+ cout << "| |" << endl;
+ cout << "| |" << endl;
+ cout << "-----------------------------------------------------------------------------" << endl;
+ cout << "\nWelcome :) \n" << endl;
+ cout << "Do you want to make a Speed or Torque Command Message?" << endl;
+ cout << " _______________________________" << endl;
+ cout << "| [s] for Speed, [t] for Torque |" << endl;
+ cout << "|_______________________________|" << endl;
+ cout << ">";
+ cin >> speed_or_torque;
+
+ if( speed_or_torque == 's' || speed_or_torque == 'S' ){
+
+ test_type = COMMAND_SPEED_M;
+ cout << "\nPlease enter a Speed Value: (RPM)" << endl;
+ cout << ">";
+ cin >> speed_val;
+ }
+ else if( speed_or_torque == 't' || speed_or_torque == 'T' ){
+
+ test_type = COMMAND_TOURQUE_M;
+ cout << "\nPlease enter a Torque Value: (N*m)" << endl;
+ cout << ">";
+ cin >> torque_val;
+ }
+
+ cout << "\nNow, specify the Inverter's Direction:" << endl;
+ cout << " ____________________________________________" << endl;
+ cout << "| [f] for FORWARD (default), [r] for REVERSE |" << endl;
+ cout << "|____________________________________________|" << endl;
+ cout << ">";
+ cin >> inv_direction;
+
+ if( inv_direction == 'f' || inv_direction == 'F' ){ test_direction = FORWARD; }
+ else if( inv_direction == 'r' || inv_direction == 'R' ){ test_direction = REVERSE; }
+
+
+
+
+ //test command message
+ //pass all the necessary parameters needed to make CAN Message
+ int *CAM_mssg = test_message.send_command_message( test_type, torque_val, speed_val, test_direction, test_enable );
+
+ //Printing out CAN Message (data bytes)
+ cout << "\n _______________________________________" << endl;
+ cout << "| CAN Message generated: |" << endl;
+ cout << "| { ";
+ for ( int i = 0; i < 8; i++ ) {
+ cout << CAM_mssg[i];
+ if( i != 7 ){ cout << ", "; }
+ }
+ cout << " }" << endl;
+ cout << "| |" << endl;
+ cout << "|_______________________________________|" << endl;
+
+
+
+}
+
diff --git a/Inverter/old/COMMAND_MESSAGE.h b/Inverter/old/COMMAND_MESSAGE.h
new file mode 100644
index 0000000..3c306f1
--- /dev/null
+++ b/Inverter/old/COMMAND_MESSAGE.h
@@ -0,0 +1,46 @@
+#ifndef COMMAND_MESSAGE_H
+#define COMMAND_MESSAGE_H
+
+//types of CAN messages
+typedef enum m_type {
+ BROADCAST_M,
+ COMMAND_TOURQUE_M,
+ COMMAND_SPEED_M
+} message_type;
+
+//command message variables for inverter
+typedef enum i_direction {
+ REVERSE, //clock-wise
+ FORWARD //counter-clock-wise
+} inverter_direction;
+
+typedef enum i_enable {
+ ENABLE,
+ DISABLE
+} inverter_enable;
+
+
+
+class command_message{
+
+ public:
+
+ message_type command_message;
+
+ int* create_command_message( message_type command_message,
+ float torque_val, //Value in N.m
+ float speed_val, //RPM
+ inverter_direction direction_command,
+ inverter_enable enable_command );
+
+
+
+
+
+
+
+
+
+};
+
+#endif
diff --git a/Inverter/src/Actuator.h b/Inverter/src/Actuator.h
new file mode 100644
index 0000000..37d7675
--- /dev/null
+++ b/Inverter/src/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/Inverter/src/Base.h b/Inverter/src/Base.h
new file mode 100644
index 0000000..623ae26
--- /dev/null
+++ b/Inverter/src/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/Inverter/src/Inverter.cpp b/Inverter/src/Inverter.cpp
new file mode 100644
index 0000000..ffdb9db
--- /dev/null
+++ b/Inverter/src/Inverter.cpp
@@ -0,0 +1,33 @@
+#include "Actuator.h"
+#include "Inverter.h"
+
+Inverter::Inverter(Serial_CAN* CANBus, arduino_t arduino) : Actuator(A_INVERTER, arduino, 0) {
+ this->CANBus = CANBus;
+}
+
+int* create_command_message (message_type command, float value, inverter_direction direction, inverter_enable enable){
+ int data_high_byte;
+ int data_low_byte;
+
+ if(command == COMMAND_TOURQUE_M){
+ if(value >= 0){
+ data_low_byte = int(value * 10) % 256;
+ data_high_byte = int(value * 10) / 256;
+ } else{
+ data_low_byte = ( int(value * 10) & 255 );
+ data_high_byte = ( int(value * 10) & 65280 ) >> 8;
+ }
+
+ static int can_data_bytes[8] = { data_low_byte, data_high_byte, 0, 0, direction, enable, 0, 0 };
+
+ return can_data_bytes;
+ } else if(command == COMMAND_SPEED_M){
+
+ data_low_byte = int(value) % 256;
+ data_high_byte = value / 256;
+
+ static int can_data_bytes[8] = { 0, 0, data_low_byte, data_high_byte, direction, enable, 0, 0 };
+
+ return can_data_bytes;
+ }
+}
\ No newline at end of file
diff --git a/Inverter/src/Inverter.h b/Inverter/src/Inverter.h
new file mode 100644
index 0000000..755b7ba
--- /dev/null
+++ b/Inverter/src/Inverter.h
@@ -0,0 +1,36 @@
+#ifndef INVERTER_H
+#define INVERTER_H
+
+#include "Actuator.h"
+#include "Serial_CAN_Module.h"
+
+//types of CAN messages
+typedef enum m_type {
+ BROADCAST_M,
+ COMMAND_TOURQUE_M,
+ COMMAND_SPEED_M
+} message_type;
+
+// COMMAND
+
+//command message variables for inverter
+typedef enum i_direction {
+ REVERSE, //clock-wise
+ FORWARD //counter-clock-wise
+} inverter_direction;
+
+typedef enum i_enable {
+ DISABLE,
+ ENABLE
+} inverter_enable;
+
+class Inverter : public Actuator {
+ public:
+ Inverter(Serial_CAN* CANBus, arduino_t arduino);
+ private:
+ Serial_CAN* CANBus;
+ errorlevel_t set(float target) override;
+ errorlevel_t init() override;
+};
+
+#endif
\ No newline at end of file
diff --git a/Inverter/src/InverterDebug.cpp b/Inverter/src/InverterDebug.cpp
new file mode 100644
index 0000000..ba5fad7
--- /dev/null
+++ b/Inverter/src/InverterDebug.cpp
@@ -0,0 +1,127 @@
+#include "Sensor.h"
+#include "InverterDebug.h"
+
+InverterDebug::InverterDebug(Serial_CAN* CANBus, arduino_t arduino) : Sensor(S_INVERTERDEBUG, arduino, 1000) {
+ this->CANBus = CANBus;
+}
+
+InverterDebug::init(){
+ return ERR_NONE;
+}
+
+errorlevel_t InverterDebug::read(t_datum* data, uint8_t numdata){
+ // TODO: Get can message
+ int msg[9] = {0,0,0,0,0,0,0,0,0};
+ data[0].data = read_vsm_state(msg);
+ data[1].data = read_inverter_state(msg);
+ data[2].data = read_fault_codes(msg);
+ // TODO: fault triggers return error
+ return ERR_NONE;
+}
+
+vsm_state read_vsm_state(int CAN_msg[9])
+{
+ if (CAN_msg[0] != 0x0AA || !((CAN_msg[2] >= 0 && CAN_msg[2] <= 7) || CAN_msg[2] == 14 || CAN_msg[2] == 15)){
+ // cout << "Message CAN ID is not 0x0AA, this is NOT a VSM message" << endl;
+ return NOT_A_VSM_STATE;
+ }
+ return (vsm_state)CAN_msg[2];
+}
+
+inverter_state read_inverter_state(int CAN_msg[9])
+{
+ if (CAN_msg[0] != 0x0AA || !((CAN_msg[3] >=0 && CAN_msg[3] <= 4) || CAN_msg[3] == 8 || CAN_msg[3] == 9))
+ {
+ // cout << "Message CAN ID is not 0xAA, this is NOT an inverter" << endl;
+ return NOT_AN_INVERTER_STATE;
+ }
+
+ return (inverter_state)CAN_msg[3];
+}
+
+/* Disable one or more messages at a time
+ * Example usage: disable_broadcast_message(test_msg, TEMPERATURE_2 | CURRENT_INFORMATION | DIAG_DATA);
+ */
+void disable_broadcast_message(int CAN_msg[9], int listOfMsgs)
+{
+ if (CAN_msg[0] != 0x0C1 || CAN_msg[1] != 148) // CAN ID
+ {
+ // cout << "Message CAN Address is not 0x0C1" << endl;
+ // cout << "Message Parameter Address is not 148" << endl;
+ return;
+ }
+
+ int loWord = (CAN_msg[6] << 8) | CAN_msg[5]; // loWord = [6] concatenated with [5]
+
+ if ((TEMPERATURE_1 & listOfMsgs) == TEMPERATURE_1)
+ loWord &= ~(1U);
+ if ((TEMPERATURE_2 & listOfMsgs) == TEMPERATURE_2)
+ loWord &= ~(1U << 1);
+ if ((TEMPERATURE_3 & listOfMsgs) == TEMPERATURE_3)
+ loWord &= ~(1U << 2);
+ if ((ANALOG_INPUT_VOLTAGES & listOfMsgs) == ANALOG_INPUT_VOLTAGES)
+ loWord &= ~(1U << 3);
+ if ((DIGITAL_INPUT_STATUS & listOfMsgs) == DIGITAL_INPUT_STATUS)
+ loWord &= ~(1U << 4);
+ if ((MOTOR_POSITION_INFORMATION & listOfMsgs) == MOTOR_POSITION_INFORMATION)
+ loWord &= ~(1U << 5);
+ if ((CURRENT_INFORMATION & listOfMsgs) == CURRENT_INFORMATION)
+ loWord &= ~(1U << 6);
+ if ((VOLTAGE_INFORMATION & listOfMsgs) == VOLTAGE_INFORMATION)
+ loWord &= ~(1U << 7);
+ if ((FLUX_INFORMATION & listOfMsgs) == FLUX_INFORMATION)
+ loWord &= ~(1U << 8);
+ if ((INTERNAL_VOLTAGES & listOfMsgs) == INTERNAL_VOLTAGES)
+ loWord &= ~(1U << 9);
+ if ((INTERNAL_STATES & listOfMsgs) == INTERNAL_STATES)
+ loWord &= ~(1U << 10);
+ if ((FAULT_CODES & listOfMsgs) == FAULT_CODES)
+ loWord &= ~(1U << 11);
+ if ((TORQUE_AND_TIMER_INFORMATION & listOfMsgs) == TORQUE_AND_TIMER_INFORMATION)
+ loWord &= ~(1U << 12);
+ if ((MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO & listOfMsgs) == MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO)
+ loWord &= ~(1U << 13);
+ if ((FIRMWARE_INFORMATION & listOfMsgs) == FIRMWARE_INFORMATION)
+ loWord &= ~(1U << 14);
+ if ((DIAG_DATA & listOfMsgs) == DIAG_DATA)
+ loWord &= ~(1U << 15);
+
+ // Separate loWord back into two bytes
+ CAN_msg[5] = loWord & 0xFF;
+ CAN_msg[6] = (loWord >> 8) & 0xFF;
+}
+
+int64_t read_fault_codes(int CAN_msg[9]) {
+ //extract the CAN ID & define return vector of fault codes
+ int CAN_ID = CAN_msg[0];
+ int64_t faults;
+
+ //check if CAN message is FAULT message
+ if( CAN_ID != 0x0AB ){
+ faults |= 1UL << 64;
+ } else if( CAN_ID == 0x0AB ){
+ int fault_byte = 0; //var used for indexing fault code array
+
+ //here we'll loop 8 times, analyze each CAN data byte
+ for( int msgbyte = 0; msgbyte < 8; msgbyte++ )
+ {
+ int byte_i = CAN_msg[msgbyte];
+
+ //vars to check each bit of current byte
+ int current_bit;
+ int int_to_binary = byte_i;
+ for( int i = 0; i < 8; i++ ){
+ current_bit = int_to_binary % 2;
+ int_to_binary = int_to_binary / 2;
+
+ if( current_bit ){
+ faults |= 1ULL << (fault_byte*8 + i);
+ }
+ }
+
+ fault_byte++;
+ }
+ }
+
+ return faults;
+}
\ No newline at end of file
diff --git a/Inverter/src/InverterDebug.h b/Inverter/src/InverterDebug.h
new file mode 100644
index 0000000..de65ce4
--- /dev/null
+++ b/Inverter/src/InverterDebug.h
@@ -0,0 +1,176 @@
+#ifndef INVERTERDEBUG_H
+#define INVERTERDEBUG_H
+
+#include "Sensor.h"
+#include "Serial_CAN_Module.h"
+
+//types of CAN messages
+typedef enum m_type {
+ BROADCAST_M,
+ COMMAND_TOURQUE_M,
+ COMMAND_SPEED_M
+} message_type;
+
+// BROADCAST
+
+typedef enum vsm_state
+{
+ VSM_START,
+ PRE_CHARGE_INIT,
+ PRE_CHARGE_ACTIVE,
+ PRE_CHARGE_COMPLETE,
+ VSM_WAIT,
+ VSM_READY,
+ MOTOR_RUNNING,
+ BLINK_FAULT_CODE,
+ SHUTDOWN_IN_PROGRESS = 14,
+ RECYCLE_POWER,
+ NOT_A_VSM_STATE
+} vsm_state;
+
+// Reference 0x0AA - Internal States, Byte #2
+typedef enum inverter_state
+{
+ POWER_ON,
+ STOP,
+ OPEN_LOOP,
+ CLOSED_LOOP,
+ WAIT,
+ IDLE_RUN = 8,
+ IDLE_STOP,
+ NOT_AN_INVERTER_STATE = 13
+} inverter_state;
+
+// Reference Param Address 148
+typedef enum can_active_messages_lo_word
+{
+ // Data Byte 4
+ TEMPERATURE_1 = 0x0001,
+ TEMPERATURE_2 = 0x0002,
+ TEMPERATURE_3 = 0x0004,
+ ANALOG_INPUT_VOLTAGES = 0x0008,
+ DIGITAL_INPUT_STATUS = 0x0010,
+ MOTOR_POSITION_INFORMATION = 0x0020,
+ CURRENT_INFORMATION = 0x0040,
+ VOLTAGE_INFORMATION = 0x0080,
+ // Data Byte 5
+ FLUX_INFORMATION = 0x0100,
+ INTERNAL_VOLTAGES = 0x0200,
+ INTERNAL_STATES = 0x0400,
+ FAULT_CODES = 0x0800,
+ TORQUE_AND_TIMER_INFORMATION = 0x1000,
+ MOD_INDEX_FLUX_WEAKENING_OUTPUT_INFO = 0x2000,
+ FIRMWARE_INFORMATION = 0x4000,
+ DIAG_DATA = 0x8000
+} can_active_messages_lo_word;
+
+// Reference Param Address 148, should always be enabled (default)
+typedef enum can_active_messages_hi_word
+{
+ // Data Byte 6
+ SLAVE_MODE_COMMAND_MESSAGE = 6,
+ BMS_COMMAND_MESSAGE,
+ // Data Byte 7
+ OBD2_GENERAL_QUERY,
+ OBD2_SPECIFIC_QUERY,
+ OBD2_RESPONSE,
+ U2C_TX_MESSAGE,
+ U2C_RX_MESSAGE,
+ PARAMETER_RESPONSE_MESAGE,
+ PARAMETER_COMMAND_MESSAGE,
+ CAN_COMMAND_MESSAGE
+} can_active_messages_hi_word;
+
+//All types of Fault Codes
+typedef enum fault_code
+{
+ //POST FAULTS
+ //Byte 0
+ Hardware_Gate_Desaturation_Fault,
+ HW_Over_current_Fault,
+ Accelerator_Shorted,
+ Accelerator_Open,
+ Current_Sensor_Low,
+ Current_Sensor_High,
+ Module_Temperature_Low,
+ Module_Temperature_High,
+ //Byte 1
+ Control_PCB_Temperature_Low,
+ Control_PCB_Temperature_High,
+ Gate_Drive_PCB_Temperature_Low,
+ Gate_Drive_PCB_Temperature_High,
+ Sense_Voltage_Low_5V,
+ Sense_Voltage_High_5V,
+ Sense_Voltage_Low_12V,
+ Sense_Voltage_High_12V,
+ //Byte 2
+ Sense_Voltage_Low_2_5V,
+ Sense_Voltage_High_2_5V,
+ Sense_Voltage_Low_1_5V,
+ Sense_Voltage_High_1_5V,
+ DC_Bus_Voltage_High,
+ DC_Bus_Voltage_Low,
+ Pre_charge_Timeout,
+ Pre_charge_Voltage_Failure,
+ //Byte 3
+ EEPROM_Checksum_Invalid,
+ EEPROM_Data_Out_of_Range,
+ EEPROM_Update_Required,
+ RESERVED_1,
+ RESERVED_2,
+ RESERVED_3,
+ Brake_Shorted,
+ Brake_Open,
+ //Byte 4
+ //RUN FAULTS
+ Motor_Over_speed_Fault,
+ Over_current_Fault,
+ Over_voltage_Fault,
+ Inverter_Over_temperature_Fault,
+ Accelerator_Input_Shorted_Fault,
+ Accelerator_Input_Open_Fault,
+ Direction_Command_Fault,
+ Inverter_Response_Time_out_Fault,
+ //Byte 5
+ Hardware_Gate_Desaturation_RUN_Fault,
+ Hardware_Over_current_Fault,
+ Under_voltage_Fault,
+ CAN_Command_Message_Lost_Fault,
+ Motor_Over_temperature_Fault,
+ RESERVED_4,
+ RESERVED_5,
+ RESERVED_6,
+ //Byte 6
+ Brake_Input_Shorted_Fault,
+ Brake_Input_Open_Fault,
+ Module_A_Over_temperature_Fault,
+ Module_B_Over_temperature_Fault,
+ Module_C_Over_temperature_Fault,
+ PCB_Over_temperature_Fault,
+ Gate_Drive_Board_1_Over_temperature_Fault,
+ Gate_Drive_Board_2_Over_temperature_Fault,
+ //Byte 7
+ Gate_Drive_Board_3_Over_temperature_Fault,
+ Current_Sensor_Fault,
+ RESERVED_7,
+ Hardware_Over_Voltage_Fault,
+ RESERVED_8,
+ RESERVED_9,
+ Resolver_Not_Connected,
+ Inverter_Discharge_Active,
+
+ //Finally, error if the CAN mssg is NOT for fault codes
+ NOT_FAULT_CAN_MSSG
+
+} PM100_FAULT_CODE;
+
+class InverterDebug : public Sensor {
+ public:
+ InverterDebug(Serial_CAN* CANBus, arduino_t arduino);
+ private:
+ Serial_CAN* CANBus;
+ errorlevel_t read(t_datum* data, uint8_t numdata) override;
+ errorlevel_t init() override;
+};
+
+#endif
\ No newline at end of file
diff --git a/Inverter/src/Sensor.h b/Inverter/src/Sensor.h
new file mode 100644
index 0000000..3fa9c50
--- /dev/null
+++ b/Inverter/src/Sensor.h
@@ -0,0 +1,69 @@
+#ifndef Sensor_H
+#define Sensor_H
+
+#include "Base.h"
+
+// Sensor identifiers
+typedef enum sensors_t {
+ S_OPT2002,
+ S_VN200,
+ S_PROSENSERTD,
+ S_TMP006,
+ S_MPU9250,
+ S_DCT500,
+ S_SPTD25_20_1000H,
+ S_SPTD25_20_0200A,
+ S_CANBUS,
+ S_INVERTERDEBUG
+} sensors_t;
+
+// Single datapoint
+typedef struct t_datum {
+ float data;
+ const char* units;
+} t_datum;
+
+// All sensor state info + latest datum - used as the "cache" in the sensor object
+// TODO: Replace state enums with state structs containing messages, etc.
+typedef struct SensorState {
+ errorlevel_t error;
+ debuglevel_t debug;
+ uint16_t timestamp; //Last data update (millis since start)
+ t_datum* data; //Array of datum
+ uint8_t numdata;
+} SensorState;
+
+// Wrapper for all sensor stuff - this is what gets passed to the main computer
+typedef struct SensorData {
+ sensors_t sensor;
+ arduino_t arduino;
+ SensorState state;
+} SensorData;
+
+struct t_datasetup {
+ uint8_t numdata;
+ const char** units;
+};
+
+// Sensor class - note the difference in exposure and implementation in read/init and getRead/begin
+class Sensor{
+ private:
+ unsigned long delta; //The minimum time (milliseconds) between sensor updates.
+ unsigned long lastread; //Timestamp of last read ATTEMPT
+ protected:
+ // Sensor-specific functionality initialize and read functions - to be implemented by sensor classes
+ virtual errorlevel_t init() = 0; //Connect to sensor, calibrate, set data count and units, and update state accordingly
+ virtual errorlevel_t read(t_datum* data, uint8_t numdata) = 0; //Get ALL data from the sensor hardware -> data[i in numdata]
+
+ // State and IDs
+ SensorState state; //Stores all the latest state data for this sensor.
+ public:
+ arduino_t arduino;
+ sensors_t sensor;
+ // Wrappers return pointer to updated state
+ SensorState* update(); //Calls read(), manages delta, and wraps all t_datum
+ SensorState* begin(); //Sets state in accordance with init()
+ Sensor(sensors_t sensor, arduino_t arduino, t_datasetup setup, unsigned long delta);
+};
+
+#endif
\ No newline at end of file
diff --git a/Inverter/src/Serial_CAN_Module.cpp b/Inverter/src/Serial_CAN_Module.cpp
new file mode 100644
index 0000000..c1c6638
--- /dev/null
+++ b/Inverter/src/Serial_CAN_Module.cpp
@@ -0,0 +1,408 @@
+// ID3 ID2 ID1 ID0 EXT RTR DTA0 DTA1 DTA2 DTA3 DTA4 DTA5 DTA6 DTA7
+
+#include
+#include
+
+SoftwareSerial *canSerial = NULL;
+
+void Serial_CAN::begin(int can_tx, int can_rx, unsigned long baud)
+{
+ canSerial = new SoftwareSerial(can_tx, can_rx);
+ //Serial.println("Hello, we are inside begin()");
+ canSerial->begin(baud);
+}
+
+unsigned char Serial_CAN::send(unsigned long id, uchar ext, uchar rtrBit, uchar len, const uchar *buf)
+{
+ unsigned char dta[14] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+ dta[0] = id>>24; // id3
+ dta[1] = id>>16&0xff; // id2
+ dta[2] = id>>8&0xff; // id1
+ dta[3] = id&0xff; // id0
+
+ dta[4] = ext;
+ dta[5] = rtrBit;
+
+
+ for(int i=0; iwrite(dta[i]);
+ }
+
+ for(int i=0; i<14; i++)
+ {
+ //Serial.print( "Sending data frame:" );
+ //Serial.println( dta[i] );
+ }
+
+
+}
+
+
+// 0: no data
+// 1: get data
+unsigned char Serial_CAN::recv(unsigned long *id, uchar *buf)
+{
+ if(canSerial->available())
+ {
+ unsigned long timer_s = millis();
+
+ int len = 0;
+ uchar dta[20];
+
+ while(1)
+ {
+ while(canSerial->available())
+ {
+ dta[len++] = canSerial->read();
+ if(len == 12)
+ break;
+
+ if((millis()-timer_s) > 10)
+ {
+ canSerial->flush();
+ return 0; // Reading 12 bytes should be faster than 10ms, abort if it takes longer, we loose the partial message in this case
+ }
+ }
+
+ if(len == 12) // Just to be sure, must be 12 here
+ {
+ unsigned long __id = 0;
+
+ for(int i=0; i<4; i++) // Store the id of the sender
+ {
+ __id <<= 8;
+ __id += dta[i];
+ }
+
+ *id = __id;
+
+ for(int i=0; i<8; i++) // Store the message in the buffer
+ {
+ buf[i] = dta[i+4];
+ }
+ return 1;
+ }
+
+ if((millis()-timer_s) > 10)
+ {
+ canSerial->flush();
+ return 0; // Reading 12 bytes should be faster than 10ms, abort if it takes longer, we loose the partial message in this case
+ }
+
+ }
+ }
+
+ return 0;
+}
+
+unsigned char Serial_CAN::cmdOk(char *cmd)
+{
+
+ unsigned long timer_s = millis();
+ unsigned char len = 0;
+
+ canSerial->println(cmd);
+
+ //Serial.println(cmd);
+ //Serial.println("Printing cmd above.");
+
+ while(1)
+ {
+ if(millis()-timer_s > 500)
+ {
+ return 0;
+ }
+
+ while(canSerial->available())
+ {
+
+ str_tmp[len++] = canSerial->read();
+ timer_s = millis();
+ }
+
+ if(len >= 4 && str_tmp[len-1] == '\n' && str_tmp[len-2] == '\r' && str_tmp[len-3] == 'K' && str_tmp[len-4] == 'O')
+ {
+ clear();
+ return 1;
+ }
+
+ }
+}
+
+/*
+value 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18
+rate(kb/s) 5 10 20 25 31.2 33 40 50 80 83.3 95 100 125 200 250 500 666 1000
+*/
+unsigned char Serial_CAN::canRate(unsigned char rate)
+{
+ double rates[18] = {5, 10, 20, 25, 31.2, 33, 40, 50, 80, 83.3, 95, 100, 125, 200, 250, 500, 666, 1000};
+
+ enterSettingMode();
+ if(rate < 10)
+ sprintf(str_tmp, "AT+C=0%d\r\n", rate);
+ else
+ sprintf(str_tmp, "AT+C=%d\r\n", rate);
+
+ int ret = cmdOk(str_tmp);
+
+ Serial.print("Serial CAN Rate set to: ");
+ Serial.println(rates[rate-1]);
+
+ exitSettingMode();
+ return ret;
+}
+
+/*
+value 0 1 2 3 4
+baud rate(b/s) 9600 19200 38400 57600 115200
+*/
+
+unsigned char Serial_CAN::baudRate(unsigned char rate)
+{
+ unsigned long baud[5] = {9600, 19200, 38400, 57600, 115200};
+ int baudNow = 0;
+
+ for(int i=0; i<5; i++)
+ {
+ canSerial->begin(baud[i]);
+ canSerial->print("+++");
+ delay(100);
+
+ if(cmdOk( (char*)"AT\r\n" ))
+ {
+ //Serial.print("SERIAL BAUD RATE IS: ");
+ //Serial.println(baud[i]);
+ baudNow = i;
+ break;
+ }
+ }
+
+ sprintf(str_tmp, "AT+S=%d\r\n", rate);
+ cmdOk(str_tmp);
+
+ canSerial->begin(baud[rate]);
+
+ int ret = cmdOk( (char*)"AT\r\n" );
+
+ if(ret)
+ {
+ Serial.print("Serial Baud Rate set to: ");
+ Serial.println(baud[rate]);
+ }
+
+ exitSettingMode();
+ return ret;
+}
+
+
+void Serial_CAN::clear()
+{
+ unsigned long timer_s = millis();
+ while(1)
+ {
+ if(millis()-timer_s > 50)return;
+ while(canSerial->available())
+ {
+ canSerial->read();
+ timer_s = millis();
+ }
+ }
+}
+
+unsigned char Serial_CAN::enterSettingMode()
+{
+ canSerial->print("+++");
+ clear();
+
+ //Serial.println("Inside enterSettingMode()");
+
+ return 1;
+}
+
+unsigned char Serial_CAN::exitSettingMode()
+{
+ clear();
+ int ret = cmdOk((char*)"AT+Q\r\n");
+ clear();
+ return ret;
+}
+
+void make8zerochar(int n, char *str, unsigned long num)
+{
+ for(int i=0; i>= 4;
+ }
+ str[n] = '\0';
+}
+
+/*
++++ Switch from Normal mode to Config mode
+AT+S=[value] Set serial baud rate
+AT+C=[value] Set CAN Bus baud rate
+AT+M=[N][EXT][value] Set mask,AT+M=[1][0][000003DF]
+AT+F=[N][EXT][value] Set filter,AT+F=[1][0][000003DF]
+AT+Q Switch to Normal Mode
+*/
+unsigned char Serial_CAN::setMask(unsigned long *dta)
+{
+ enterSettingMode();
+ char __str[10];
+
+
+ for(int i=0; i<2; i++)
+ {
+ make8zerochar(8, __str, dta[1+2*i]);
+ //Serial.println(__str);
+ sprintf(str_tmp, "AT+M=[%d][%d][", i, dta[2*i]);
+ for(int i=0; i<8; i++)
+ {
+ str_tmp[12+i] = __str[i];
+ }
+ str_tmp[20] = ']';
+ str_tmp[21] = '\r';
+ str_tmp[22] = '\n';
+ str_tmp[23] = '\0';
+
+ //Serial.println(str_tmp);
+
+ if(!cmdOk(str_tmp))
+ {
+ Serial.print("mask fail - ");
+ Serial.println(i);
+ exitSettingMode();
+ return 0;
+ }
+ clear();
+ delay(10);
+ //
+ }
+ exitSettingMode();
+ return 1;
+
+}
+
+unsigned char Serial_CAN::setFilt(unsigned long *dta)
+{
+ enterSettingMode();
+
+ char __str[10];
+
+ for(int i=0; i<6; i++)
+ {
+ make8zerochar(8, __str, dta[1+2*i]);
+ //Serial.println(__str);
+ sprintf(str_tmp, "AT+F=[%d][%d][", i, dta[2*i]);
+ for(int i=0; i<8; i++)
+ {
+ str_tmp[12+i] = __str[i];
+ }
+ str_tmp[20] = ']';
+ str_tmp[21] = '\r';
+ str_tmp[22] = '\n';
+ str_tmp[23] = '\0';
+
+ //Serial.println(str_tmp);
+
+ clear();
+ if(!cmdOk(str_tmp))
+ {
+ //Serial.print("filt fail at - ");
+ //Serial.println(i);
+ exitSettingMode();
+ return 0;
+ }
+ clear();
+ delay(10);
+ //
+ }
+ exitSettingMode();
+ return 1;
+}
+
+/*
+value 0 1 2 3 4
+baud rate(b/s) 9600 19200 38400 57600 115200
+*/
+unsigned char Serial_CAN::factorySetting()
+{
+ // check baudrate
+ unsigned long baud[5] = {9600, 19200, 38400, 57600, 115200};
+
+ for(int i=0; i<5; i++)
+ {
+ canSerial->begin(baud[i]);
+ canSerial->print("+++");
+ delay(100);
+
+ if(cmdOk( (char*)"AT\r\n"))
+ {
+ Serial.print("SERIAL BAUD RATE IS: ");
+ Serial.println(baud[i]);
+ baudRate(0); // set serial baudrate to 9600
+ Serial.println("SET SERIAL BAUD RATE TO: 9600 OK");
+ canSerial->begin(9600);
+ break;
+ }
+ }
+
+ if(canRate(CAN_RATE_500))
+ {
+ Serial.println("SET CAN BUS BAUD RATE TO 500Kb/s OK");
+ }
+ else
+ {
+ Serial.println("SET CAN BUS BAUD RATE TO 500Kb/s FAIL");
+ return 0;
+ }
+
+ unsigned long mask[4] = {0, 0, 0, 0,};
+ unsigned long filt[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
+
+ if(setFilt(filt))
+ {
+ Serial.println("FACTORY SETTING FILTS OK");
+ }
+ else
+ {
+ Serial.println("FACTORY SETTING FILTS FAIL");
+ return 0;
+ }
+
+ if(setMask(mask))
+ {
+ Serial.println("FACTORY SETTING MASKS OK");
+ }
+ else
+ {
+ Serial.println("FACTORY SETTING MASKS FAIL");
+ return 0;
+ }
+
+ return 1;
+}
+
+void Serial_CAN::debugMode()
+{
+ while(Serial.available())
+ {
+ canSerial->write(Serial.read());
+ }
+
+ while(canSerial->available())
+ {
+ Serial.write(canSerial->read());
+ }
+}
+
+// END FILE
diff --git a/Inverter/src/Serial_CAN_Module.h b/Inverter/src/Serial_CAN_Module.h
new file mode 100644
index 0000000..c053ccf
--- /dev/null
+++ b/Inverter/src/Serial_CAN_Module.h
@@ -0,0 +1,57 @@
+#ifndef __SERIAL_CAN_MODULE_H__
+#define __SERIAL_CAN_MODULE_H__
+// ID3 ID2 ID1 ID0 EXT RTR DTA0 DTA1 DTA2 DTA3 DTA4 DTA5 DTA6 DTA7
+#include
+#define uchar unsigned char
+
+
+#define CAN_RATE_5 1
+#define CAN_RATE_10 2
+#define CAN_RATE_20 3
+#define CAN_RATE_25 4
+#define CAN_RATE_31_2 5
+#define CAN_RATE_33 6
+#define CAN_RATE_40 7
+#define CAN_RATE_50 8
+#define CAN_RATE_80 9
+#define CAN_RATE_83_3 10
+#define CAN_RATE_95 11
+#define CAN_RATE_100 12
+#define CAN_RATE_125 13
+#define CAN_RATE_200 14
+#define CAN_RATE_250 15
+#define CAN_RATE_500 16
+#define CAN_RATE_666 17
+#define CAN_RATE_1000 18
+
+#define SERIAL_RATE_9600 0
+#define SERIAL_RATE_19200 1
+#define SERIAL_RATE_38400 2
+#define SERIAL_RATE_57600 3
+#define SERIAL_RATE_115200 4
+
+class Serial_CAN
+{
+private:
+ unsigned char cmdOk(char *cmd);
+ unsigned char enterSettingMode();
+ unsigned char exitSettingMode();
+ void clear();
+ char str_tmp[100];
+public:
+
+ void begin(int can_tx, int can_rx, unsigned long baud);
+ unsigned char send(unsigned long id, uchar ext, uchar rtrBit, uchar len, const uchar *buf);
+ unsigned char recv(unsigned long *id, uchar *buf);
+
+ unsigned char canRate(unsigned char rate);
+ unsigned char baudRate(unsigned char rate);
+
+ unsigned char setMask(unsigned long *dta);
+ unsigned char setFilt(unsigned long *dta);
+
+ unsigned char factorySetting();
+ void debugMode();
+
+};
+#endif
\ No newline at end of file
diff --git a/Inverter/tests/recv_basic_test.ino b/Inverter/tests/recv_basic_test.ino
new file mode 100644
index 0000000..29a3b51
--- /dev/null
+++ b/Inverter/tests/recv_basic_test.ino
@@ -0,0 +1,56 @@
+// RECV EXAMPLE OF SERIAL CAN MODULE
+// unsigned char recv(unsigned long *id, uchar *buf);
+// SUPPORT: joney.sui@longan-labs.cc
+//First recv() test by Adam P
+
+#include
+#include
+
+Serial_CAN can;
+
+#define can_tx 10 //TX of Serial CAN Module connected to D10
+#define can_rx 11 //RX of Serial CAN Module connected to D11
+
+
+void setup()
+{
+ Serial.begin(9600);
+ while(!Serial);
+ can.begin(can_tx, can_rx, 9600);
+
+ if(can.canRate(CAN_RATE_500))
+ {
+ Serial.println("Set CAN rate OK");
+ }
+ else
+ {
+ Serial.println("Set CAN rate FAIL");
+ }
+}
+
+unsigned long id = 5;
+unsigned char dta[8];
+
+// send(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf);
+void loop()
+{
+
+ can.debugMode();
+ if(can.recv(&id, dta))
+ {
+ Serial.print("GETTING DATA FROM ID: ");
+ Serial.println(id);
+ for(int i=0; i<8; i++)
+ {
+ Serial.print("0x");
+ Serial.print(dta[i], HEX);
+ Serial.print('\t');
+ }
+ Serial.println();
+ }
+ else{
+ //Serial.print("Didn't work!!!");
+ }
+}
+
+// END FILE
diff --git a/Inverter/tests/recv_mask_filt_test_2.ino b/Inverter/tests/recv_mask_filt_test_2.ino
new file mode 100644
index 0000000..17c653a
--- /dev/null
+++ b/Inverter/tests/recv_mask_filt_test_2.ino
@@ -0,0 +1,75 @@
+// RECV EXAMPLE OF SERIAL CAN MODULE - WITH MASK/FILTERING
+//
+// SUPPORT: joney.sui@longan-labs.cc
+//Second recv() test by Adam P
+
+#include
+#include
+
+Serial_CAN can;
+
+#define can_tx 10 //TX of Serial CAN Module connected to D10
+#define can_rx 11 //RX of Serial CAN Module connected to D11
+
+unsigned long mask[4] =
+{
+ 0, 0x0f, // ext, maks 0
+ 0, 0x0f, // ext, mask 1
+};
+
+unsigned long filt[12] =
+{
+ 0, 0xff, // ext, filt 0
+ 0, 0xff, // ext, filt 1
+ 0, 0xff, // ext, filt 2
+ 0, 0xff, // ext, filt 3
+ 0, 0xff, // ext, filt 4
+ 0, 0xff, // ext, filt 5
+};
+
+void setup()
+{
+ Serial.begin(9600);
+ while(!Serial);
+ can.begin(can_tx, can_rx, 9600); // tx, rx
+
+ if(can.setFilt(filt))
+ {
+ Serial.println("set filt ok");
+ }
+ else
+ {
+ Serial.println("set filt fail");
+ }
+
+ if(can.setMask(mask))
+ {
+ Serial.println("set mask ok");
+ }
+ else
+ {
+ Serial.println("set mask fail");
+ }
+
+}
+
+void loop()
+{
+ unsigned long id = 0;
+ unsigned char dta[8];
+
+ if(can.recv(&id, dta))
+ {
+ Serial.print("GET DATA FROM ID: ");
+ Serial.println(id);
+ for(int i=0; i<8; i++)
+ {
+ Serial.print("0x");
+ Serial.print(dta[i], HEX);
+ Serial.print('\t');
+ }
+ Serial.println();
+ }
+}
+
+// END FILE
diff --git a/Inverter/tests/send_basic_test.ino b/Inverter/tests/send_basic_test.ino
new file mode 100644
index 0000000..39368be
--- /dev/null
+++ b/Inverter/tests/send_basic_test.ino
@@ -0,0 +1,37 @@
+// SEND EXAMPLE OF SERIAL CAN MODULE
+// unsigned char send(unsigned long id, uchar ext, uchar rtrBit, uchar len, const uchar *buf);
+// SUPPORT: joney.sui@longan-labs.cc
+//First send() test by Adam P
+
+#include
+#include
+
+Serial_CAN can;
+
+#define can_tx 10 //TX of Serial CAN Module connected to D10
+#define can_rx 11 //RX of Serial CAN Module connected to D11
+
+
+void setup()
+{
+ Serial.begin(9600); //Baud Rates: 9600, 19200, 38400, 57600, 74880, 115200
+ //9600 works the best, higher rates start to have problems
+ can.begin(can_tx, can_rx, 9600);
+ Serial.println("Starting:");
+ //can.debugMode();
+}
+
+
+unsigned char dta[8] = {1, 2, 3, 4, 5, 10, 11, 12};
+
+
+// send(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf);
+void loop()
+{
+ can.send(0x77, 0, 0, 8, dta); // SEND TO ID:0X77
+ // CAN ID is not important for testing, all frames will be recieved
+ delay(100);
+ //can.debugMode();
+}
+
+// END FILE
diff --git a/Inverter/tests/send_mask_filt_test_2.ino b/Inverter/tests/send_mask_filt_test_2.ino
new file mode 100644
index 0000000..7d556e7
--- /dev/null
+++ b/Inverter/tests/send_mask_filt_test_2.ino
@@ -0,0 +1,37 @@
+// SEND EXAMPLE OF SERIAL CAN MODULE - WITH MASK/FILTERING
+// unsigned char send(unsigned long id, uchar ext, uchar rtrBit, uchar len, const uchar *buf);
+// SUPPORT: joney.sui@longan-labs.cc
+//Second send() test by Adam P
+
+#include
+#include
+
+Serial_CAN can;
+
+#define can_tx 10 //TX of Serial CAN Module connected to D10
+#define can_rx 11 //RX of Serial CAN Module connected to D11
+
+
+void setup()
+{
+ Serial.begin(9600); //Baud Rates: 9600, 19200, 38400, 57600, 74880, 115200
+ //9600 works the best, higher rates start to have problems
+ can.begin(can_tx, can_rx, 9600);
+ Serial.println("Starting:");
+ //can.debugMode();
+}
+
+
+unsigned char dta[8] = {1, 2, 3, 4, 5, 10, 11, 12};
+
+
+// send(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf);
+void loop()
+{
+ can.send(0x0f, 0, 0, 8, dta); // SEND TO ID:0x0f
+ // CAN ID is not important for testing, all frames will be recieved
+ delay(100);
+ //can.debugMode();
+}
+
+// END FILE
diff --git a/Sensor.h b/Sensor.h
index 9d384e4..3fa9c50 100644
--- a/Sensor.h
+++ b/Sensor.h
@@ -13,7 +13,8 @@ typedef enum sensors_t {
S_DCT500,
S_SPTD25_20_1000H,
S_SPTD25_20_0200A,
- S_CANBUS
+ S_CANBUS,
+ S_INVERTERDEBUG
} sensors_t;
// Single datapoint