View previous topic :: View next topic |
Author |
Message |
rachel Guest
|
sampling |
Posted: Tue May 04, 2004 8:33 am |
|
|
i want to make a timing through it i can sample an input voltage.
i know that i must use timer and interruption but i can't do it lonely |
|
|
nfs
Joined: 28 Apr 2004 Posts: 18
|
hi |
Posted: Tue May 04, 2004 8:38 am |
|
|
me too i search to resolve the same problem if you find a solution plz tell me thank you _________________ nfs |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Tue May 04, 2004 12:37 pm |
|
|
Look up Microchip Application Note AN513 and see if that is what you are asking about. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 04, 2004 1:02 pm |
|
|
If you want a simple program that will read an analog voltage
once every hour, and send the result to a PC by RS-232,
then here is an example:
I wanted to learn how quickly the batteries were used up
on a battery-operated project. So, I made this simple program
to run on my 16F877 demo board. I connected pin RA0 and ground
from my demo board to the battery terminals on the target board.
Then I connected a serial port cable between my demo board
and a PC. The PC was running a RS232 terminal program.
Then I let it run for several days. After that time, I took
the data and imported it into Microsoft Excel, and produced
a graph which showed me how long the batteries would last.
Code: | #include <16F877.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#define TIMER1_PRESET 3036
#define ADC_RIGHT_JUSTIFY 1
#define ADC_LEFT_JUSTIFY 0
#bit ADFM_BIT = 0x9F.7
int16 half_second_counter;
int16 hours_counter;
char one_hour_flag;
void timer1_isr(void);
//===============================
main()
{
int16 adc_result;
char low_bat_pin;
low_bat_pin = 1;
half_second_counter = 0;
hours_counter = 0;
one_hour_flag = FALSE;
setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
ADFM_BIT = ADC_RIGHT_JUSTIFY;
printf("Checking voltage once per hour.\n\r");
adc_result = read_adc();
low_bat_pin = input(PIN_B3);
printf("Hour = %ld, ADC = %ld LoBat pin = %u \n\r", hours_counter, adc_result, low_bat_pin);
set_timer1(TIMER1_PRESET);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
while(1)
{
if(one_hour_flag == TRUE)
{
one_hour_flag = FALSE;
adc_result = read_adc();
low_bat_pin = input(PIN_B3);
printf("Hour = %ld, ADC = %ld LoBat pin = %u \n\r", hours_counter, adc_result, low_bat_pin);
}
}
}
//----------------------------------
#int_timer1
void timer1_isr(void)
{
setup_timer_1(T1_DISABLED);
set_timer1(TIMER1_PRESET);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
half_second_counter++;
if(half_second_counter == 7200) // Reached 1 hour ?
{
one_hour_flag = TRUE;
half_second_counter = 0;
hours_counter++;
}
}
|
|
|
|
rachel Guest
|
re |
Posted: Wed May 05, 2004 8:13 am |
|
|
thank you for the example
but if i want to store samples in RAM to mesure the average during a certain period. how i can do this? |
|
|
Haplo
Joined: 06 Sep 2003 Posts: 659 Location: Sydney, Australia
|
|
Posted: Wed May 05, 2004 8:30 am |
|
|
Simply store the A/D results in an array instead of sending them to the serial port. This way you can calculate the average later. |
|
|
Neutone
Joined: 08 Sep 2003 Posts: 839 Location: Houston
|
Re: re |
Posted: Wed May 05, 2004 9:01 am |
|
|
rachel wrote: | thank you for the example
but if i want to store samples in RAM to mesure the average during a certain period. how i can do this? |
Keep a running total of sample values and number of samples. Then divide total by number of samples. This will allow you to use any number of samples when averaging. |
|
|
SteveS
Joined: 27 Oct 2003 Posts: 126
|
|
Posted: Thu May 06, 2004 6:57 am |
|
|
And if you want to do a 'running average' or filtering - meaning you have continuous input and want a continuous, averaged, output then:
1. Use a circular buffer to store the samples - average across the buffer each sample.
-or-
2. Filter with a simple digital filter - a really simple, and effective, filter is
Code: |
NewOut = 0.75 * NewIn + 0.25 * OldOut
OldOut = NewOut
where : NewIn is your latest sample
NewOut is the latest output
OldOut is the last output
|
Note that coefficients shown are easy to do with adds and shifts. The larger the NewIn coefficent the more averaging. Just be sure the two coefficent add to 1.
-or-
3. Use a median filter- There you take an odd number of input samples and use the median value as the new output. Harder to code efficiently, but kills spike noise and preserves legitimite step changes. |
|
|
rachel Guest
|
RE |
Posted: Thu May 06, 2004 9:16 am |
|
|
I'm not speakin about averaging voltage but ADC results. |
|
|
SteveS
Joined: 27 Oct 2003 Posts: 126
|
|
Posted: Thu May 06, 2004 2:29 pm |
|
|
All the posted techniques work on the ADC data. |
|
|
|