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 CCS Technical Support

PIC16F1947 and ADC

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



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PIC16F1947 and ADC
PostPosted: Sun Sep 23, 2012 10:37 pm     Reply with quote

Hey,

I have been trying to configure these ADC ports on the chip, I even built a basic test program to spit out to the screen what it sees and it appears to be lots of trash. Anyway before anyone asks AVss is connected to ground, and AVdd is connected to +5 volts, I am using a voltage divider of R1 = 10k Ohm, R2 = 7.15k Ohm to change 0 - 12 volts to roughly 0 to 5 volts, oh and I'm using a 32 MHz crystal cause it says it can run it at that speed in the data sheet. I can't seem to find anything simple to reference off of, can anyone help?

Code:

//Main pin configuration
#define STATUS1_LED   PIN_B1
#define ERROR1_LED   PIN_B2
#define STATUS2_LED   PIN_B3
#define ERROR2_LED   PIN_B4
#define TRIAC1      PIN_C1
#define TRIAC2      PIN_C2
#define AC_SIGNAL   PIN_B0
#define DIAG_SWITCH   PIN_D3
#define ALARM      PIN_D2

//RS485 pin configuration
#define RS485_RX   PIN_G2
#define RS485_TX   PIN_G1
#define TX_ENABLE   PIN_D0
#define RX_ENABLE   PIN_D1

//RS232 pin configuration
#define RS232_TX   PIN_C6
#define RS232_RX   PIN_C7

//Analog channel configuration
#define SIGNAL1_INPUT   0  //PIN_A0
#define SIGNAL1_MINIMUM   3  //PIN_A1
#define SIGNAL2_INPUT   2  //PIN_A2
#define SIGNAL2_MINIMUM   1  //PIN_A3
#define NTC1      4  //PIN_A5
#define NTC2      5  //PIN_F7
#define OPTION_SENSE1   6  //PIN_F1
#define OPTION_SENSE2   7  //PIN_F2
#define OPTION_SENSE3   10 //PIN_F5

//Program conditions
#define SIGNAL1         0#define SIGNAL2         1#define INPUT         0#define MINIMUM         1#define NTC            2

#include <16F1947.h>
#device ICD = TRUE;
#device ADC=10;
#fuses HS,PLL_SW,NOWDT,NOPROTECT,NOLVP
#use delay(clock=32000000) //Crystal Oscillator @ 32MHz
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)

void StartupSettings();

void main() {
   unsigned char uchSwitchValue, uchACSignalValue, uchLoopVal;
   unsigned long int uliADCValues[17];

   StartupSettings();

   uchSwitchValue = 0;
   uchACSignalValue = 0;

   output_high(STATUS1_LED);
   output_high(ERROR1_LED);
   output_high(STATUS2_LED);
   output_high(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS1_LED);
   delay_ms(500);
   output_low(ERROR1_LED);
   delay_ms(500);
   output_low(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS2_LED);
   delay_ms(1000);

   while (1) {
      uchACSignalValue = input_state(AC_SIGNAL);
      uchSwitchValue = input_state(DIAG_SWITCH);
      
      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         set_adc_channel(uchLoopVal);
         delay_ms(10);
         uliADCValues[uchLoopVal] = read_adc();
      }

      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         printf("Channel %u, Value = %Lu\n\r", uchLoopVal, uliADCValues[uchLoopVal]);
      }

   }

   return;
}

void StartupSettings() {
   set_tris_a(0x00);
   set_tris_b(0x01);
   set_tris_c(0x00);
   set_tris_d(0x08);
   set_tris_e(0x00);
   set_tris_f(0x00);
   set_tris_g(0x00);
   
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc_ports(ALL_ANALOG);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);
   return;
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Sep 24, 2012 1:04 am     Reply with quote

Start by re-reading the data sheet....

No, you can't run off a 32MHz crystal. The _processor_ can run to 32MHz, but requires that you use the PLL. The crystal oscillator, is rated to 20Mhz max.
Table 30-1 in the data sheet.

Ideally get yourself an 8Mhz crystal, and add the 'PLL' setting to the fuses. Then the processor will run at 32Mhz. You already have this setting, so the chip will be trying to multiply the incoming crystal frequency by 4, and going way above it's ratings.

I'd suggest this is the main problem. Often if you try to run a long way above the oscillator ratings, it'll lock onto an 'undertone'. So it is probably oscillating at perhaps 16Mhz, and hence the 'trash' on your display.

Start much simpler. A couple of line 'Hello World' program, and prove you are displaying what your expect. Only then move on to trying to use the ADC.

Add the keyword 'ERRORS' to your RS232 declaration. This _must_ be present when using the hardware RS232, unless _you_ handle hardware errors. This is becoming a 'mantra' that needs to be repeated again and again.

Then, ADC_CLOCK_INTERNAL, is _not_ recommended (it'll give inaccurate results), for a processor clock rate above 1MHz. On this chip it just says to avoid it, and that using the divider is better, but most chips have a more stringent warning about this.

Then you are setting the TRIS on the pins you are trying to use as analog inputs, to '0'. This will make them not work.
Get rid of all the TRIS lines. Unless you need to change things, the compiler _will_ handle TRIS for you, and won't make this type of mistake.

Get rid of the 'return' at the end of the main. There is nothing to return 'to'. No 'OS' sitting outside the code. If you get here, the code would be dying anyway....

Best Wishes
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Mon Sep 24, 2012 1:40 am     Reply with quote

Well here is what I get on a terminal window now

Code:

Channel 0, Value = 1
Channel 1, Value = 5
Channel 2, Value = 3
Channel 3, Value = 2
Channel 4, Value = 4
Channel 5, Value = 4
Channel 6, Value = 3
Channel 7, Value = 3
Channel 8, Value = 4
Channel 9, Value = 3
Channel 10, Value = 4
Channel 11, Value = 3
Channel 12, Value = 4
Channel 13, Value = 1023
Channel 14, Value = 1
Channel 15, Value = 1
Channel 16, Value = 1


I can change the crystal right now actually, and as for the Tris...well I have 2 digital inputs and a ton of digital outputs on the same port sharing the analogs, so...whats the alternative?
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Sep 24, 2012 1:57 am     Reply with quote

Either set the TRIS correctly, or let the compiler handle it. If you don't have the TRIS statements, the compiler _will_ correctly set the TRIS for you. It knows which pins you perform digital I/O on, and changes TRIS automatically. You are 'breaking' this.
That the chip runs, is a 'fluke'.....

Best Wishes
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Mon Sep 24, 2012 2:36 am     Reply with quote

Ok this is what I am seeing:

Code:

Channel 0, Value = 255
Channel 1, Value = 189
Channel 2, Value = 127
Channel 3, Value = 74
Channel 4, Value = 44
Channel 5, Value = 25
Channel 6, Value = 5
Channel 7, Value = 4
Channel 8, Value = 2
Channel 9, Value = 2
Channel 10, Value = 3
Channel 11, Value = 4
Channel 12, Value = 4
Channel 13, Value = 1023
Channel 14, Value = 4
Channel 15, Value = 4
Channel 16, Value = 255


But channel 0 and 1 are only changing by 2 or 3 values, I changed the crystal to 20 MHz cause I don't have any 8 MHz crystals with me and I adjusted my code. What else am I doing wrong?

Code:

//Main pin configuration
#define STATUS1_LED   PIN_B1
#define ERROR1_LED   PIN_B2
#define STATUS2_LED   PIN_B3
#define ERROR2_LED   PIN_B4
#define TRIAC1      PIN_C1
#define TRIAC2      PIN_C2
#define AC_SIGNAL   PIN_B0
#define DIAG_SWITCH   PIN_D3
#define ALARM      PIN_D2

//RS485 pin configuration
#define RS485_RX   PIN_G2
#define RS485_TX   PIN_G1
#define TX_ENABLE   PIN_D0
#define RX_ENABLE   PIN_D1

//RS232 pin configuration
#define RS232_TX   PIN_C6
#define RS232_RX   PIN_C7

//Analog channel configuration
#define SIGNAL1_INPUT   0  //PIN_A0
#define SIGNAL1_MINIMUM   3  //PIN_A1
#define SIGNAL2_INPUT   2  //PIN_A2
#define SIGNAL2_MINIMUM   1  //PIN_A3
#define NTC1      4  //PIN_A5
#define NTC2      5  //PIN_F7
#define OPTION_SENSE1   6  //PIN_F1
#define OPTION_SENSE2   7  //PIN_F2
#define OPTION_SENSE3   10 //PIN_F5

//Program conditions
#define SIGNAL1         0
#define SIGNAL2         1
#define INPUT         0
#define MINIMUM         1
#define NTC            2

#include <16F1947.h>
#device ICD = TRUE;
#device ADC=10;
#fuses HS,PLL_SW,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000) //Crystal Oscillator @ 20MHz
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)

void StartupSettings();

void main() {
   unsigned char uchSwitchValue, uchACSignalValue, uchLoopVal;
   unsigned long int uliADCValues[17];

   StartupSettings();

   uchSwitchValue = 0;
   uchACSignalValue = 0;

   output_high(STATUS1_LED);
   output_high(ERROR1_LED);
   output_high(STATUS2_LED);
   output_high(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS1_LED);
   delay_ms(500);
   output_low(ERROR1_LED);
   delay_ms(500);
   output_low(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS2_LED);
   delay_ms(1000);

   while (1) {
      uchACSignalValue = input_state(AC_SIGNAL);
      uchSwitchValue = input_state(DIAG_SWITCH);
      
      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         set_adc_channel(uchLoopVal);
         delay_ms(10);
         uliADCValues[uchLoopVal] = read_adc();
      }

      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         printf("Channel %u, Value = %Lu\n\r", uchLoopVal, uliADCValues[uchLoopVal]);
      }

      printf("\n\r");
      delay_ms(2000);

   }
}

void StartupSettings() {
   setup_adc(ADC_CLOCK_DIV_4);
   setup_adc_ports(ALL_ANALOG);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);
   
   return;
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Sep 24, 2012 3:26 am     Reply with quote

DIV_4, is too fast for the ADC with a 20MHz clock.

DIV_16, is the recommended value at this speed. Table 16-1. Note2.

Best Wishes
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Mon Sep 24, 2012 3:55 am     Reply with quote

Table 16-1 is for the DAC did you mean 15-1? Cause if thats so DIV_16 is "outside the recommended range" I have already tried all the DIV's even 32 and 8, it's forced all the ADC's to 0 when there is a voltage signal to them. There is still a problem here that I am not catching. Also there is a current to the ADC's I made sure at least 4 volts is going to the pin
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon Sep 24, 2012 5:16 am     Reply with quote

No.
The DAC, does not use a clock.

In the current microchip data sheet, table 16.1, is "ADC CLOCK PERIOD (TAD) VS. DEVICE OPERATING FREQUENCIES".

I suspect you may not have the current data sheet.

/16, is the 'borderline', but can be used, it doesn't have the note for the faster rates "These values violate the minimum required TAD time". /32, and /64, are the recommended ones at 20MHz.
At 32MHz, only /32, and /64 are recommended.
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Mon Sep 24, 2012 10:42 am     Reply with quote

Well here is the updated code

Code:

//Main pin configuration
#define STATUS1_LED   PIN_B1
#define ERROR1_LED   PIN_B2
#define STATUS2_LED   PIN_B3
#define ERROR2_LED   PIN_B4
#define TRIAC1      PIN_C1
#define TRIAC2      PIN_C2
#define AC_SIGNAL   PIN_B0
#define DIAG_SWITCH   PIN_D3
#define ALARM      PIN_D2

//RS485 pin configuration
#define RS485_RX   PIN_G2
#define RS485_TX   PIN_G1
#define TX_ENABLE   PIN_D0
#define RX_ENABLE   PIN_D1

//RS232 pin configuration
#define RS232_TX   PIN_C6
#define RS232_RX   PIN_C7

//Analog channel configuration
#define SIGNAL1_INPUT   0  //PIN_A0
#define SIGNAL1_MINIMUM   3  //PIN_A1
#define SIGNAL2_INPUT   2  //PIN_A2
#define SIGNAL2_MINIMUM   1  //PIN_A3
#define NTC1      4  //PIN_A5
#define NTC2      5  //PIN_F7
#define OPTION_SENSE1   6  //PIN_F1
#define OPTION_SENSE2   7  //PIN_F2
#define OPTION_SENSE3   10 //PIN_F5

//Program conditions
#define SIGNAL1         0#define SIGNAL2         1#define INPUT         0#define MINIMUM         1#define NTC            2

#include <16F1947.h>
#device ICD = TRUE;
#device ADC=10;
#fuses HS,PLL_SW,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20M, crystal) //Crystal Oscillator @ 20MHz
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7,ERRORS)

void StartupSettings();

void main() {
   unsigned char uchSwitchValue, uchACSignalValue, uchLoopVal;
   unsigned long int uliADCValues[17];

   StartupSettings();

   uchSwitchValue = 0;
   uchACSignalValue = 0;

   output_high(STATUS1_LED);
   output_high(ERROR1_LED);
   output_high(STATUS2_LED);
   output_high(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS1_LED);
   delay_ms(500);
   output_low(ERROR1_LED);
   delay_ms(500);
   output_low(ERROR2_LED);
   delay_ms(500);
   output_low(STATUS2_LED);
   delay_ms(1000);

   while (1) {
      uchACSignalValue = input_state(AC_SIGNAL);
      uchSwitchValue = input_state(DIAG_SWITCH);
      
      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         set_adc_channel(uchLoopVal);
         delay_ms(100);
         uliADCValues[uchLoopVal] = read_adc();
      }

      for (uchLoopVal = 0; uchLoopVal <= 16; uchLoopVal++) {
         printf("Channel %u, Value = %Lu\n\r", uchLoopVal, uliADCValues[uchLoopVal]);
      }

      printf("\n\r");
      delay_ms(2000);
   }
}

void StartupSettings() {
   setup_adc(ADC_CLOCK_DIV_16);
   setup_adc_ports(ALL_ANALOG);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_2);
   
   return;
}


I don't know what else to, I was off a few versions in the datasheet. But it doesn't matter what DIV I use, 2, 4, 8, 16, 32, 64, or Internal...not a single one of these settings work. So what's next to try? config the chip to behave on an internal clock of 8 MHz and remove the crystal off my circuit board?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 24, 2012 3:55 pm     Reply with quote

Make a much more simple test program. Get rid of about 90% of your
code. Put a 5K (or less) trimpot on pin AN0. Connect the ends of the
trimpot to +5v and ground, so you can supply any voltage in that range
to AN0. Make a test program similar to the one shown in this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=40279
Get that working first. Then try to make your larger program work.
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Mon Sep 24, 2012 4:31 pm     Reply with quote

Ok, now I'm starting to see some progress using this code

Code:

#include <16F1947.h>
#device adc=10
#fuses HS,PLL_SW,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=20000000) 
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//=================================
void main()
{
int16 result;

setup_adc_ports(sAN0|sAN1|sAN2|sAN3|sAN4|sAN5|sAN6|sAN7|sAN10);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
delay_us(15);

while(1)
  { 
   result = read_adc();
   printf("%LX \n\r", result);
   delay_ms(500);
  }

}


It's a bit jittery on the printf output but the POT seems to be putting out a reasonable output as far as a voltage signal goes on AN0,1,2,3 at least as for 4,5,6,7,10 I will require an external power supply to test them. It looks like the ATD's are reading properly now, I will post more on this message if an issue should surface when grafting segments of this code onto my main program, but for now, thank you all for your help I was getting frustrated and I want you to know I appreciate your assistance. Smile

(I would send everyone a beer if I had some)
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue Sep 25, 2012 1:07 am     Reply with quote

'Jittery'.
Some things to remember:
1) You are using the chip's power supply for your Vref. The result will depend on how accurate/stable this is. You may well be suffering from a supply that is a bit noisy. Have you got a capacitor with good HF blocking characteristics (ceramic, or polyester for example), right by the processor?.
2) Careful wiring to the pot. Does the ground connection go directly to the _processor_ ground pin (not somewhere else inches away on the board). Similarly for the other connections. Short, not passing near to circuits with magnetic fields (inductors etc,).
3) Nature of the pot. Some carbon pots, are inherently quite noisy (these are what used to produce the 'crackles' on the old TV/radio volume controls.

Best Wishes
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Tue Sep 25, 2012 1:14 am     Reply with quote

Thank you very much, I'll check some caps on my board ^.^
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