View previous topic :: View next topic |
Author |
Message |
trishide
Joined: 11 Mar 2005 Posts: 2
|
Analog sampling on 16f819 Help Please! |
Posted: Mon Mar 14, 2005 10:07 am |
|
|
hi we are trying to read in a varied analog bit stream which uses fsk which is sent through an envelop detector to vary the amplitute. Our code calulates the amplitude of each pulse and determines whether it is a 1 or 0. Unfortunatley we keep getting random output and we dont know why. This is our code. Is there anything wrong with it?
Code: |
#include <16F819.h>
#include <stdlib.h>
#include <stdio.h>
#fuses HS,NOWDT,NOPROTECT,PUT
#use delay (clock=4000000)
#use fast_io(B)
main()
{
int read1, min, max, read2, amp, bit, i, j;
char bitarray[5];
char zero[] = "00000";
//set_tris_a (0x01); //a0 input rest outputs
set_tris_b (0x00); //port b output
Port_b_pullups (true);
setup_adc_ports(RA0_RA1_ANALOG_RA3_REF); //set pin a0 as analog input ra3 reference voltage
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel( 0 ); //Use RA0 for ANALOG input into A/D.
delay_us(10);
//min = 84;
//max = 194; //3.8v
while (1)
{
for (i=0; i<5; i++)
{
read1 = read_adc(); //\
delay_us(5); // > consecutive readings
read2 = read_adc(); ///
/* while(read2>read1) //rising edge
{
max = read2;
read1 = read_adc(); //\
//delay_us(5); // > consecutive readings
read2 = read_adc(); ///
}*/
while(read2<=read1) //falling edge
{
min = read2;
read1 = read_adc(); //\
//delay_us(5); // > consecutive readings
read2 = read_adc(); ///
}
amp = 198 - min; //calculate amplitude
if(amp<=90) //if amplitude < 3v
{
output_low(pin_b6);
bit = 0;
}
else
{
output_high(pin_b6);
bit = 1;
}
bitarray[i] = bit; //add bit to array
}
/*for (j=0; j<5; j++)
{
for (i=0; i<5; i++)
{
if (bitarray[i]==0)
{
output_low(pin_b5);
delay_ms(500);
}
else
{
output_high(pin_b5);
delay_ms(500);
}
}
}*/
}
}
|
Thabks for looking |
|
|
jma_1
Joined: 08 Feb 2005 Posts: 147 Location: Wisconsin
|
|
Posted: Mon Mar 14, 2005 10:24 am |
|
|
Greetings,
I do not remember off the top of my head all the details of the 16F819, but double check the A/D conversion (8, 10, etc). If the A/D conversion is 10 bits, change your initialization of read1, read2, min, max to int16. This probably isn't the problem, but it's worth looking at.
Justin |
|
|
Guest Guest
|
Analog sampling.... |
Posted: Mon Mar 14, 2005 9:04 pm |
|
|
What is the frequency content of your signal? How big is the difference (in volts) between a 1 and a 0?
You are just sampling "open loop" as far as I can see. No synchronization, etc. You will always get a difference between 2 subsequent ADC grabs, and you will be misled into thinking you have found a "rising" or "falling" edge. IF your signal is very low frequency, you can be sampling on essentially "DC" regions of the data. And if it is very high frequency, you may miss "bits" in the signal. Don't you need a clock to time the data grabs?
I am not suprised you get random output, to be honest. Then again, I don't know anything about FSK and how it is normally detected..... |
|
|
trishide
Joined: 11 Mar 2005 Posts: 2
|
|
Posted: Wed Mar 16, 2005 7:13 am |
|
|
hi. Thanks we've gotten rid of the envelope detector and are calulating the number of peaks over each millisecond. The input is either 7 or 17 KHz depending if it is a 0 or 1 (repectively). However we keep getting incorrect output (i,e always less than 7Khz). After an interrupt occurs, when it returns to the main program, where does it return to? The start of main() or the next line of code it was about to execute?
This is our new code
Code: |
#include <16F819.h>
#device *=16 ADC=10
#include <stdlib.h>
#include <stdio.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay (clock=4000000)
#use fast_io(A)
#use fast_io(B)
#define INT_PER_MSSECONDS 2
BYTE m_seconds; // A running seconds counter
BYTE int_count; // Number of interrupts left before a second has elapsed
int peakNo; // Initialise peakNo
#INT_TIMER0
void clock_isr()
{
int PN;
if(--int_count==0)
{
PN = peakNo;
peakNo = 0;
++m_seconds;
int_count=INT_PER_MSSECONDS;
if (PN == 0)
{
output_high(pin_b4); //b4 testing
}
else if (PN < 9)
{
output_high(pin_b5); //b5
}
else if (PN > 15)
{
output_high(pin_b6); //b6
}
else
{
output_b(0xff);
}
output_low(pin_b4);
output_low(pin_b5);
output_low(pin_b6);
}
}
int16 readAn()
{
int16 val;
val = read_adc();
delay_us(10);
return val;
}
void main()
{
int16 value;
int peak;
peakNo = 0;
set_tris_b (0x00); //port b output
Port_b_pullups (true);
setup_adc_ports(A_ANALOG); //all port a analog and ref=vdd (not A4 - used for timer0)
setup_adc (ADC_CLOCK_INTERNAL);
set_adc_channel ( 0 ); //Use RA0 for ANALOG input into A/D.
delay_us (10);
set_timer0 (0);
int_count = INT_PER_MSSECONDS;
setup_timer_0 (RTCC_DIV_2|RTCC_INTERNAL);
enable_interrupts (INT_TIMER0);
enable_interrupts (GLOBAL);
output_high(PIN_B7); //checks if program enters main
do
{
output_high(PIN_B1);
while ((readAn()) >= 400) //voltage is 1V
{
output_high(PIN_B2); //checks if program enters peak of a sine wave
peak = 1;
}
output_low(PIN_B2);
if (peak != 0)
{
output_high(PIN_B3); //checks if program increments peakNo
peakNo=peakNo+1;
peak = 0;
}
output_low(PIN_B3);
output_low(PIN_B1);
} while(true);
output_low(PIN_B7);
}
|
|
|
|
trishide
Joined: 11 Mar 2005 Posts: 2
|
|
Posted: Fri Mar 18, 2005 6:03 am |
|
|
hi weve changed the code to the code in the post above. Does anyone know where the code starts executing in the main after an interrupt returns? (ie start of main or the next line of code it was about to execute before the interrupt was called) we really don't know why its not working! |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Fri Mar 18, 2005 7:44 am |
|
|
The whole point of interrupts is that the precessor resumes executing where it left off. The interrupt may be executed in the middle of a line of main() code, and main() has no way of knowing unless the interrupt set a flag of some sort. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
|