|
|
View previous topic :: View next topic |
Author |
Message |
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
AC DC Voltage and Current Sensors Using PIC18F25K80 |
Posted: Sat Jun 29, 2024 12:02 pm |
|
|
Hello honorable members and admins!
I am sensing AC and DC current and voltage and frequency. Everything is working but the Dc_current swings a lot. AC Voltage, AC Current, Frequency and DC Voltage are as stable as they coul be but the Dc current cannot stay at one place! I don't have scope. but if I put mymeter on the ADC pin it seems stable so I instructed the LCD to display the ADC voltave of the DC Current, on the LCD the ADC coltave also seems to be swinging changing capacitors or different values and precitions could not help much.
Below is the code I am working with:
Code: |
#include <18f25k80.h>
#device ADC = 12
#FUSES NOWDT,INTRC_IO, PUT, NOPROTECT, NOMCLR, NOCPD, BROWNOUT,NOIESO, FCMEN, NOCANC,NOCANB
#use delay(clock = 16000000)
#use I2C(master, I2C1, FAST = 100000,NOFLOAT_HIGH,FORCE_HW, STREAM = I2C_LCD)
#include <I2C_LCD.c>
#define ADC_RESOLUTION 4096 // max. ADC output
#define HIGH_START 0xFF -250 //500us INT_RTCC
#define sys_led PIN_B6
#define VREF 5.0 // Reference voltage for ADC
#define R1 120000.0 // 120K Ohm resistor
#define R2 2200.0 // 2.2K Ohm resistor
//*************************** Non Blocking Timer0 Delay Variables **************************
int display_dl;
int Sdisplay_dl;
int16 Cdisplay_dl,Counter_sys_1s;
// ******************************************************************************************
//******************************* other variables ********************************************
int display;
int16 mains;
float batt,ac_current,dc_current;
FLOAT adc_volt=0.0;
int16 avgResult_mains = 0;
int16 avgResult_ac_current = 0;
void init()
{
setup_oscillator (OSC_INTRC|OSC_16MHZ|OSC_NORMAL|OSC_PLL_OFF);
setup_adc (ADC_CLOCK_DIV_16);
setup_adc_ports (sAN1|sAN2|sAN3|sAN4|VSS_VDD); // Select Analog Inputs
setup_comparator (NC_NC_NC_NC); // disable comparator module
SET_TIMER0 (HIGH_START);
SETUP_TIMER_0 (T0_INTERNAL|T0_DIV_8|T0_8_BIT);
enable_interrupts (INT_TIMER0);
enable_interrupts (global);
display_dl = 0;
Sdisplay_dl = 0;
//delay_ms (3000) ;
}
// the timer is incremented (16000000/4)/16 or 500000 times a second (2 us).
// 250 x 2us = 500us
#INT_TIMER0
void clock_isr()
{
// Start Delay///////////////////////////////////////////////////////////
IF (Sdisplay_dl)
{
IF (++Cdisplay_dl >= (1000 * 2))//1s
{
Sdisplay_dl = 0;
display_dl = 1;
}
}
ELSE Cdisplay_dl = 0;
//**********************SYSTEM LED Flash Settings******************************
IF (++Counter_SYS_1s >= (1000 * 2))//1s
{
Counter_sys_1s = 0;
output_toggle (sys_led);
}
}
//*****************************************************************************/
//********* FUNCTIONS TO READ AC CURRENT ON CHANNEL 4 ***************************/
FLOAT Get_ac_current ()
{
set_adc_channel (4); //Select AN4 as ADC Input FOR acs
FLOAT acsHigh = 0;
FLOAT acsLow = ADC_RESOLUTION;
INT16 acs = 0; //variable to store analog reads
for (INT i = 0; i < 40; i++)
{
delay_us (500);
acs = read_adc (); // read ADC every time
IF (acs > acsHigh)
acsHigh = acs;
IF (acs < acsLow)
acsLow = acs;
}
RETURN (acsHigh - acsLow); // retutn value that was somehow averaged
}
//**************** FUNCTIONS TO READ MAINS VOLTAGE ON CHANNEL 1 *******************/
INT16 Get_mains_voltage ()
{
set_adc_channel (1); //Select AN1 as ADC Input FOR ms
INT16 mainsHigh = 0;
INT16 mainsLow = ADC_RESOLUTION;
INT16 ms = 0; //variable to store analog reads
for (INT i = 0; i < 40; i++)
{
delay_us (500);
ms = read_adc (); // read ADC every time
IF (ms > mainsHigh)
mainsHigh = ms;
IF (ms < mainsLow)
mainsLow = ms;
}
RETURN (mainsHigh - mainsLow); // retutn value that was somehow averaged
}
//****************** FUNCTIONS TO READ DC CURRENT ON CHANNEL 2 ***************************/
float get_dc_current ()
//FLOAT get_dc_current ()
{
set_adc_channel (2); // Select channel AN2
INT16 dcs_SENSE; //variable to store analog reads
FLOAT dcs_SENSE_Average;
FLOAT dcs_SENSE_Samples;
//FLOAT adc_volt=0.0;
FLOAT CURRENT;
INT n_sample = 100;
delay_us (500); // let ADC settle before next sample 500us
dcs_SENSE = read_adc ();
for (INT i = 0; i < n_sample; i++) //Get 100 dcs_SENSE_Samples
{
dcs_SENSE_Samples = dcs_SENSE_Samples += dcs_SENSE; //Add samples together
}
dcs_SENSE_Average = dcs_SENSE_Samples /= n_sample; //Taking Average of ac2 Sense Samples
delay_us (500); // let ADC settle before next sample 500us
adc_volt = dcs_SENSE_Average *(VREF/4095.0);
current = (adc_volt)/50.0/0.001;// Gain 50 for INA139NA AND R001 SHUNT
RETURN (current);
}
//
//************** FUNCTIONS TO READ BATTERY VOLTAGE ON CHANNEL 3 **************************/
float read_battery_voltage() {
int16 adc_value;
float batt_volt, adc_voltage, divider_ratio;
set_adc_channel(3);
delay_us(500);
// Read ADC value
adc_value = read_adc();
// Calculate voltage divider ratio
divider_ratio = (R1 + R2) / R2;
// Convert ADC value to voltage
adc_voltage = (adc_value * VREF) / 4095.0; // 12-bit ADC, so 2^12-1 = 4095
// Calculate battery voltage
batt_volt = adc_voltage * divider_ratio;
return batt_volt;
}
VOID lcd_display (void)
{
CHAR line1[21];
CHAR line2[21];
CHAR line3[21];
CHAR line4[21];
sprintf (line1, " AC DC SENSORS ");
lcd_GOTO (1, 1); // Go to column 1 row 1
printf (lcd_out, line1);
sprintf (line2, "BATTERY: %2.1gV %2.1gA ", batt, dc_current);
lcd_GOTO (1, 2); // Go to column 1 row 2
printf (lcd_out, line2);
sprintf (line3, "MAINS %3LuV %2.1gA ", mains, ac_current);
lcd_GOTO (1, 3); // Go to column 1 row 3
printf (lcd_out, line3);
sprintf (line4, " DC CURRENT %2.3gV ", adc_volt);
lcd_GOTO (1, 4); // Go to column 1 row 4
printf (lcd_out, line4);
}
//********************************/
VOID main (void)
{
init ();
delay_ms (100);
LCD_Begin (0x4E); //PCF8574 (111) // Initialize LCD module with I2C address = 0x4E
delay_ms (2000) ;
WHILE (TRUE)
{
//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC Parameter Calculations CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA FOR Mains Voltage AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
for (INT i = 0; i < 10; i++)
{
avgResult_mains += Get_mains_voltage ();
}
avgResult_mains = avgResult_mains / 10;
mains = 0.0285 * avgResult_mains;
avgResult_mains = 0;
//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA FOR CT AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
for (INT i = 0; i < 10; i++)
{
avgResult_ac_current += Get_ac_current ();
}
avgResult_ac_current = avgResult_ac_current / 10;
ac_current = (0.0050 * avgResult_ac_current);
avgResult_ac_current = 0;
// BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB FOR BATTERY BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Batt = read_battery_voltage();
//DDDDDDDDDDDDDDDDDCCCCCCCCCCCCCCCCCC FOR DC CURRENT DDDDDDDDDDDDDCCCCCCCCCCCCCCCCCCCCC
/*
* INA139 Current (I) :
* = ADC * ((5/4096) / 50 / Rshunt) // 50 IS GAIN
*/
dc_current = get_dc_current ();
//*******************************************************************************
//******************************** DISPLAY SETTINGS STARTS **************************
display = 1;// Variable to cause non b,ocling delay 1000ms to start runing
IF (display == 1)
{
Sdisplay_dl = 1;
IF (display_dl)
{
lcd_display () ;
display_dl = 0;
}
}
ELSE Cdisplay_dl = 0;
}
}
| [/b] _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Sat Jun 29, 2024 12:18 pm |
|
|
I started this topic; Please could any one here tell me what is wrong with this code. I forgot to mention that I attached the circuit on a battery charger between the dc bus voltage, It measures current for the high side. My clamp meter at the same wire does not swing. It is ver stable. It decreases and increases accordingnly the way it should be for a battery charger. _________________ All is well even in the well! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9237 Location: Greensville,Ontario
|
|
Posted: Sat Jun 29, 2024 2:28 pm |
|
|
Your DMM ,if like 99.44% of the others, ONLY samples every 3 reading per second, so you should adjust your DC amps function to be similar.
Also, instead of taking 100 samples, take 64 or 128. Makes it a LOT faster on the divide math.
Perhaps do 'Olympic' averaging ( 10 readings,delete highest,lowest, avg the remaining 8 ) it may give better results.
what is the current sensor device ( link ? ) ,may have wrong interface to it ?? |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Sat Jun 29, 2024 3:57 pm |
|
|
As I am using for ADCs, can I apply the Olympic Averaging only to the dc_current measurements. Can others still work the way they are? _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Sat Jun 29, 2024 4:05 pm |
|
|
As I am using four ADCs, can I apply the Olympic Averaging only to the dc_current measurements. Can others still work the way they are? _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Sat Jun 29, 2024 6:00 pm |
|
|
Ok. I have applied the Olympic Averaging in simulator only for DC Current and other sensors are working. In the morning I will do it in hardware _________________ All is well even in the well! |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9237 Location: Greensville,Ontario
|
|
Posted: Sat Jun 29, 2024 6:27 pm |
|
|
I had a quick look at the sensor and T suggests using a unity gain 'buffer' between it and the ADC as well as a 'low pass ' filter.
You should do as they say, in order to get accurate readings. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Sun Jun 30, 2024 3:01 am |
|
|
It's worth understanding that the ADC's used on 99% of low priced DMM's
are what are knows as "dual slope integrating ADC's". These are one of the
few ADC's giving high accuracy at low price, but do this by actually
integrating the incoming source for a time, then comparing this to an
integration the 'other way', from the reference, till the value gets back to
zero. The time taken, then gives a nice accurate value, but a value for the
integrated voltage (so over time), not the instantaneous value.
'Fast reading' DMM's, cost dozens of times what the normal DMM costs.
I have a 5 1/2 digit Fluke unit, that does 25 readings per second, versus
my normal one that manages 4. This actually allows several million samples
per second to be recorded, but not displayed. The former costs nearly
£2000, when my equivalent accuracy normal DMM, is about £100. The
fast unit also requires much more frequent calibration to remain certified.
A couple of my more reasonably priced units do have a low accuracy 'bar
graph' display below the main reading that responds quickly, and this is a
common way of giving the quick response.
This is a huge 'caveat' about such DMM's!.
For many years (when DMM's first appeared), the speed was even worse,
and this was one of the reasons why adoption of DVM's was slow. A simple
old AVO meter, would show a signal fluctuating, with the needle wobbling,
when the DMM was saying the voltage was stable......
The slow speed of units is actually in part deliberate!. The 250mSec
sample rate provides an inherent 'notch' filter for multiples of the
mains frequencies used worldwide (50/60Hz). Also an update at 4Hz,
is readable, while if (for instance) the display was updating at 20Hz,
and flickering between 201, and 101, you could see this as 301.
Some nicer modern units actually allow the reading speed to be set
(Agilent for example have units that do this). Generally really fast speeds
are only workable on units that have PC connections, or memories, so
you can step back to look at readings. |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Sun Jun 30, 2024 4:13 am |
|
|
Ttelmah wrote: | It's worth understanding that the ADC's used on 99% of low priced DMM's
are what are knows as "dual slope integrating ADC's". These are one of the
few ADC's giving high accuracy at low price, but do this by actually
integrating the incoming source for a time, then comparing this to an
integration the 'other way', from the reference, till the value gets back to
zero. The time taken, then gives a nice accurate value, but a value for the
integrated voltage (so over time), not the instantaneous value.
'Fast reading' DMM's, cost dozens of times what the normal DMM costs.
I have a 5 1/2 digit Fluke unit, that does 25 readings per second, versus
my normal one that manages 4. This actually allows several million samples
per second to be recorded, but not displayed. The former costs nearly
£2000, when my equivalent accuracy normal DMM, is about £100. The
fast unit also requires much more frequent calibration to remain certified.
A couple of my more reasonably priced units do have a low accuracy 'bar
graph' display below the main reading that responds quickly, and this is a
common way of giving the quick response.
This is a huge 'caveat' about such DMM's!.
For many years (when DMM's first appeared), the speed was even worse,
and this was one of the reasons why adoption of DVM's was slow. A simple
old AVO meter, would show a signal fluctuating, with the needle wobbling,
when the DMM was saying the voltage was stable......
The slow speed of units is actually in part deliberate!. The 250mSec
sample rate provides an inherent 'notch' filter for multiples of the
mains frequencies used worldwide (50/60Hz). Also an update at 4Hz,
is readable, while if (for instance) the display was updating at 20Hz,
and flickering between 201, and 101, you could see this as 301.
Some nicer modern units actually allow the reading speed to be set
(Agilent for example have units that do this). Generally really fast speeds
are only workable on units that have PC connections, or memories, so
you can step back to look at readings. |
It's true, especially the AVO meter you mentioned. _________________ All is well even in the well! |
|
|
mcmsat
Joined: 25 May 2018 Posts: 51 Location: Nigeria
|
|
Posted: Tue Jul 09, 2024 1:05 am |
|
|
temtronic wrote: | Your DMM ,if like 99.44% of the others, ONLY samples every 3 reading per second, so you should adjust your DC amps function to be similar.
Also, instead of taking 100 samples, take 64 or 128. Makes it a LOT faster on the divide math.
Perhaps do 'Olympic' averaging ( 10 readings,delete highest,lowest, avg the remaining 8 ) it may give better results.
what is the current sensor device ( link ? ) ,may have wrong interface to it ?? |
I'm sorry for the late reply. I was away from the house, engaged in something that never allow a spare time to attend other things.
The Olympic Averaging worked for me and with some filterations. Thanks everyone who helped _________________ All is well even in the well! |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|