I am working on a project using the Texas Instruments EK-TM4C123GXL LaunchPad to measure the voltage of a breadboard power supply module(hw-131) . I am using the onboard ADC module to read the voltage, but I am facing some issues:
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_ints.h"
#include "driverlib/sysctl.h"
#include "driverlib/adc.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/uart.h"
#include "utils/uartstdio.h"
#include "driverlib/pin_map.h"
#define NUM_SAMPLES 8
// Function to configure UART0 for communication
void ConfigureUART(void)
{
// Enable UART0 and GPIOA peripherals
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
// Configure PA0 and PA1 as UART pins
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
// Initialize UART0 with a baud rate of 115200
UARTStdioConfig(0, 115200, SysCtlClockGet());
}
// ADC0 interrupt handler
void ADC0IntHandler(void)
{
// Clear the ADC interrupt flag
ADCIntClear(ADC0_BASE, 0);
uint32_t ui32ADC0Value[NUM_SAMPLES];
uint32_t ui32Sum = 0;
uint32_t i = 0;
// Get the ADC sequence data
ADCSequenceDataGet(ADC0_BASE, 0, ui32ADC0Value);
// Sum the ADC values
while(i < NUM_SAMPLES){
ui32Sum += ui32ADC0Value[i];
i++;
}
// Calculate the average ADC value
uint32_t ui32Average = ui32Sum / NUM_SAMPLES;
// Print the average ADC value to the UART
UARTprintf("ADC Average Value: %d\n", ui32Average);
// Calculate the input voltage in volts (assuming 3.3V reference voltage)
float voltage = (ui32Average * 3.3) / 4096.0;
uint32_t v_int_part = voltage; // Integer part of the voltage
uint32_t v_frac_part = (voltage - v_int_part) * 1000; // Fractional part in millivolts
// Print the calculated voltage to the UART
UARTprintf("Input Voltage: %d.%03d V\n", v_int_part, v_frac_part);
}
int main(void)
{
// Set the system clock to 50MHz (200MHz PLL / 4)
SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
// Configure UART for debugging
ConfigureUART();
// Enable the ADC0 and GPIOE peripherals
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
// Wait for the peripherals to be ready
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_ADC0) || !SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE))
{
}
// Configure PE3 as ADC input
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3);
// Set the ADC clock source and rate
ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 8);
// Configure ADC sequence 0 to be triggered by the processor
ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_PROCESSOR, 0);
// Configure all 8 steps in the sequence to sample from CH0 (PE3)
ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); // Enable interrupt on last step
// Enable ADC sequence 0
ADCSequenceEnable(ADC0_BASE, 0);
// Clear any pending ADC interrupts
ADCIntClear(ADC0_BASE, 0);
// Enable ADC interrupts
ADCIntEnable(ADC0_BASE, 0);
// Enable the ADC0 sequence 0 interrupt in the NVIC
IntEnable(INT_ADC0SS0);
// Set ADC0 sequence 0 interrupt priority to highest (0)
IntPrioritySet(INT_ADC0SS0, 0x00);
while(1)
{
// Trigger the ADC conversion
ADCProcessorTrigger(ADC0_BASE, 0);
// Delay to simulate some processing time
SysCtlDelay(SysCtlClockGet() / 6);
}
}
It seems that power supply module OFF fluctuate more significantly than power supply module ON.
Any suggestions or guidance would be greatly appreciated! Thank you!
The large fluctuations are errors in your debug output and not "real". For example when you have an ADC value 9
corresponding to (9 x 3.3) / 4096 = 0.007 Volts, your debug code is outputting 0.7 Volts.
It looks as if your UARTprintf
function does not support the %03d
format-specifier. Or the code you have posted is not the same as the code generating that output. Save yourself the trouble, and use integer arithmetic and output the value in millivolts.
Otherwise I would say that the raw ADC fluctuation is a plausible level electrical noise from your power supply, the MCU itself, or even cross-talk from the UART output.
Your attempt at averaging is ineffective, taking only 8 samples probably at a far higher frequency than the noise you are trying to remove. A larger moving average or an average taken from many readings over a long period of perhaps 0.5 seconds, or even an FIR or IIR low-pass filter would produce far better results. Either way your signal conditioning needs to be appropriate to the characteristics of the noise you are observing. Note that such a filter will perform poorly if the sample rate is variable, which it will be if you attempt to output readings to the UART in the interrupt handler - just one more way your debug code will give you misleading results.