|
|
@@ -14,15 +14,13 @@ uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
|
|
|
uint32_t gTxADClen, gTxADCcount;
|
|
|
uint32_t gRxADClen, gRxADCcount;
|
|
|
|
|
|
-
|
|
|
uint8_t ADC_ConstructConfigBytes(ADC_PARAMS params) {
|
|
|
|
|
|
uint8_t config = 0;
|
|
|
|
|
|
-
|
|
|
config |= ((params.channel - 1) << 5); // Channel Selection (Bits 6-5)
|
|
|
|
|
|
- if (params.continuous) config |= (1 << 4); // Continuous Mode (Bit 4)
|
|
|
+ config |= (1 << 4); // One-Shot Mode
|
|
|
|
|
|
switch (params.resolution) {
|
|
|
case 12: config |= (0b00 << 2); break;
|
|
|
@@ -47,8 +45,6 @@ void ADC_SetConfigurationBytes(ADC_PARAMS params) {
|
|
|
// **Construct Configuration Byte**
|
|
|
uint8_t config_byte = ADC_ConstructConfigBytes(params);
|
|
|
|
|
|
- //printf("Writing Config: 0x%02X to ADC (0x%X)...\n", config_byte, ADC_TARGET_BASE_ADDRESS);
|
|
|
-
|
|
|
// Wait for I2C Bus to be Free**
|
|
|
while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
|
|
|
|
|
@@ -57,15 +53,22 @@ void ADC_SetConfigurationBytes(ADC_PARAMS params) {
|
|
|
gTxPacket[0]= config_byte;
|
|
|
gTxADClen= 1;
|
|
|
gTxADCcount= 0;
|
|
|
- gTxComplete= true;
|
|
|
+ gTxComplete= false;
|
|
|
+
|
|
|
DL_I2C_startControllerTransfer(I2C_controller_INST, ADC_TARGET_BASE_ADDRESS, DL_I2C_CONTROLLER_DIRECTION_TX, gTxADClen);
|
|
|
DL_I2C_enableInterrupt(I2C_controller_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
|
|
|
- while(!gTxComplete);
|
|
|
+ //while(!gTxComplete);
|
|
|
// **Ensure STOP Condition is Sent**
|
|
|
while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
|
|
printf("Configuration Sent Successfully for 0x%X!\n", config_byte);
|
|
|
}
|
|
|
|
|
|
+// **Interrupt handler for configuration completion**
|
|
|
+void I2C_ConfigInterruptHandler(void) {
|
|
|
+ if (DL_I2C_getPendingInterrupt(I2C_controller_INST) == DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER) {
|
|
|
+ gTxComplete = true;
|
|
|
+ }
|
|
|
+}
|
|
|
/*
|
|
|
READY BIT:
|
|
|
This bit is the data ready flag. In read mode, this bit indicates if the output register has been updated
|
|
|
@@ -81,7 +84,7 @@ bool ADC_CheckReadyBit(uint8_t slot_id, ADC_PARAMS params){
|
|
|
uint8_t config_byte = ADC_ConstructConfigBytes(params);
|
|
|
DL_I2C_startControllerTransfer(I2C_controller_INST, ADC_TARGET_BASE_ADDRESS+slot_id, DL_I2C_CONTROLLER_DIRECTION_RX, 1);
|
|
|
config_byte= DL_I2C_receiveControllerData(I2C_controller_INST);
|
|
|
- bool ready= (config_byte & 0x80)==0;
|
|
|
+ bool ready= (config_byte & 0x80)==0; //Ready bit is bit 7
|
|
|
printf("Slot: %d | Config Byte: 0x%02X | READY Bit: %d\n", slot_id, config_byte, ready);
|
|
|
return ready;
|
|
|
}
|
|
|
@@ -117,22 +120,27 @@ Function to read ADC DATA: This function simply retrieves the ADC raw digital ou
|
|
|
* Output code is in binary and is proportional to the Input Voltage and PGA settings.
|
|
|
* From the datasheet: https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/22226a.pdf
|
|
|
- Equation 4.4 is being used to convert the output codes to input voltage
|
|
|
+
|
|
|
+* The ACK bits after conversion is issued by the Master, when the device receives a READ command, it outputs two data bytes
|
|
|
+ followed by a configuration register in 16 bit conversion mode the MSB(=sign bit) of the first data type is D15.
|
|
|
+
|
|
|
*/
|
|
|
|
|
|
int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params)
|
|
|
{
|
|
|
+ //Request ADC Conversion
|
|
|
+ //ADC_SetConfigurationBytes(params);
|
|
|
+
|
|
|
+ //Wait until data is ready
|
|
|
while(!ADC_CheckReadyBit(slot_id, params)){
|
|
|
delay_cycles(50000);
|
|
|
}
|
|
|
- uint8_t adc_data[3] = {0}; // Buffer for ADC data (MSB, LSB, Config Byte)
|
|
|
+ // Buffer for ADC data (MSB, LSB, Config Byte)
|
|
|
+ uint8_t adc_data[3] = {0};
|
|
|
int16_t raw_adc = 0;
|
|
|
- /*The ACK bits after conversion is issued by the Master, when the device receives a READ command, it outputs two data bytes
|
|
|
- followed by a configuration register
|
|
|
- in 16 bit conversion mode the MSB(=sign bit) of the first data type is D15.
|
|
|
- */
|
|
|
uint8_t bytes_to_read= 3;
|
|
|
uint8_t adc_address= ADC_TARGET_BASE_ADDRESS + slot_id;
|
|
|
- //printf("Reading ADC Data from MCP3428 for channel: %u\n", params.channel);
|
|
|
+ printf("Reading ADC Data from MCP3428 for channel: %u\n", params.channel);
|
|
|
|
|
|
if(DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS){
|
|
|
printf("Error: I2C bus stuck! Resetting..\n");
|
|
|
@@ -146,11 +154,7 @@ int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params)
|
|
|
DL_I2C_startControllerTransfer(I2C_controller_INST, adc_address, DL_I2C_CONTROLLER_DIRECTION_RX, gRxADClen);
|
|
|
DL_I2C_enableInterrupt(I2C_controller_INST, DL_I2C_INTERRUPT_CONTROLLER_RXFIFO_TRIGGER);
|
|
|
while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
|
|
- delay_cycles(100000);
|
|
|
while(!gRxComplete);
|
|
|
-
|
|
|
-
|
|
|
- while (DL_I2C_getControllerStatus(I2C_controller_INST) & DL_I2C_CONTROLLER_STATUS_BUSY_BUS);
|
|
|
|
|
|
uint8_t msb= gRxPacket[0];
|
|
|
uint8_t lsb= gRxPacket[1];
|
|
|
@@ -179,6 +183,13 @@ int16_t ADC_ReadData(uint8_t slot_id, ADC_PARAMS params)
|
|
|
|
|
|
}
|
|
|
|
|
|
+// **Interrupt handler for ADC Read Completion**
|
|
|
+void I2C_ADC_IRQHandler(void) {
|
|
|
+ if (DL_I2C_getPendingInterrupt(I2C_controller_INST) == DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER) {
|
|
|
+ gRxComplete = true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
/* Function to Convert ADC Reading to Voltage */
|
|
|
uint16_t ADC_ConvertToVoltage(int16_t adc_value, ADC_PARAMS params) {
|
|
|
@@ -201,12 +212,6 @@ uint16_t ADC_ConvertToVoltage(int16_t adc_value, ADC_PARAMS params) {
|
|
|
return 0;
|
|
|
}
|
|
|
measured_voltage= (((uint32_t)adc_value * ADC_VREF_MV) * 3)/max_adc_value;
|
|
|
-
|
|
|
-
|
|
|
- /*Formula for ADC to Voltage Conversion*/
|
|
|
- //voltage = (adc_value / max_adc_value)* VREF/gain;
|
|
|
-
|
|
|
- //printf("Converted Voltage: %d mV\n", measured_voltage);
|
|
|
return (uint16_t)measured_voltage;
|
|
|
}
|
|
|
|
|
|
@@ -216,8 +221,9 @@ uint16_t ADC_ConvertToCurrent(int16_t adc_value, ADC_PARAMS params) {
|
|
|
//uint8_t r_shunt= 0.1;
|
|
|
//Convert ADC value to voltage across shunt resistor:
|
|
|
uint16_t voltage_mV= ADC_ConvertToVoltage(adc_value, params);
|
|
|
+ uint8_t gain_multiplier= (1 <<(params.gain - 1));
|
|
|
//Convert voltage drop across shunt resistor to current
|
|
|
- current_mA= (voltage_mV)/ 0.1;
|
|
|
+ current_mA= (voltage_mV)/ (0.1 * gain_multiplier);
|
|
|
//printf("Converted Current: %d mA.\n", current_mA);
|
|
|
return (int16_t)current_mA;
|
|
|
}
|
|
|
@@ -225,6 +231,7 @@ uint16_t ADC_ConvertToCurrent(int16_t adc_value, ADC_PARAMS params) {
|
|
|
void Battery_UpdateVoltage(ADC_PARAMS params){
|
|
|
for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
|
|
|
//CH1: Voltage Setup
|
|
|
+ params.channel= 1;
|
|
|
int16_t raw_adc_voltage= ADC_ReadData(slot, params);
|
|
|
batteries[slot].voltage= ADC_ConvertToVoltage(raw_adc_voltage, params);
|
|
|
printf("Battery Voltage for slot %d is %u mV.\n", slot, batteries[slot].voltage);
|
|
|
@@ -235,9 +242,40 @@ void Battery_UpdateVoltage(ADC_PARAMS params){
|
|
|
void Battery_UpdateCurrent(ADC_PARAMS params){
|
|
|
for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
|
|
|
//CH2: Charge Current
|
|
|
+ params.channel= 2;
|
|
|
int16_t raw_adc_current= ADC_ReadData(slot, params);
|
|
|
batteries[slot].current= ADC_ConvertToCurrent(raw_adc_current, params);
|
|
|
printf("Battery current for slot %d is %u mA.\n", slot, batteries[slot].current);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+void Battery_UpdateADCReading(){
|
|
|
+ ADC_PARAMS adc_params;
|
|
|
+
|
|
|
+ // For Channel 1: Voltage
|
|
|
+ adc_params.channel= 1;
|
|
|
+ adc_params.resolution= 12;
|
|
|
+ adc_params.continuous= 0;
|
|
|
+ adc_params.gain= 1;
|
|
|
+ ADC_SetConfigurationBytes(adc_params);
|
|
|
+ delay_cycles(50000);
|
|
|
+ for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
|
|
|
+ int16_t raw_adc_voltage= ADC_ReadData(slot, adc_params);
|
|
|
+ batteries[slot].voltage= ADC_ConvertToVoltage(raw_adc_voltage, adc_params);
|
|
|
+ printf("Battery Voltage for slot %d is %u mV.\n", slot, batteries[slot].voltage);
|
|
|
+ }
|
|
|
+
|
|
|
+ //For Channel 2: Current
|
|
|
+ adc_params.channel= 2;
|
|
|
+ ADC_SetConfigurationBytes(adc_params);
|
|
|
+ delay_cycles(50000);
|
|
|
+
|
|
|
+ for(uint8_t slot=0; slot< NUM_SLOTS; slot++ ){
|
|
|
+ int16_t raw_adc_current= ADC_ReadData(slot, adc_params);
|
|
|
+ batteries[slot].current= ADC_ConvertToCurrent(raw_adc_current, adc_params);
|
|
|
+ printf("Battery current for slot %d is %u mA.\n", slot, batteries[slot].current);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|