diff --git a/Libraries/mcp_can/mcp_can.h b/Libraries/mcp_can/mcp_can.h index 7e3bd2ca..1c77e4ae 100644 --- a/Libraries/mcp_can/mcp_can.h +++ b/Libraries/mcp_can/mcp_can.h @@ -50,6 +50,16 @@ #define MAX_CHAR_IN_MESSAGE 8 +// This is not part of the actual library. Added as FlexCAN-style interface. +typedef struct CAN_message_t { + uint32_t id; // can identifier + uint8_t ext; // identifier is extended + uint8_t rtr; // remote transmission request packet type + uint8_t len; // length of data + uint16_t timeout; // milliseconds, zero will disable waiting + uint8_t buf[8]; +} CAN_message_t; + class MCP_CAN { private: @@ -131,6 +141,22 @@ class MCP_CAN unsigned long getCanId(void); // get can id when receive byte isRemoteRequest(void); // get RR flag when receive byte isExtendedFrame(void); // did we recieve 29bit frame? + + // This is not part of the actual library. Added as FlexCAN-style interface. + inline int read(CAN_message_t& msg) { + if (checkReceive() != CAN_MSGAVAIL) + return false; + readMsgBuf(&msg.len, msg.buf); + msg.id = can_id; + msg.ext = ext_flg; + msg.rtr = rtr; + msg.timeout = 0; + return true; + } + + inline int write(CAN_message_t& msg) { + return sendMsgBuf(msg.id, msg.ext, msg.rtr, msg.len, msg.buf); + } }; #endif diff --git a/Utilities/flexcan_tester_rev2/README.md b/Utilities/flexcan_tester_rev2/README.md new file mode 100644 index 00000000..514d3ce3 --- /dev/null +++ b/Utilities/flexcan_tester_rev2/README.md @@ -0,0 +1,14 @@ +This utility operates on the assumption that you have two Teensy controllers, one running the transmitter code and one running the receiver code. + +Switch between send and receive configurations by switching which header is included in [flexcan_tester_rev2.ino](./flexcan_tester_rev2.ino). + +[receiver.h](./receiver.h) and [transmitter.h](./transmitter.h) each defines two functions: + +``` +void synchronize(); +template inline T handle_message(unsigned id, T data); +``` + +This utility is capable of transmitting a series of messages and validating the ouput. `synchronize()` is used to ensure that both programs are on the same page regarding which frame is being sent. `handle_message(id, data)` is used to actually send or receive a message over FlexCAN. data should always be a member class of the [HyTech_CAN](../Libraries/HyTech_CAN) library. + +There is a `print()` helper function defined in [flexcan_tester_rev2.h](./flexcan_tester_rev2.h). This prints the ID and length of the messages received. There is no provision for printing the contents of the message - it is recommended that users either extend the `print()` function to suit their purposes or print the data in `loop()` using the data returned by `handle_message()`. If the [tcu-refactor](https://github.com/hytech-racing/code-2020/tree/tcu-refactor) branch has been merged in, then most classes should already have some kind of `print()` member function, which can be activated by uncommenting `#define HT_DEBUG_EN` in [flexcan_tester_rev2.ino](./flexcan_tester_rev2.ino). \ No newline at end of file diff --git a/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.h b/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.h new file mode 100644 index 00000000..493b326b --- /dev/null +++ b/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +// I'm lazy so this is how we're handling CAN library switching +#ifdef HT_CAN_MODE_FLEXCAN +#include +extern FlexCAN CAN; + +#elif defined(HT_CAN_MODE_FLEXCAN_T4) +#include +extern FlexCAN_T4 CAN; + +#elif defined(HT_CAN_MODE_MCP) +#include +extern MCP_CAN CAN; +#endif + +#define SYNC 0x90 +#define ACK 0x91 +#define BEGIN 0x92 + +template +inline void print(CAN_message_t& message, unsigned id, T& data) { + Serial.println ("CAN Message"); + Serial.println ("-----------"); + Serial.print ("ID = "); Serial.println (message.id, HEX); + Serial.print ("LEN = "); Serial.println (message.len); + + if (id != message.id) { + Serial.println("Warning: ID Mismatch -- Expected "); + Serial.println(id, HEX); + } + if (sizeof(T) != message.len) { + Serial.println("Warning: Length Mismatch -- Expected "); + Serial.println(sizeof(T)); + } + // this may not exist yet if you haven't merged in the tcu-refactor branch as an alternative, add if/elses here or print in the loop() function + #ifdef HT_DEBUG_EN + data.print(); + #endif +} diff --git a/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.ino b/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.ino new file mode 100644 index 00000000..695e21bb --- /dev/null +++ b/Utilities/flexcan_tester_rev2/flexcan_tester_rev2.ino @@ -0,0 +1,77 @@ +// #define HT_DEBUG_EN // only uncomment this line if tcu-refactor merged in + +#define HT_CAN_MODE_FLEXCAN + +#define TRANSMIT "transmitter.h" +#define RECEIVE "receiver.h" + +//Choose mode here +#define MODE TRANSMIT + +#include MODE + +#ifdef HT_CAN_MODE_FLEXCAN +FlexCAN CAN(500000); +void setupCAN() { + CAN.begin(); +} + +#elif defined(HT_CAN_MODE_FLEXCAN_T4) +FlexCAN_T4 CAN; +void setupCAN() { + CAN.begin(); + CAN.setBaudRate(500000); +} + +#elif defined(HT_CAN_MODE_MCP) +MCP_CAN CAN(11); +void setupCAN() { + while (CAN_OK != CAN.begin(CAN_500KBPS)) + delay(200); +} +#endif + +void setup() { + setupCAN(); + Serial.begin(9600); +} + +void loop() { + synchronize(); + + GLV_current_readings glv = handle_message(ID_GLV_CURRENT_READINGS, GLV_current_readings(100, 200)); + Serial.println(glv.get_cooling_current_value()); + Serial.println(glv.get_ecu_current_value()); + + MCU_pedal_readings mpr = handle_message(ID_MCU_PEDAL_READINGS, MCU_pedal_readings(1, 2, 3, 4, 5)); + Serial.println(mpr.get_accelerator_implausibility()); + Serial.println(mpr.get_accelerator_pedal_raw_1()); + Serial.println(mpr.get_accelerator_pedal_raw_2()); + Serial.println(mpr.get_brake_implausibility()); + Serial.println(mpr.get_brake_pedal_active()); + Serial.println(mpr.get_brake_pedal_raw()); + Serial.println(mpr.get_pedal_flags()); + Serial.println(mpr.get_torque_map_mode()); + + MCU_status ms = handle_message(ID_MCU_STATUS, MCU_status(10,20,30,40)); + Serial.println(ms.get_bms_ok_high()); + Serial.println(ms.get_flags()); + Serial.println(ms.get_glv_battery_voltage()); + Serial.println(ms.get_inverter_powered()); + Serial.println(ms.get_shutdown_b_above_threshold()); + Serial.println(ms.get_shutdown_c_above_threshold()); + Serial.println(ms.get_shutdown_d_above_threshold()); + Serial.println(ms.get_shutdown_e_above_threshold()); + Serial.println(ms.get_shutdown_f_above_threshold()); + Serial.println(ms.get_shutdown_f_above_threshold()); + Serial.println(ms.get_state()); + Serial.println(ms.get_temperature()); + + BMS_coulomb_counts bcc = handle_message(ID_BMS_COULOMB_COUNTS, BMS_coulomb_counts(123456, 987654)); + Serial.println(bcc.get_total_charge()); + Serial.println(bcc.get_total_discharge()); + + BMS_balancing_status bbs = handle_message(ID_BMS_BALANCING_STATUS, BMS_balancing_status(5, 0XDEADBEEF)); + Serial.println(bbs.get_group_id()); + //Serial.println(bbs.get_balancing()); +} diff --git a/Utilities/flexcan_tester_rev2/receiver.h b/Utilities/flexcan_tester_rev2/receiver.h new file mode 100644 index 00000000..b9a83f75 --- /dev/null +++ b/Utilities/flexcan_tester_rev2/receiver.h @@ -0,0 +1,27 @@ +#include "flexcan_tester_rev2.h" + +void synchronize() { + CAN_message_t message; + Serial.println("before the SYNC\n"); + message.timeout = 0; + while (!(CAN.read(message) && message.id == SYNC)) { // wait for sync message + Serial.println("waiting on SYNC"); + delay(500); + } + Serial.println("got the SYNC, send the ACK\n"); + message.id = ACK; + message.len = 0; + CAN.write(message); // send response + while (!(CAN.read(message) && message.id == BEGIN)); // clear extra syncs from mailbox + Serial.println("got BEGIN\n"); +} + +template +inline T handle_message(unsigned id, T data) { + CAN_message_t message; + while (!CAN.read(message)); + + data.load(message.buf); + print(message, id, data); + return data; +} diff --git a/Utilities/flexcan_tester_rev2/transmitter.h b/Utilities/flexcan_tester_rev2/transmitter.h new file mode 100644 index 00000000..65f2daa5 --- /dev/null +++ b/Utilities/flexcan_tester_rev2/transmitter.h @@ -0,0 +1,39 @@ +#include "flexcan_tester_rev2.h" +#include + +Metro timer(1000); + +void synchronize() { + CAN_message_t message; + message.id = SYNC; + message.len = 0; + message.timeout = 0; + Serial.println("before sending the SYNC\n"); + do { + Serial.println("sending the SYNC\n"); + CAN.write(message); // send sync message + delay(500); + } while (!(CAN.read(message) && message.id == ACK)); + Serial.println("received the ACK\n"); + message.id = BEGIN; + message.len = 0; + CAN.write(message); + Serial.println("sent BEGIN\n"); + timer.reset(); // reset send timer +} + + + +template +inline T handle_message(unsigned id, T data) { + CAN_message_t message; + + while (!timer.check()); + message.id = id; + message.len = sizeof(T); + data.write(message.buf); + + print(message, id, data); + CAN.write(message); + return data; +}