diff --git a/datasheets/ACS3704x.pdf b/datasheets/ACS3704x.pdf new file mode 100644 index 0000000..ac5bd47 Binary files /dev/null and b/datasheets/ACS3704x.pdf differ diff --git a/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_CurrentSensing.h b/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_CurrentSensing.h new file mode 100644 index 0000000..aef5fda --- /dev/null +++ b/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_CurrentSensing.h @@ -0,0 +1,83 @@ +// PDU_Mk1_CurrentSensing.h +// ---------------------------------------------------------------------------- +// Stuff for output current sensing on BBPDU. + +#pragma once + +// INCLUDES ------------------------------------------------------------------- + +#include "stm32xx_hal.h" + +// BBPDU peripherals +#include "PDU_Mk1.h" +#include "PDU_Mk1_Pins.h" + +// drivers +#include "ADS131M08-Q1.h" +#include "ACS3704x-010B3.h" + +// DEFINES -------------------------------------------------------------------- + +#define CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES 20 // number of samples used for calculating no-current offset +#define CURRENT_SENSING_OFFSET_CALC_SAMPLE_DELAY_MS 100 // [ms] delay between samples for calculating no-current offset + +// VARIABLE DECLARATIONS ------------------------------------------------------ + +extern SPI_HandleTypeDef hspi2; +extern SemaphoreHandle_t spi2_mutex; +extern StaticSemaphore_t spi2_mutex_buffer; +extern SemaphoreHandle_t spi2_done_sem; + +extern SPI_HandleTypeDef hspi3; +extern SemaphoreHandle_t spi3_mutex; +extern StaticSemaphore_t spi3_mutex_buffer; +extern SemaphoreHandle_t spi3_done_sem; + +extern float currents[PDU_MK1_NUM_CHANNELS]; +extern float current_adc_v_offset[PDU_MK1_NUM_CHANNELS]; + +// FUNCTIONS ------------------------------------------------------------------ + +/** + * @brief Initializes current sensing functions (ADCs, initial calibration-TODO). + * Must be called while all outputs are disabled. + * @param None + * @retval bool: true if successful, false otherwise + */ +bool PDU_Mk1_CurrentSensing_Init(); + +/** + * @brief Initializes ADC_SNS1 for current sensing use. + * @param None + * @retval ADS131M08Q1 Status (ADS131M08Q1_🙂 if successful) + */ +ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS0(); + +/** + * @brief Initializes ADC_SNS1 for current sensing use. + * @param None + * @retval ADS131M08Q1 Status (ADS131M08Q1_🙂 if successful) + */ +ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS1(); + +/** + * @brief Reads current sensing ADCs under zero-current conditions to get offset. + * Must only be run while all high-side switches are off. + * @param None + * @retval bool: true if successful, false otherwise + */ +bool PDU_Mk1_CurrentSensing_CollectOffsets(); + +/** + * @brief Reads sample from current sensing ADCs and calculates current conversion. + * @param None + * @retval bool: true if successful, false otherwise + */ +bool PDU_Mk1_CurrentSensing_ReadCurrents(); + +/** + * @brief Returns pointer to array where last currents sample is stored. + * @param None + * @retval float pointer to currents array + */ +float* PDU_Mk1_CurrentSensing_GetCurrentsPtr(); diff --git a/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_Current_Sensing.h b/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_Current_Sensing.h deleted file mode 100644 index 3dd4de5..0000000 --- a/firmware/PowerDistributionUnit_Mk1/core/inc/PDU_Mk1_Current_Sensing.h +++ /dev/null @@ -1,52 +0,0 @@ -// PDU_Mk1_Current_Sensing.h -// ---------------------------------------------------------------------------- -// Stuff for output current sensing on BBPDU. - -#pragma once - -#include "stm32xx_hal.h" - -#include "ADS131M08-Q1.h" - -#include "PDU_Mk1.h" -#include "PDU_Mk1_Pins.h" - -extern SPI_HandleTypeDef hspi2; -extern SemaphoreHandle_t spi2_mutex; -extern StaticSemaphore_t spi2_mutex_buffer; -extern SemaphoreHandle_t spi2_done_sem; - -extern SPI_HandleTypeDef hspi3; -extern SemaphoreHandle_t spi3_mutex; -extern StaticSemaphore_t spi3_mutex_buffer; -extern SemaphoreHandle_t spi3_done_sem; - -extern float currents[PDU_MK1_NUM_CHANNELS]; -extern float current_offset[PDU_MK1_NUM_CHANNELS]; - -/** - * @brief Initializes current sensing functions (ADCs, initial calibration-TODO). - * Must be called while all outputs are disabled. - * @param None - * @retval bool: true if successful, false otherwise - */ -bool PDU_Mk1_Current_Sensing_Init(); - -/** - * @brief Initializes ADC_SNS1 for current sensing use. - * @param None - * @retval ADS131M08Q1 Status (ADS131M08Q1_🙂 if successful) - */ -ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS0(); - -/** - * @brief Initializes ADC_SNS1 for current sensing use. - * @param None - * @retval ADS131M08Q1 Status (ADS131M08Q1_🙂 if successful) - */ -ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS1(); - -// TODO -// ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS0(); -// bool PDU_Mk1_Current_Sensing_SetOffsets(); -// bool PDU_Mk1_Current_Sensing_ReadCurrents(); diff --git a/firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_Current_Sensing.c b/firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_CurrentSensing.c similarity index 50% rename from firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_Current_Sensing.c rename to firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_CurrentSensing.c index d7987b1..9c82b50 100644 --- a/firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_Current_Sensing.c +++ b/firmware/PowerDistributionUnit_Mk1/core/src/PDU_Mk1_CurrentSensing.c @@ -1,14 +1,14 @@ -// PDU_Mk1_Current_Sensing.c +// PDU_Mk1_CurrentSensing.c -#include "PDU_Mk1_Current_Sensing.h" +#include "PDU_Mk1_CurrentSensing.h" ADS131M08Q1_HandleTypeDef adc_sns1; ADS131M08Q1_HandleTypeDef adc_sns0; float currents[PDU_MK1_NUM_CHANNELS] = {0}; -float current_offset[PDU_MK1_NUM_CHANNELS] = {0}; +float current_adc_v_offset[PDU_MK1_NUM_CHANNELS] = {0}; -bool PDU_Mk1_Current_Sensing_Init() +bool PDU_Mk1_CurrentSensing_Init() { if(PDU_Mk1_Init_ADC_SNS0() != ADS131M08Q1_🙂) { @@ -20,6 +20,11 @@ bool PDU_Mk1_Current_Sensing_Init() return false; } + if(PDU_Mk1_CurrentSensing_CollectOffsets() != true) + { + return false; + } + return true; } @@ -74,8 +79,72 @@ ADS131M08Q1_Status_t PDU_Mk1_Init_ADC_SNS1() adc_sns1.config.fsr = ADS131M08Q1_INTERNAL_REFERENCE_V; adc_sns1.config.powermode = ADS131M08Q1_CONFIG_POWERMODE_DEFAULT; - // channel 0 reads about 0.24 V high for some reason (rev A only) - // adc_sns1.config.ch_configs[0].offset_cal = ADS131M08Q1_CalcOffsetCalRegValue(&adc_sns1, -0.24); - return ADS131M08Q1_Init(&adc_sns1); } + +bool PDU_Mk1_CurrentSensing_CollectOffsets() +{ + float adc_results_sns0[CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES][ADS131M08Q1_NUM_CHANNELS] = {0}; + float adc_results_sns1[CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES][ADS131M08Q1_NUM_CHANNELS] = {0}; + + for(uint8_t sample = 0; sample < CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES; sample++) + { + if(ADS131M08Q1_ReadConversionResults(&adc_sns0, adc_results_sns0[sample]) != ADS131M08Q1_🙂) + { + return false; + } + + if(ADS131M08Q1_ReadConversionResults(&adc_sns1, adc_results_sns1[sample]) != ADS131M08Q1_🙂) + { + return false; + } + + if(sample != CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES-1) + { + vTaskDelay(pdMS_TO_TICKS(CURRENT_SENSING_OFFSET_CALC_SAMPLE_DELAY_MS)); + } + } + + for(uint8_t ch = 0; ch < ADS131M08Q1_NUM_CHANNELS; ch++) + { + for(uint8_t sample = 0; sample < CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES; sample++) + { + current_adc_v_offset[ch] += -1.0*adc_results_sns1[sample][(ADS131M08Q1_NUM_CHANNELS-1)-ch]; + current_adc_v_offset[ADS131M08Q1_NUM_CHANNELS+ch] += -1.0*adc_results_sns0[sample][(ADS131M08Q1_NUM_CHANNELS-1)-ch]; + } + + current_adc_v_offset[ch] /= (float) CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES; + current_adc_v_offset[ADS131M08Q1_NUM_CHANNELS+ch] /= (float) CURRENT_SENSING_OFFSET_CALC_NUMSAMPLES; + } + + return true; +} + +bool PDU_Mk1_CurrentSensing_ReadCurrents() +{ + float adc_results_sns0[ADS131M08Q1_NUM_CHANNELS] = {0}; + float adc_results_sns1[ADS131M08Q1_NUM_CHANNELS] = {0}; + + if(ADS131M08Q1_ReadConversionResults(&adc_sns0, adc_results_sns0) != ADS131M08Q1_🙂) + { + return false; + } + + if(ADS131M08Q1_ReadConversionResults(&adc_sns1, adc_results_sns1) != ADS131M08Q1_🙂) + { + return false; + } + + for(uint8_t i = 0; i < ADS131M08Q1_NUM_CHANNELS; i++) + { + currents[i] = ACS3704x_010B3_Current_Conversion_QVOCentered(adc_results_sns1[(ADS131M08Q1_NUM_CHANNELS-1)-i]+current_adc_v_offset[i]); + currents[ADS131M08Q1_NUM_CHANNELS+i] = ACS3704x_010B3_Current_Conversion_QVOCentered(adc_results_sns0[(ADS131M08Q1_NUM_CHANNELS-1)-i]+current_adc_v_offset[ADS131M08Q1_NUM_CHANNELS+i]); + } + + return true; +} + +float* PDU_Mk1_CurrentSensing_GetCurrentsPtr() +{ + return currents; +} diff --git a/firmware/PowerDistributionUnit_Mk1/test/src/ACS_Current_Sensing.c b/firmware/PowerDistributionUnit_Mk1/test/src/ACS_Current_Sensing.c new file mode 100644 index 0000000..6659ab5 --- /dev/null +++ b/firmware/PowerDistributionUnit_Mk1/test/src/ACS_Current_Sensing.c @@ -0,0 +1,265 @@ +// Current_Sensing.c +// ---------------------------------------------------------------------------- +// Senses current through each channel on BBPDU Mk1 using the hall-effect +// current sensor (not HSS one) and prints to the serial monitor. + +// INCLUDES ------------------------------------------------------------------- + +#include "stm32xx_hal.h" +// stm32xx_hal.h contains includes for RTOS stuff. +#include +#include + +// BBPDU Peripherals +#include "PDU_Mk1_Pins.h" +#include "PDU_Mk1_SPI.h" +#include "PDU_Mk1_GPIO.h" +#include "PDU_Mk1_UART.h" +#include "PDU_Mk1_CurrentSensing.h" + +// drivers +#include "ADS131M08-Q1.h" +#include "ACS3704x-010B3.h" + +// DEFINES -------------------------------------------------------------------- + +#define TASKPRIORITY_INIT tskIDLE_PRIORITY + 3 +#define TASKSTACKSIZE_INIT configMINIMAL_STACK_SIZE+5000 + +#define TASKPRIORITY_BLINK tskIDLE_PRIORITY + 2 +#define TASKSTACKSIZE_BLINK configMINIMAL_STACK_SIZE + +#define TASKPRIORITY_CURRENT_SENSE tskIDLE_PRIORITY + 2 +#define TASKSTACKSIZE_CURRENT_SENSE configMINIMAL_STACK_SIZE+3000 + +#define INTERVAL_BLINK_MS 500 +#define INTERVAL_BLINK_ERROR_MS 50 +#define INTERVAL_CURRENT_SENSE_MS 500 + +// DECLARATIONS --------------------------------------------------------------- + +SPI_HandleTypeDef hspi1; +SPI_HandleTypeDef hspi2; +SPI_HandleTypeDef hspi3; + +extern ADS131M08Q1_HandleTypeDef adc_sns0; +extern ADS131M08Q1_HandleTypeDef adc_sns1; +float adc_results_sns0[8]; +float adc_results_sns1[8]; + +SemaphoreHandle_t spi1_mutex; // Mutex to prevent simultaneous SPI access +StaticSemaphore_t spi1_mutex_buffer; // Static buffer for mutex allocation + +SemaphoreHandle_t spi1_done_sem; // Semaphore to signal SPI IT completion +StaticSemaphore_t spi1_done_sem_buffer; // Static buffer for completion semaphore + +SemaphoreHandle_t spi2_mutex; // Mutex to prevent simultaneous SPI access +StaticSemaphore_t spi2_mutex_buffer; // Static buffer for mutex allocation + +SemaphoreHandle_t spi2_done_sem; // Semaphore to signal SPI IT completion +StaticSemaphore_t spi2_done_sem_buffer; // Static buffer for completion semaphore + +SemaphoreHandle_t spi3_mutex; // Mutex to prevent simultaneous SPI access +StaticSemaphore_t spi3_mutex_buffer; // Static buffer for mutex allocation + +SemaphoreHandle_t spi3_done_sem; // Semaphore to signal SPI IT completion +StaticSemaphore_t spi3_done_sem_buffer; // Static buffer for completion semaphore + +TaskHandle_t init_task; +StaticTask_t init_task_buffer; +StackType_t init_task_stack[TASKSTACKSIZE_INIT]; + +TaskHandle_t blink_task; +StaticTask_t blink_task_buffer; +StackType_t blink_task_stack[TASKSTACKSIZE_BLINK]; + +TaskHandle_t current_sense_task; +StaticTask_t current_sense_task_buffer; +StackType_t current_sense_task_stack[TASKSTACKSIZE_CURRENT_SENSE]; + +// TASKS ---------------------------------------------------------------------- + +// initialize stuff +void Init_Task(void *argument) +{ + PDU_Mk1_GPIO_Init(); + + if(PDU_Mk1_SPI2_ADC_Init() != true) + { + printf("FAIL:SPI2_INIT\n"); + Error_Handler(); + } + + if(PDU_Mk1_SPI3_ADC_Init() != true) + { + printf("FAIL:SPI3_INIT\n"); + Error_Handler(); + } + + if(PDU_Mk1_UART_Printf_Init() != true) + { + printf("FAIL:UART_PRINTF_INIT\n"); + Error_Handler(); + } + + if(SPI_RTOS_Mutex_Semaphore_Setup(&spi2_mutex, &spi2_mutex_buffer, &spi2_done_sem, &spi2_done_sem_buffer) != true) + { + printf("FAIL:MUTEX_SEMAPHORE_INIT\n"); + Error_Handler(); + } + + // SPI dummy send because CLK pin initializes high even when configured low for some reason + if(SPI_Init_Dummy_Send(&hspi2, spi2_mutex, spi2_done_sem) != true) + { + printf("FAIL:SPI2_INIT_DUMMY_SEND\n"); + Error_Handler(); + } + + if(SPI_RTOS_Mutex_Semaphore_Setup(&spi3_mutex, &spi3_mutex_buffer, &spi3_done_sem, &spi3_done_sem_buffer) != true) + { + printf("FAIL:MUTEX_SEMAPHORE_INIT\n"); + Error_Handler(); + } + + // SPI dummy send because CLK pin initializes high even when configured low for some reason + if(SPI_Init_Dummy_Send(&hspi3, spi3_mutex, spi3_done_sem) != true) + { + printf("FAIL:SPI3_INIT_DUMMY_SEND\n"); + while(1) + { + HAL_GPIO_TogglePin(LED_PORT, LED_PIN); + vTaskDelay(pdMS_TO_TICKS(INTERVAL_BLINK_ERROR_MS)); + } + } + + if(PDU_Mk1_CurrentSensing_Init() != true) + { + printf("FAIL:ISENSE_INIT\n"); + Error_Handler(); + } + + printf("Initialization complete.\n"); + + // get this party started + vTaskResume(blink_task); + vTaskResume(current_sense_task); + // task kills itself + vTaskDelete(NULL); +} + +// blink LED +void Blink_Task(void *argument) +{ + for(;;) + { + HAL_GPIO_TogglePin(LED_PORT, LED_PIN); + + vTaskDelay(pdMS_TO_TICKS(INTERVAL_BLINK_MS)); + } +} + +// read currents and print to serial +void Current_Sense_Task(void *argument) +{ + // magic delay required to make things work for some reason + vTaskDelay(pdMS_TO_TICKS(1)); + + for(;;) + { + if(PDU_Mk1_CurrentSensing_ReadCurrents() != true) + { + printf("FAIL:CURRENT_SAMPLING\n"); + Error_Handler(); + } + + float* currents = PDU_Mk1_CurrentSensing_GetCurrentsPtr(); + + printf("\nCurrents\n----------\n" + "CH0: %.4f A\n" + "CH1: %.4f A\n" + "CH2: %.4f A\n" + "CH3: %.4f A\n" + "CH4: %.4f A\n" + "CH5: %.4f A\n" + "CH6: %.4f A\n" + "CH7: %.4f A\n" + "CH8: %.4f A\n" + "CH9: %.4f A\n" + "CH10: %.4f A\n" + "CH11: %.4f A\n" + "CH12: %.4f A\n" + "CH13: %.4f A\n" + "CH14: %.4f A\n" + "CH15: %.4f A\n", + currents[0], + currents[1], + currents[2], + currents[3], + currents[4], + currents[5], + currents[6], + currents[7], + currents[8], + currents[9], + currents[10], + currents[11], + currents[12], + currents[13], + currents[14], + currents[15]); + + vTaskDelay(pdMS_TO_TICKS(INTERVAL_CURRENT_SENSE_MS)); + } +} + +// MAIN ----------------------------------------------------------------------- + +int main() +{ + HAL_Init(); + SystemClock_Config(); + + init_task = xTaskCreateStatic(Init_Task, + "Init Task", + TASKSTACKSIZE_INIT, + NULL, + TASKPRIORITY_INIT, + init_task_stack, + &init_task_buffer + ); + + blink_task = xTaskCreateStatic(Blink_Task, + "Blink Task", + TASKSTACKSIZE_BLINK, + NULL, + TASKPRIORITY_BLINK, + blink_task_stack, + &blink_task_buffer + ); + + current_sense_task = xTaskCreateStatic(Current_Sense_Task, + "Current Sense Task", + TASKSTACKSIZE_CURRENT_SENSE, + NULL, + TASKPRIORITY_CURRENT_SENSE, + current_sense_task_stack, + ¤t_sense_task_buffer + ); + + vTaskSuspend(blink_task); + vTaskSuspend(current_sense_task); + vTaskStartScheduler(); + + while(1) {} +} + +// ERROR HANDLER -------------------------------------------------------------- + +void Error_Handler(void) +{ + while(1) + { + HAL_GPIO_TogglePin(LED_PORT, LED_PIN); + vTaskDelay(pdMS_TO_TICKS(INTERVAL_BLINK_ERROR_MS)); + } +} diff --git a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_Convert.c b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_Convert.c index be17712..fbcb90b 100644 --- a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_Convert.c +++ b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_Convert.c @@ -16,7 +16,7 @@ #include "PDU_Mk1_SPI.h" #include "PDU_Mk1_GPIO.h" #include "PDU_Mk1_UART.h" -#include "PDU_Mk1_Current_Sensing.h" +#include "PDU_Mk1_CurrentSensing.h" // drivers #include "ADS131M08-Q1.h" @@ -132,7 +132,7 @@ void Init_Task(void *argument) } } - if(PDU_Mk1_Current_Sensing_Init() != true) + if(PDU_Mk1_CurrentSensing_Init() != true) { printf("FAIL:ISENSE_INIT\n"); Error_Handler(); diff --git a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_LockUnlock_Status.c b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_LockUnlock_Status.c index 2f790ae..008e1d6 100644 --- a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_LockUnlock_Status.c +++ b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_LockUnlock_Status.c @@ -16,7 +16,7 @@ #include "PDU_Mk1_SPI.h" #include "PDU_Mk1_GPIO.h" #include "PDU_Mk1_UART.h" -#include "PDU_Mk1_Current_Sensing.h" +#include "PDU_Mk1_CurrentSensing.h" // drivers #include "ADS131M08-Q1.h" @@ -110,7 +110,7 @@ void Init_Task(void *argument) Error_Handler(); } - if(PDU_Mk1_Current_Sensing_Init() != true) + if(PDU_Mk1_CurrentSensing_Init() != true) { printf("FAIL:ISENSE_INIT\n"); Error_Handler(); diff --git a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_StandbyWakeup.c b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_StandbyWakeup.c index 9e4107b..9aa1bbd 100644 --- a/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_StandbyWakeup.c +++ b/firmware/PowerDistributionUnit_Mk1/test/src/ADS131M08Q1_StandbyWakeup.c @@ -16,7 +16,7 @@ #include "PDU_Mk1_SPI.h" #include "PDU_Mk1_GPIO.h" #include "PDU_Mk1_UART.h" -#include "PDU_Mk1_Current_Sensing.h" +#include "PDU_Mk1_CurrentSensing.h" // drivers #include "ADS131M08-Q1.h" @@ -108,7 +108,7 @@ void Init_Task(void *argument) Error_Handler(); } - if(PDU_Mk1_Current_Sensing_Init() != true) + if(PDU_Mk1_CurrentSensing_Init() != true) { printf("FAIL:ISENSE_INIT\n"); Error_Handler(); diff --git a/firmware/driver/inc/ACS3704x-010B3.h b/firmware/driver/inc/ACS3704x-010B3.h new file mode 100644 index 0000000..4457084 --- /dev/null +++ b/firmware/driver/inc/ACS3704x-010B3.h @@ -0,0 +1,28 @@ +// ACS3704x-010B3.h +// ---------------------------------------------------------------------------- +// Driver for ACS3704x-010B3 current sensor (+/- 10A range, 3.3V supply). +// Datasheet: datasheets/ACS3704x.pdf (from BBPDU repo root) + +#pragma once + +// DEVICE PARAMETERS ---------------------------------------------------------- + +#define ACS3704x_010B3_V_QVO 1.65 // V, quiescent output voltage (no current) +#define ACS3704x_010B3_SENSITIVITY 0.132 // V/A, output voltage increase per amp + +// USER FUNCTIONS ----------------------------------------------------------- + +/** + * @brief Converts current sensor output voltage to current passing through the device. + * @param v float: current sensor output voltage (relative to GND) + * @returns float: current conversion + */ +float ACS3704x_010B3_Current_Conversion(float v); + +/** + * @brief Converts current sensor output voltage (already centered on V_QVO = 1.65 V) + * to current passing through the device. + * @param v float: current sensor output voltage (relative to V_QVO = 1.65 V) + * @returns float: current conversion + */ +float ACS3704x_010B3_Current_Conversion_QVOCentered(float v); diff --git a/firmware/driver/src/ACS3704x-010B3.c b/firmware/driver/src/ACS3704x-010B3.c new file mode 100644 index 0000000..54f8c5e --- /dev/null +++ b/firmware/driver/src/ACS3704x-010B3.c @@ -0,0 +1,13 @@ +// ACS3704x-010B3.c + +#include "ACS3704x-010B3.h" + +float ACS3704x_010B3_Current_Conversion(float v) +{ + return (v - ACS3704x_010B3_V_QVO) / ACS3704x_010B3_SENSITIVITY; +} + +float ACS3704x_010B3_Current_Conversion_QVOCentered(float v) +{ + return v / ACS3704x_010B3_SENSITIVITY; +} \ No newline at end of file