add some features

This commit is contained in:
Edward Emelianov 2022-02-02 14:37:05 +03:00
parent a738607455
commit 13de663270
11 changed files with 220 additions and 82 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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');
}

View File

@ -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__

View File

@ -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<<curr_mul_addr; // set bit - found
}else{ // not found
sens_present[i] &= ~(1<<curr_mul_addr); // reset bit - not found
}
}
return 0;
return TRUE;
}
static uint8_t getcoeff(uint8_t i){
const uint8_t regs[5] = {0xAA, 0xA8, 0xA6, 0xA4, 0xA2}; // commands for coefficients
uint8_t err = 5;
uint16_t *coef = coefficients[curr_mul_addr][i];
for(uint8_t j = 0; j < 5; ++j){
uint32_t K;
if(write_i2c(Taddr[i], regs[j])){
if(read_i2c(Taddr[i], &K, 2)){
coef[j] = K;
--err;
}else break;
}else break;
}
if(err){ // restart all procedures if we can't get coeffs of present sensor
return FALSE;
}
return TRUE;
}
// procedure call each time @ getting coefficients
static uint8_t getcoefsproc(){
uint8_t i, j;
const uint8_t regs[5] = {0xAA, 0xA8, 0xA6, 0xA4, 0xA2}; // commands for coefficients
for(i = 0; i < 2; ++i){
uint8_t r = TRUE;
for(uint8_t i = 0; i < 2; ++i){
if(!(sens_present[i] & (1<<curr_mul_addr))) continue; // no sensors @ given line
uint8_t err = 5;
uint16_t *coef = coefficients[curr_mul_addr][i];
for(j = 0; j < 5; ++j){
uint32_t K;
if(write_i2c(Taddr[i], regs[j])){
if(read_i2c(Taddr[i], &K, 2)){
coef[j] = K;
--err;
}else break;
}else break;
}
if(err){ // restart all procedures if we can't get coeffs of present sensor
return 1;
}
if(!getcoeff(i)) r = FALSE;
}
return 0;
return r;
}
// procedure call each time @ start measurement
@ -190,18 +217,25 @@ static uint8_t msrtempproc(){
uint8_t i, j;
for(i = 0; i < 2; ++i){
if(!(sens_present[i] & (1<<curr_mul_addr))){ // no sensors @ given line - try to find it
resetproc();
if(sens_present[i] & (1<<curr_mul_addr)){ // found!
if(getcoefsproc()) continue; // error
else count_sensors(); // refresh Nsens_present
}else continue; // not found - continue
if(write_i2c(Taddr[i], TSYS01_RESET)){
sens_present[i] |= 1<<curr_mul_addr;
mesg("One sensor added");
count_sensors();
// if(getcoeff(i)) count_sensors();
}
continue;
}
for(j = 0; j < 5; ++j){
if(write_i2c(Taddr[i], TSYS01_START_CONV)) break;
if(!write_i2c(Taddr[i], TSYS01_RESET)) i2c_setup(CURRENT_SPEED); // maybe I2C restart will solve the problem?
//if(!write_i2c(Taddr[i], TSYS01_RESET)) i2c_setup(CURRENT_SPEED); // maybe I2C restart will solve the problem?
}
if(j == 5){
sens_present[i] &= ~(1<<curr_mul_addr); // clear presence flag
mesg("One sensor removed");
count_sensors();
}
}
return 0;
return TRUE;
}
// procedure call each time @ read temp
@ -224,13 +258,13 @@ static uint8_t gettempproc(){
write_i2c(Taddr[i], TSYS01_RESET);
}
}
return 0;
return TRUE;
}
/**
* 2 phase for each call: 1) set address & turn on mul.; 2) call function & turn off mul.
* Change address @ call function `procfn`
* @return 1 if scan is over
* @return TRUE if scan is over
*/
static uint8_t sensors_scan(uint8_t (* procfn)()){
static uint8_t callctr = 0;
@ -242,16 +276,16 @@ static uint8_t sensors_scan(uint8_t (* procfn)()){
callctr = 0;
uint8_t s = procfn();
MUL_OFF();
if(s){ // start scan again if error
if(!s){ // start scan again if error
curr_mul_addr = 0;
return 0;
return FALSE;
}
if(++curr_mul_addr > 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;

View File

@ -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();

Binary file not shown.

View File

@ -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