CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Analog sampling on 16f819 Help Please!

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
trishide



Joined: 11 Mar 2005
Posts: 2

View user's profile Send private message

Analog sampling on 16f819 Help Please!
PostPosted: Mon Mar 14, 2005 10:07 am     Reply with quote

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 Smile
jma_1



Joined: 08 Feb 2005
Posts: 147
Location: Wisconsin

View user's profile Send private message

PostPosted: Mon Mar 14, 2005 10:24 am     Reply with quote

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....
PostPosted: Mon Mar 14, 2005 9:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Mar 16, 2005 7:13 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Mar 18, 2005 6:03 am     Reply with quote

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) Crying or Very sad we really don't know why its not working!
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Mar 18, 2005 7:44 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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