diff --git a/STM32/TSYS_controller/Makefile b/STM32/TSYS_controller/Makefile index 0701667..2081386 100644 --- a/STM32/TSYS_controller/Makefile +++ b/STM32/TSYS_controller/Makefile @@ -111,6 +111,7 @@ $(STARTUP): $(INC_DIR)/startup/vector.c $(VERSION_FILE): *.[ch] @echo " Generate version: $(NEXTVER) for date $(BUILDDATE)" @sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE) + @sed -i "s/#define BUILDNO.*/#define BUILDNO $(NEXTVER)/" $(VERSION_FILE) @sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE) $(OBJDIR)/proto.o: proto.c $(VERSION_FILE) diff --git a/STM32/TSYS_controller/Readme.md b/STM32/TSYS_controller/Readme.md index 0feff0f..2824aaa 100644 --- a/STM32/TSYS_controller/Readme.md +++ b/STM32/TSYS_controller/Readme.md @@ -5,6 +5,7 @@ USART speed 115200. Code for ../../kicad/stm32 ## Serial interface commands (ends with '\n'), small letter for only local processing: - **0...7** send message to Nth controller, not broadcast (after number should be CAN command) +- **@** set/reset debug mode - **a** get raw ADC values - **B** send dummy CAN messages to broadcast address - **b** get/set CAN bus baudrate @@ -15,12 +16,15 @@ USART speed 115200. Code for ../../kicad/stm32 - **Ff** turn sensors off - **g** group (sniffer) CAN mode (print to USB terminal all incoming CAN messages with alien IDs) - **Hh** switch I2C to high speed (100kHz) +- **Ii** (re)init sensors - **Jj** get MCU temperature - **Kk** get values of U and I - **Ll** switch I2C to low speed (default, 10kHz) - **Mm** change master id to 0 (**m**) / broadcast (**M**) +- **N** get build number - **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands are local!) - **P** ping everyone over CAN +- **Qq** get system time - **Rr** reinit I2C - **s** send CAN message (format: ID data[0..8], dec, 0x - hex, 0b - binary) - **Tt** start single temperature measurement @@ -72,6 +76,9 @@ First (number zero) byte of every sequence is command mark (0xA5) or data mark ( - `CMD_GETUIVAL` (13) request to get values of V12, V5, I12 and V3.3 - `CMD_GETUIVAL0` (14) answer with values of V12 and V5 - `CMD_GETUIVAL1` (15) answer with values of I12 and V3.3 +- `CMD_REINIT_SENSORS` (16) (re)init all sensors (discover all and get calibrated data) +- `CMD_GETBUILDNO` (17) get by CAN firmware build number (uint32_t, littleendian, starting from byte #4) +- `CMD_SYSTIME` (18) get system time in ms (uint32_t, littleendian, starting from byte #4) ### Dummy commands for test purposes - `CMD_DUMMY0` = 0xDA, diff --git a/STM32/TSYS_controller/can_process.c b/STM32/TSYS_controller/can_process.c index e6aa695..291cda0 100644 --- a/STM32/TSYS_controller/can_process.c +++ b/STM32/TSYS_controller/can_process.c @@ -25,6 +25,7 @@ #include "can_process.h" #include "proto.h" #include "sensors_manage.h" +#include "version.inc" extern volatile uint32_t Tms; // timestamp data // id of master - all data will be sent to it @@ -97,13 +98,16 @@ void can_messages_proc(){ SEND(" "); printuhex(can_mesg->data[ctr]); } - newline(); sendbuf(); + newline(); } // don't process alien messages if(can_mesg->ID != CANID && can_mesg->ID != BCAST_ID) return; int16_t t; + uint32_t U32; if(data[0] == COMMAND_MARK){ // process commands if(len < 2) return; + // master shouldn't react to broadcast commands! + if(can_mesg->ID == BCAST_ID && CANID == MASTER_ID) return; switch(data[1]){ case CMD_DUMMY0: case CMD_DUMMY1: @@ -158,6 +162,19 @@ void can_messages_proc(){ case CMD_GETUIVAL: senduival(); break; + case CMD_REINIT_SENSORS: + sensors_init(); + break; + case CMD_GETBUILDNO: + b[1] = 0; + *((uint32_t*)&b[2]) = BUILDNO; + can_send_data(b, 6); + break; + case CMD_SYSTIME: + b[1] = 0; + *((uint32_t*)&b[2]) = Tms; + can_send_data(b, 6); + break; } }else if(data[0] == DATA_MARK){ // process received data char Ns = '0' + data[1]; @@ -216,6 +233,20 @@ void can_messages_proc(){ case CMD_GETUIVAL1: // I12 and V3.3 showui("I12_", "V33_", data); break; + case CMD_GETBUILDNO: + addtobuf("BUILDNO"); + bufputchar(Ns); + bufputchar('='); + U32 = *((uint32_t*)&data[4]); + printu(U32); + break; + case CMD_SYSTIME: + addtobuf("SYSTIME"); + bufputchar(Ns); + bufputchar('='); + U32 = *((uint32_t*)&data[4]); + printu(U32); + break; default: SEND("UNKNOWN_DATA"); } @@ -264,7 +295,7 @@ CAN_status can_send_data(uint8_t *data, uint8_t len){ * @return next number or -1 if all data sent */ int8_t send_temperatures(int8_t N){ - if(N < 0 || Controller_address == 0) return -1; + if(N < 0 || Controller_address == 0) return -1; // don't need to send Master's data over CAN bus int a, p; uint8_t can_data[4]; int8_t retn = N; diff --git a/STM32/TSYS_controller/can_process.h b/STM32/TSYS_controller/can_process.h index 2775140..d78fc4b 100644 --- a/STM32/TSYS_controller/can_process.h +++ b/STM32/TSYS_controller/can_process.h @@ -47,6 +47,9 @@ typedef enum{ CMD_GETUIVAL, // request to get values of V12, V5, I12 and V3.3 CMD_GETUIVAL0, // answer with values of V12 and V5 CMD_GETUIVAL1, // answer with values of I12 and V3.3 + CMD_REINIT_SENSORS, // (re)init sensors + CMD_GETBUILDNO, // request for firmware build number + CMD_SYSTIME, // get system time // dummy commands for test purposes CMD_DUMMY0 = 0xDA, CMD_DUMMY1 = 0xAD diff --git a/STM32/TSYS_controller/main.c b/STM32/TSYS_controller/main.c index affe161..64a12ff 100644 --- a/STM32/TSYS_controller/main.c +++ b/STM32/TSYS_controller/main.c @@ -66,7 +66,7 @@ static void iwdg_setup(){ } int main(void){ - uint32_t lastT = 0, lastS = 0; + uint32_t lastT = 0, lastS = 0, lastB = 0; uint8_t gotmeasurement = 0; char inbuf[256]; sysreset(); @@ -80,6 +80,7 @@ int main(void){ CAN_setup(0); // setup with default 250kbaud RCC->CSR |= RCC_CSR_RMVF; // remove reset flags USB_setup(); + sensors_init(); iwdg_setup(); while (1){ @@ -90,10 +91,19 @@ int main(void){ // send dummy command to noone to test CAN bus //can_send_cmd(NOONE_ID, CMD_DUMMY0); } - if(lastS > Tms || Tms - lastS > 5){ // run sensors proc. once per 5ms + if(lastS != Tms){ // run sensors proc. once per 1ms sensors_process(); lastS = Tms; + if(SENS_SLEEPING == Sstate){ // show temperature @ each sleeping occurence + if(!gotmeasurement){ + gotmeasurement = 1; + showtemperature(); + } + }else{ + if(SENS_WAITING == Sstate) gotmeasurement = 0; + } } + usb_proc(); can_proc(); CAN_status stat = CAN_get_status(); if(stat == CAN_FIFO_OVERRUN){ @@ -104,27 +114,22 @@ int main(void){ canerror = 1; } can_messages_proc(); - if(SENS_SLEEPING == Sstate){ // show temperature @ each sleeping occurence - if(!gotmeasurement){ - gotmeasurement = 1; - showtemperature(); - } - }else{ - gotmeasurement = 0; - } - usb_proc(); + IWDG->KR = IWDG_REFRESH; uint8_t r = 0; if((r = USB_receive(inbuf, 255))){ inbuf[r] = 0; cmd_parser(inbuf, 1); } - if(usartrx()){ // usart1 received data, store in in buffer + if(usartrx()){ // usart1 received data, store it in buffer char *txt = NULL; r = usart_getline(&txt); txt[r] = 0; cmd_parser(txt, 0); } - sendbuf(); + if(lastB - Tms > 99){ // run `sendbuf` each 100ms + sendbuf(); + lastB = Tms; + } } return 0; } diff --git a/STM32/TSYS_controller/proto.c b/STM32/TSYS_controller/proto.c index 716d530..4226277 100644 --- a/STM32/TSYS_controller/proto.c +++ b/STM32/TSYS_controller/proto.c @@ -34,9 +34,10 @@ #include "version.inc" extern volatile uint8_t canerror; +extern volatile uint32_t Tms; static char buff[UARTBUFSZ+1], *bptr = buff; -static uint8_t blen = 0, USBcmd = 0; +static uint8_t blen = 0, USBcmd = 0, debugmode = 0; // LEDs are OFF by default uint8_t noLED = #ifdef EBUG @@ -183,7 +184,6 @@ static CAN_message *parseCANmsg(char *txt){ return NULL; } SEND("Message parsed OK\n"); - sendbuf(); canmsg.length = (uint8_t) ctr; return &canmsg; } @@ -207,7 +207,6 @@ void cmd_parser(char *txt, uint8_t isUSB){ USBcmd = isUSB; int16_t L = strlen(txt), ID = BCAST_ID; char _1st = txt[0]; - sendbuf(); if(_1st >= '0' && _1st < '8'){ // send command to Nth controller, not broadcast if(L == 3){ // with '\n' at end! ID = (CAN_ID_PREFIX & CAN_ID_MASK) | (_1st - '0'); @@ -217,6 +216,13 @@ void cmd_parser(char *txt, uint8_t isUSB){ } } switch(_1st){ + case '@': + debugmode = !debugmode; + SEND("DEBUG mode "); + if(debugmode) SEND("ON"); + else SEND("OFF"); + newline(); + break; case 'a': showADCvals(); break; @@ -259,6 +265,12 @@ void cmd_parser(char *txt, uint8_t isUSB){ case 'h': i2c_setup(HIGH_SPEED); break; + case 'I': + CANsend(ID, CMD_REINIT_SENSORS, _1st); + break; + case 'i': + sensors_init(); + break; case 'J': CANsend(ID, CMD_GETMCUTEMP, _1st); break; @@ -283,6 +295,9 @@ void cmd_parser(char *txt, uint8_t isUSB){ case 'm': CANsend(ID, CMD_CHANGE_MASTER, _1st); break; + case 'N': + CANsend(ID, CMD_GETBUILDNO, _1st); + break; case 'O': noLED = 0; SEND("LED on\n"); @@ -296,6 +311,12 @@ void cmd_parser(char *txt, uint8_t isUSB){ case 'P': CANsend(ID, CMD_PING, _1st); break; + case 'Q': + CANsend(ID, CMD_SYSTIME, _1st); + break; + case 'q': + SEND("SYSTIME0="); printu(Tms); newline(); + break; case 'R': CANsend(ID, CMD_REINIT_I2C, _1st); break; @@ -354,6 +375,7 @@ void cmd_parser(char *txt, uint8_t isUSB){ SEND( "ALL little letters - without CAN messaging\n" "0..7 - send command to given controller (0 - this) instead of broadcast\n" + "@ - set/reset debug mode\n" "a - get raw ADC values\n" "B - send broadcast CAN dummy message\n" "b - get/set CAN bus baudrate\n" @@ -364,24 +386,26 @@ void cmd_parser(char *txt, uint8_t isUSB){ "Ff- turn oFf sensors\n" "g - group (sniffer) CAN mode\n" "Hh- high I2C speed\n" + "Ii- (re)init sensors\n" "Jj- get MCU temperature\n" "Kk- get U/I values\n" "Ll- low I2C speed\n" "Mm- change master id to 0 (m) / broadcast (M)\n" + "N - get build number\n" "Oo- turn onboard diagnostic LEDs *O*n or *o*ff (both commands are local)\n" "P - ping everyone over CAN\n" + "Qq- get system time\n" "Rr- reinit I2C\n" "s - send CAN message\n" "Tt- start temperature measurement\n" "u - unique ID (default) CAN mode\n" "Vv- very low I2C speed\n" "Xx- Start themperature scan\n" - "Yy- get sensors state over CAN\n" + "Yy- get sensors state\n" "z - check CAN status for errors\n" ); break; } - sendbuf(); } // print 32bit unsigned int @@ -493,3 +517,11 @@ char *getnum(char *txt, int32_t *N){ } return getdec(txt, N); } + +// show message in debug mode +void mesg(char *txt){ + if(!debugmode) return; + addtobuf("[DBG] "); + addtobuf(txt); + bufputchar('\n'); +} diff --git a/STM32/TSYS_controller/proto.h b/STM32/TSYS_controller/proto.h index 6909bce..48e544f 100644 --- a/STM32/TSYS_controller/proto.h +++ b/STM32/TSYS_controller/proto.h @@ -46,5 +46,6 @@ void printu(uint32_t val); void printuhex(uint32_t val); void sendbuf(); char *getnum(char *txt, int32_t *N); +void mesg(char *txt); #endif // __PROTO_H__ diff --git a/STM32/TSYS_controller/sensors_manage.c b/STM32/TSYS_controller/sensors_manage.c index 63e485f..fbac396 100644 --- a/STM32/TSYS_controller/sensors_manage.c +++ b/STM32/TSYS_controller/sensors_manage.c @@ -56,6 +56,8 @@ static const char *statenames[] = { ,[SENS_OVERCURNT_OFF] = "offbyovercurrent" }; +static uint8_t getcoeff(uint8_t i); + const char *sensors_get_statename(SensorsState x){ if(x >= SENS_STATE_CNT) return "wrongstate"; return statenames[x]; @@ -77,7 +79,9 @@ const double mul[5] = {-1.5e-2, 1., -2., 4., -2.}; */ static uint16_t calc_t(uint32_t t, int i){ uint16_t *coeff = coefficients[curr_mul_addr][i]; - if(coeff[0] == 0) return BAD_TEMPERATURE; // what is with coeffs? + if(coeff[0] == 0){ + if(!getcoeff(i)) return BAD_TEMPERATURE; // what is with coeffs? + } if(t < 600000 || t > 30000000) return BAD_TEMPERATURE; // wrong value - too small or too large int j; double d = (double)t/256., tmp = 0.; @@ -92,28 +96,39 @@ static uint16_t calc_t(uint32_t t, int i){ // turn off sensors' power void sensors_off(){ + mesg("Turn off sensors"); MUL_OFF(); // turn off multiplexers SENSORS_OFF(); // turn off sensors' power Sstate = SENS_OFF; } /** - * if all OK with current, turn ON sensors' power and change state to "initing" + * if all OK with current, turn ON sensors' power */ -void sensors_on(){ - sens_present[0] = sens_present[1] = 0; +static int sensors_on(){ + mesg("Turn on sensors"); curr_mul_addr = 0; - Nsens_present = 0; MUL_OFF(); if(SENSORS_OVERCURNT()){ + mesg("OVERCURRENT!"); SENSORS_OFF(); Sstate = (++overcurnt_ctr > 32) ? SENS_OVERCURNT_OFF : SENS_OVERCURNT; + return FALSE; }else{ + mesg("Powered on"); SENSORS_ON(); - Sstate = SENS_INITING; + return TRUE; } } +// init sensors +void sensors_init(){ + sens_present[0] = sens_present[1] = 0; + overcurnt_ctr = 0; + Nsens_present = 0; + if(sensors_on()) Sstate = SENS_INITING; +} + /** * start measurement if sensors are sleeping, * turn ON if they were OFF @@ -127,7 +142,10 @@ void sensors_start(){ break; case SENS_OFF: overcurnt_ctr = 0; - sensors_on(); + if(sensors_on()) Sstate = SENS_START_MSRMNT; + break; + case SENS_OVERCURNT_OFF: + sensors_init(); break; default: break; @@ -142,47 +160,56 @@ static void count_sensors(){ ++Nsens_present; B &= (B - 1); } +/* +SEND("count_sensors(): "); +printu(Nsens_present); +newline(); +*/ } /** - * All procedures return 1 if they change current state due to error & 0 if all OK + * All procedures return TRUE if all OK or FALSE if failed and need to start scan again */ // procedure call each time @ resetting static uint8_t resetproc(){ - uint8_t i, ctr = 0; + uint8_t i; for(i = 0; i < 2; ++i){ if(write_i2c(Taddr[i], TSYS01_RESET)){ - ++ctr; sens_present[i] |= 1< MUL_MAX_ADDRESS){ // scan is over curr_mul_addr = 0; - return 1; + return TRUE; } } - return 0; + return FALSE; } // print coefficients @debug console @@ -277,10 +311,8 @@ void showcoeffs(){ // print temperatures @debug console void showtemperature(){ int a, p; - if(Nsens_present == 0){ - return; - } - if(Ntemp_measured == 0){ + if(Nsens_present == 0 || Ntemp_measured == 0){ + SEND("No sensors found"); return; } for(a = 0; a <= MUL_MAX_ADDRESS; ++a){ @@ -313,32 +345,39 @@ void sensors_process(){ Sstate = (++overcurnt_ctr > 32) ? SENS_OVERCURNT_OFF : SENS_OVERCURNT; return; } - switch (Sstate){ + switch(Sstate){ case SENS_INITING: // initialisation (restart I2C) + mesg("SENS_INITING"); i2c_setup(CURRENT_SPEED); Sstate = SENS_RESETING; lastSensT = Tms; - overcurnt_ctr = 0; + NsentOverCAN = -1; break; case SENS_RESETING: // reset & discovery procedure + if(NsentOverCAN == -1){ + mesg("SENS_RESETING"); + NsentOverCAN = 0; + } if(Tms - lastSensT > POWERUP_TIME){ - overcurnt_ctr = 0; if(sensors_scan(resetproc)){ count_sensors(); // get total amount of sensors if(Nsens_present){ Sstate = SENS_GET_COEFFS; }else{ // no sensors found + mesg("No sensors found"); sensors_off(); } } } break; case SENS_GET_COEFFS: // get coefficients + mesg("SENS_GET_COEFFS"); if(sensors_scan(getcoefsproc)){ - Sstate = SENS_START_MSRMNT; + Sstate = SENS_SLEEPING; // sleep after got coefficients } break; case SENS_START_MSRMNT: // send all sensors command to start measurements + mesg("SENS_START_MSRMNT"); if(sensors_scan(msrtempproc)){ lastSensT = Tms; Sstate = SENS_WAITING; @@ -346,33 +385,50 @@ void sensors_process(){ } break; case SENS_WAITING: // wait for end of conversion + mesg("SENS_WAITING"); if(Tms - lastSensT > CONV_TIME){ + NsentOverCAN = -1; Sstate = SENS_GATHERING; } break; case SENS_GATHERING: // scan all sensors, get thermal data & calculate temperature + if(NsentOverCAN < 0){ + mesg("SENS_SLEEPING"); + NsentOverCAN = 0; + } if(sensors_scan(gettempproc)){ lastSensT = Tms; NsentOverCAN = 0; - Sstate = SENS_SLEEPING; + Sstate = SENS_SENDING_DATA; } break; - case SENS_SLEEPING: // wait for `SLEEP_TIME` till next measurements + case SENS_SENDING_DATA: + mesg("SENS_SENDING_DATA"); NsentOverCAN = send_temperatures(NsentOverCAN); // call sending T process - if(NsentOverCAN == -1){ + if(NsentOverCAN < 0){ // all data sent -> sleep + Sstate = SENS_SLEEPING; + /* if(Nsens_present != Ntemp_measured){ // restart sensors only after measurements sent + mesg("restart"); i2c_setup(CURRENT_SPEED); sensors_on(); - } - if(sensors_scan_mode){ // sleep until next measurement start - if(Tms - lastSensT > SLEEP_TIME){ - Sstate = SENS_START_MSRMNT; - } + }*/ + } + break; + case SENS_SLEEPING: // wait for `SLEEP_TIME` till next measurements in scan mode + if(NsentOverCAN < 0){ + mesg("SENS_SLEEPING"); + NsentOverCAN = 0; + } + if(sensors_scan_mode){ // sleep until next measurement start + if(Tms - lastSensT > SLEEP_TIME){ + Sstate = SENS_START_MSRMNT; } } break; case SENS_OVERCURNT: // try to reinit all after overcurrent - sensors_on(); + mesg("SENS_OVERCURNT"); + if(sensors_on()) Sstate = SENS_SLEEPING; break; default: // do nothing break; diff --git a/STM32/TSYS_controller/sensors_manage.h b/STM32/TSYS_controller/sensors_manage.h index 37b7c18..aea0f15 100644 --- a/STM32/TSYS_controller/sensors_manage.h +++ b/STM32/TSYS_controller/sensors_manage.h @@ -46,6 +46,7 @@ typedef enum{ ,SENS_OFF // 7 sensors' power is off by external command ,SENS_OVERCURNT // 8 overcurrent detected @ any stage ,SENS_OVERCURNT_OFF // 9 sensors' power is off due to continuous overcurrent + ,SENS_SENDING_DATA // A send data over CAN bus ,SENS_STATE_CNT } SensorsState; @@ -60,7 +61,7 @@ const char *sensors_get_statename(SensorsState x); void sensors_process(); void sensors_off(); -void sensors_on(); +void sensors_init(); void sensors_start(); void showcoeffs(); void showtemperature(); diff --git a/STM32/TSYS_controller/tsys01.bin b/STM32/TSYS_controller/tsys01.bin index b5e88b7..fff6c1c 100755 Binary files a/STM32/TSYS_controller/tsys01.bin and b/STM32/TSYS_controller/tsys01.bin differ diff --git a/STM32/TSYS_controller/version.inc b/STM32/TSYS_controller/version.inc index a6bd452..7f4081a 100644 --- a/STM32/TSYS_controller/version.inc +++ b/STM32/TSYS_controller/version.inc @@ -1,2 +1,3 @@ -#define BUILD_NUMBER "28" -#define BUILD_DATE "2022-01-31" +#define BUILD_NUMBER "44" +#define BUILD_DATE "2022-02-02" +#define BUILDNO 44