implemented current and voltage monitoring (currently NOT tested)
This commit is contained in:
@ -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;
|
||||
|
||||
51
Software/Code/Core/Inc/current_monitoring.h
Normal file
51
Software/Code/Core/Inc/current_monitoring.h
Normal 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_ */
|
||||
@ -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){
|
||||
|
||||
94
Software/Code/Core/Src/current_monitoring.c
Normal file
94
Software/Code/Core/Src/current_monitoring.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user