implemented current and voltage monitoring (currently NOT tested)

This commit is contained in:
2025-03-13 21:08:45 +01:00
parent f57eb4ccf4
commit 26aa408e96
11 changed files with 9977 additions and 9746 deletions

View File

@ -10,16 +10,16 @@
#include "channel_control.h"
#include "can_halal.h"
//#include "current_monitoring.h"
#include "current_monitoring.h"
#define RX_STATUS_HEARTBEAT 0xC7 // IDs of all CAN-packages (may be other IDs next year)
#define RX_STATUS_MSG_ID 0xC8 // TODO: check new IDs
#define RX_STATUS_MSG_ID 0xC8
#define TX_STATUS_MSG_ID 0xC9
#define CUR_CHANNELS_1_ID 0xCA
#define CUR_CHANNELS_2_ID 0xCB
#define CUR_CHANNELS_3_ID 0xCC
#define CUR_CHANNELS_4_ID 0xCD
#define LV_SENS_ID 0xCE
//#define LV_SENS_ID 0xCE // not used
typedef struct { // TODO: add error-codes
enable_gpios iostatus;

View File

@ -0,0 +1,51 @@
/*
* current_monitoring.h
*
* Created on: Mar 13, 2025
* Author: janek
*/
#ifndef INC_CURRENT_MONITORING_H_
#define INC_CURRENT_MONITORING_H_
#include "stm32f3xx_hal.h"
// convert ADC quants to V
#define ADC_V_FACTOR (3.3f / 4096) // 3.3V / 12bit
// scale to LV by divider to mV
#define LV_SENSE_FACTOR (1e3 * (ADC_V_FACTOR * ((12.f + 1.8f) / 1.8f)))
#define PC_VSENSE_FACTOR (1e3 * (ADC_V_FACTOR * ((100.f + 10.f) / 10.f)));
// convert ADC quants to I_S in mA
#define CURR_SENSE_IS_FACTOR_9A (ADC_V_FACTOR / 1.2f) // 3.3V / 12bit / 1.2kOhm
#define CURR_SENSE_IS_FACTOR_4_5A (ADC_V_FACTOR / 1.f)
#define CURR_SENSE_IS_FACTOR_1A (ADC_V_FACTOR / 4.f)
// convert ADC quants to I_L in mA
#define CURR_SENSE_FACTOR_1A (300 * CURR_SENSE_IS_FACTOR) // typical current sense ratio (datasheet PROFET)
#define CURR_SENSE_FACTOR_4_5A (1500 * CURR_SENSE_IS_FACTOR)
#define CURR_SENSE_FACTOR_9A (3900 * CURR_SENSE_IS_FACTOR)
typedef struct {
uint16_t acc_cooling;
uint16_t ts_cooling;
uint16_t drs;
uint16_t acu;
uint16_t epsc;
uint16_t inverter;
uint16_t lidar;
uint16_t misc;
uint16_t alwayson;
uint16_t sdc;
uint16_t ebs1;
uint16_t ebs2;
uint16_t ebs3;
uint16_t epsc_precharge;
uint16_t lvms_v;
uint16_t asms_v;
} current_measurements;
void current_monitor_init(ADC_HandleTypeDef* hadc1, ADC_HandleTypeDef* hadc2, TIM_HandleTypeDef* trigtim);
uint8_t current_monitor_checklimits();
#endif /* INC_CURRENT_MONITORING_H_ */

View File

@ -7,7 +7,7 @@
#include "can_communication.h"
#include "channel_control.h"
//#include "current_monitoring.h"
#include "current_monitoring.h"
rx_status_frame rxstate = {};
volatile uint8_t canmsg_received = 0;
@ -23,14 +23,69 @@ void can_init(CAN_HandleTypeDef* hcan){
}
void can_sendloop(){
//static uint8_t additionaltxcounter = 0;
static uint8_t additionaltxcounter = 0;
uint8_t status_data[3];
status_data[0] = update_ports.porta.porta;
status_data[1] = update_ports.portb.portb;
status_data[2] = !inhibit_SDC;
ftcan_transmit(TX_STATUS_MSG_ID, status_data, 3);
// TODO: implement transmission of current and voltage measurements
uint8_t data[8];
switch (additionaltxcounter) {
case 0:
data[0] = current_measurements_adc_val.alwayson >> 8;
data[1] = current_measurements_adc_val.alwayson & 0xFF;
data[2] = current_measurements_adc_val.misc >> 8;
data[3] = current_measurements_adc_val.misc & 0xFF;
data[4] = current_measurements_adc_val.inverter >> 8;
data[5] = current_measurements_adc_val.inverter & 0xFF;
data[6] = current_measurements_adc_val.sdc >> 8;
data[7] = current_measurements_adc_val.sdc & 0xFF;
ftcan_transmit(CUR_CHANNELS_1_ID, data, 8);
break;
case 1:
data[0] = current_measurements_adc_val.acc_cooling >> 8;
data[1] = current_measurements_adc_val.acc_cooling & 0xFF;
data[2] = current_measurements_adc_val.ts_cooling >> 8;
data[3] = current_measurements_adc_val.ts_cooling & 0xFF;
data[4] = current_measurements_adc_val.acu >> 8;
data[5] = current_measurements_adc_val.acu & 0xFF;
data[6] = current_measurements_adc_val.epsc >> 8;
data[7] = current_measurements_adc_val.epsc & 0xFF;
ftcan_transmit(CUR_CHANNELS_2_ID, data, 8);
break;
case 2:
data[0] = current_measurements_adc_val.ebs1 >> 8;
data[1] = current_measurements_adc_val.ebs1 & 0xFF;
data[2] = current_measurements_adc_val.ebs2 >> 8;
data[3] = current_measurements_adc_val.ebs2 & 0xFF;
data[4] = current_measurements_adc_val.ebs3 >> 8;
data[5] = current_measurements_adc_val.ebs3 & 0xFF;
data[6] = current_measurements_adc_val.drs >> 8;
data[7] = current_measurements_adc_val.drs & 0xFF;
ftcan_transmit(CUR_CHANNLES_3_ID, data, 8);
break;
case 3:
data[0] = current_measurements_adc_val.lidar >> 8;
data[1] = current_measurements_adc_val.lidar & 0xFF;
data[2] = current_measurements_adc_val.lvms_v >> 8;
data[3] = current_measurements_adc_val.lvms_v & 0xFF;
data[4] = current_measurements_adc_val.asms_v >> 8;
data[5] = current_measurements_adc_val.asms_v & 0xFF;
data[6] = 0x01; // not used (transmits 313)
data[7] = 0x39; // not used (transmits 313)
ftcan_transmit(CUR_CHANNELS_4_ID, data, 8);
break;
default:
break;
}
additionaltxcounter = (additionaltxcounter + 1) % 4;
}
void ftcan_msg_received_cb(uint16_t id, size_t datalen, const uint8_t* data){

View File

@ -0,0 +1,94 @@
/*
* current_monitoring.c
*
* Created on: Mar 13, 2025
* Author: janek
*/
#include "current_monitoring.h"
#include "main.h"
volatile union adc1_channels {
struct {
uint16_t lvms_vsense; // LVMS-Vsense
uint16_t isense1; // acc-cooling
uint16_t isense2; // ts-cooling
uint16_t isense9; // always on
uint16_t isense11; // ebs1, ebs2, ebs3 (DSEL0, DSEL1)
uint16_t asms_vsense; // ASMS-Vsense
uint16_t isense10; // sdc
uint16_t isense6; // inverter
} adcbank1;
uint16_t adcbuffer[8];
} adc_channels1;
volatile union adc2_channels {
struct {
uint16_t isense3; // drs
uint16_t isense8; // misc
uint16_t isense4; // acu
uint16_t isense5; // epsc
uint16_t pc_read; // precharge voltage epsc
uint16_t isense7; // lidar
} adcbank2;
uint16_t adcbuffer[6];
} adc_channels2;
current_measurements current_measurements_adc_val;
GPIO_PinState valve2 = GPIO_PIN_RESET;
GPIO_PinState valve3 = GPIO_PIN_RESET;
ADC_HandleTypeDef* adc1;
ADC_HandleTypeDef* adc2;
void current_monitor_init(ADC_HandleTypeDef* hadc1, ADC_HandleTypeDef* hadc2, TIM_HandleTypeDef* trigtim) {
HAL_GPIO_WritePin(DSEL0_GPIO_Port, DSEL0_Pin, valve3);
HAL_GPIO_WritePin(DSEL1_GPIO_Port, DSEL1_Pin, valve2);
adc1 = hadc1;
adc2 = hadc2;
HAL_TIM_Base_Start(trigtim);
HAL_ADC_Start_DMA(hadc1, (uint32_t*)adc_channels1.adcbuffer, 6);
HAL_ADC_Start_DMA(hadc2, (uint32_t*)adc_channels2.adcbuffer, 5);
}
uint8_t current_monitor_checklimits() {return 0;} // TODO: implement properly
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if (hadc == adc1){
if (valve2 == GPIO_PIN_RESET && valve3 == GPIO_PIN_RESET){
current_measurement_adc_val.ebs1 = adc_channels1.adcbank1.isense11 * CURR_SENSE_FACTOR_1A;
valve2 = GPIO_PIN_SET;
}
if (valve2 == GPIO_PIN_SET && valve3 == GPIO_PIN_RESET){
current_measurement_adc_val.ebs2 = adc_channels1.adcbank1.isense11 * CURR_SENSE_FACTOR_1A;
valve2 = GPIO_PIN_RESET;
valve3 = GPIO_PIN_SET;
}
if (valve2 == GPIO_PIN_RESET && valve3 == GPIO_PIN_SET){
current_measurement_adc_val.ebs3 = adc_channels1.adcbank1.isense11 * CURR_SENSE_FACTOR_1A;
valve3 = GPIO_PIN_RESET;
}
}
else {
current_measurement_adc_val.lvms_v = adc_channels1.adcbank1.lvms_vsense * LV_SENSE_FACTOR;
current_measurement_adc_val.acc_cooling = adc_channels1.adcbank1.isense1 * CURR_SENSE_FACTOR_9A;
current_measurement_adc_val.ts_cooling = adc_channels1.adcbank1.isense2 * CURR_SENSE_FACTOR_9A;
current_measurement_adc_val.alwayson = adc_channels1.adcbank1.isense9 * CURR_SENSE_FACTOR_9A;
current_measurement_adc_val.asms_v = adc_channels1.adcbank1.asms_vsense * LV_SENSE_FACTOR;
current_measurement_adc_val.sdc = adc_channels1.adcbank1.isense10 * CURR_SENSE_FACTOR_4_5A;
current_measurement_adc_val.inverter = adc_channels1.adcbank1.isense6 * CURR_SENSE_FACTOR_9A;
HAL_GPIO_WritePin(DSEL0_GPIO_Port, DSEL0_Pin, valve3);
HAL_GPIO_WritePin(DSEL1_GPIO_Port, DSEL1_Pin, valve2);
}
if (hadc == adc2){
current_measurement_adc_val.drs = adc_channels2.adcbank2.isense3 * CURR_SENSE_FACTOR_4_5A;
current_measurement_adc_val.misc = adc_channels2.adcbank2.isense8 * CURR_SENSE_FACTOR_4_5A;
current_measurement_adc_val.acu = adc_channels2.adcbank2.isense4 * CURR_SENSE_FACTOR_9A;
current_measurement_adc_val.epsc = adc_channels2.adcbank2.isense5 * CURR_SENSE_FACTOR_9A;
current_measurement_adc_val.epsc_precharge = adc_channels2.adcbank2.pc_read * PC_VSENSE_FACTOR;
current_measurement_adc_val.lidar = adc_channels2.adcbank2.isense7 * CURR_SENSE_FACTOR_4_5A;
}
}

View File

@ -71,7 +71,8 @@ static void MX_TIM6_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// adc buffer
uint16_t adc1_buffer[7];
uint16_t adc2_buffer[7];
extern rx_status_frame rxstate;
extern volatile uint8_t canmsg_received;
@ -145,7 +146,7 @@ int main(void)
ChannelControl_init();
can_init(&hcan);
// currentMonitor initialisieren
current_monitor_init(&hadc1, &hadc2, &htim6);
uint32_t lasttick = HAL_GetTick(); // Zeit in ms seit Start
@ -168,10 +169,15 @@ int main(void)
lasttick = HAL_GetTick();
can_sendloop();
}
//watchdog (auch Status-LED an schalten)
if (((HAL_GetTick() - lastheartbeat) > 125U) && (HAL_GetTick() > 1000U)) {
inhibit_SDC = 1;
}
HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, (GPIO_PinState)!update_ports.portb.sdc); // indicates open SDC
HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, (GPIO_PinState)inhibit_SDC); // indicates watchdog-status
// overcurrent check (wenn funktioniert, LED schalten)
ChannelControl_UpdateGPIOs(update_ports);
current_monitor_checklimits(); // currently not implemented
}
/* USER CODE END 3 */
}