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

Problem with AD PIC12F683

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



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

Problem with AD PIC12F683
PostPosted: Tue Jun 16, 2015 6:07 pm     Reply with quote

I have a 6 years of experience in PIC programing C CCS and I have had a problem with a particular device: PIC12F683. I connected a potentiometer in A/D input (AN3) and got the result to use in a PWM OUT and it works fine! zero potentiometer... zero PWM OUT, max potentiometer, max PWM OUT. But when i try comparate the value of AD at runtime, the max value of A/D (10 bits) is 65534 instead 1023, however, the PWM keeps running.

At 2.5V rms in oscilloscope the ADC value is 1024 and the pwm is 50% in the PWM OUT

The simple code I used to test.
Code:

#include <12F683.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOBROWNOUT               //No brownout reset

#use delay(internal=8000000)

#DEFINE min_led pin_a1
#DEFINE max_led pin_a0

int16 teste=0;

#INT_AD
void  AD_isr(void)
{
if (teste>1020)
{
output_high(max_led);
}else
output_low(max_led);

}

void main()
{
   setup_adc_ports(sAN3);
   setup_adc(ADC_CLOCK_DIV_2);

   enable_interrupts(INT_AD);
   enable_interrupts(GLOBAL);
   output_high(max_led);
   delay_ms(300);
   setup_timer_2(T2_DIV_BY_4,255,1);
 
   setup_ccp1(ccp_pwm);


   while(TRUE)
   {
   
   set_adc_channel(3);
   teste=(read_adc(ADC_START_AND_READ));
   set_pwm1_duty(teste);
   }

}

I knew a few bugs in the .h file some devices, if you guys can help me the versions of my compiller is CCS PCM C Compiler, Version 5.015.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jun 16, 2015 8:11 pm     Reply with quote

Quote:
the max value of A/D (10 bits) is 65534 instead 1023

Where in your program do you get the value of 65534 ?
I don't see any printf statement to display the ADC value.
Why do you think the ADC returns a value of 65534 ?
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 5:00 am     Reply with quote

You are trying to clock the ADC at 4MHz. This is way too fast. About 1MHz is the max for most PIC ADCs (dsPIC ones go faster). The datasheet, on page 62, recommends using dividing the clock by 16 or 32.

The ADC interrupt will fire when the ADC completes its conversion. That is BEFORE the read_adc() function returns. That means teste will not be set (it will, in fact have the value it had the last time it was set). Either set teste in the ISR, and use ADC_START_ONLY in the call to read_adc(), or better, forget about the ISR completely and just use the result returned by read_adc().

It is rare to need, or be able to properly use ADC ISRs. About the only time I've wanted to was to implement continuous self-scanning ADCs, where the ISR got the last result and started the next conversion in a never-ending loop. The idea was that the main program just read the buffered results and knew it was only ever one loop time out of date. It sort of worked, but took up a disproportional amount of processor time and was wasteful when many things, such as temperature and power supply voltages, changed slowly.

Your comments about the pot slightly surprise me. Many pots only have at most about 85% usable travel, that's to say they never quite get to 0 and full, they a several percent short at each end due to the way the pots that can turn through a complete circle (they were used for wind direction sensing) but even they only had 355 degrees of active travel, with the 5 degrees just west of north being "dead".
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 5:29 am     Reply with quote

PCM programmer wrote:
Quote:
the max value of A/D (10 bits) is 65534 instead 1023

Where in your program do you get the value of 65534 ?
I don't see any printf statement to display the ADC value.
Why do you think the ADC returns a value of 65534 ?


Yes, you're right in this part of the code:
Code:

if (teste>1020)
{
output_high(max_led);
}else
output_low(max_led);
}

I changed to 65534 and the led lit near full position of potentiometer.

I will check the waveform in the led output right now to know if have a oscillating value.
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 5:31 am     Reply with quote

To simplify the tests and eliminate variables I created another code, compiled in another version of CCS (4.068) and with another PIC (PIC12F675).

The problem continues...

Code:
#include <12F675.h>
#device adc=16
#FUSES NOWDT, INTRC_IO, NOCPD, PROTECT, NOMCLR, NOPUT, BROWNOUT// NOIESO,// NOFCMEN
#use delay(clock=4000000)

#define max_led pin_a0
int16 teste=0;

void main()
{
   setup_adc_ports(sAN3|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_comparator(NC_NC);
   setup_vref(FALSE);
//   setup_oscillator(OSC_4MHZ);

while (true)
{
set_adc_channel(3);
delay_ms(200);
teste=read_adc();
if (teste>1024)output_high(max_led); else output_low(max_led);
//The LED lighting at 120mV RMS on ADC input
//In the part PIC12F683 at 8Mhz freq osc and  //"setup_adc(ADC_CLOCK_INTERNAL);" the LED lights up 2.5 V Rms
//The adc input was checked and going 60mV Rms to 5,07 V Rms
//All of setup_adc modes were tested

The ADC works fine if I use INTRC OR RC, but the clock out in the adc input, even though the ADC conversion its ok, but the part warms because the potentiometer in some positions cause short circuit to clock out. My power supply is limited in 10 mA for obvious reasons.

}

}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 4:14 pm     Reply with quote

Quote:
//the LED lights up 2.5 V Rms
//The adc input was checked and going 60mV Rms to 5,07 V Rms
//All of setup_adc modes were tested

Are you connecting an AC signal to the A/D input pin (AN3) ?
The peak voltage of a 5.07 Vrms signal would be higher than +5.3v and
would violate the Absolute Maximum Ratings of voltage limits for the PIC's
i/o pins.

Does the AC voltage also go below -0.3 volts ? That also would be a
violation of the Absolute Maximum Ratings given in the Electrical
Specifications section of the 12F675 data sheet.

What is the frequency of your AC signal ?

------------
In the note that you tacked onto the other thread, you said:
Quote:
The VDD is 5,07 V RMS

PICs don't use AC signals for their Vdd. They use DC. Do you know
what RMS means ? It means Root-mean-square. It's a term used to
describe the average voltage of an AC signal. I think you are probably
really using 5vdc for your PIC's Vdd voltage, but you are wrongly using
"V rms" to describe it. I also wonder if maybe you are really using a
DC voltage on the A/D pin.

-------------
Also, doing this does not make the 12F675 magically have a 16-bit A/D:
Quote:
#include <12F675.h>
#device adc=16

It still has a 10-bit A/D converter, but the output is left justified instead
of being right justified. Example:

With #device adc=10 the read_adc() function will return values
from 0 to 1023. With #device adc=16 , it will return 0 as the
lowest result, but the next lowest will be 64, and the maximum is 65472.
Don't use #device adc=16, unless you know exactly why you are doing it.
It does not make the PIC magically have a 16-bit A/D.
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 5:44 pm     Reply with quote

Thank You PCM programmer to reply, the voltage is +5V DC to the pic and 0 to 5.07 DC (from the potentiometer) to AD. I know what is RMS, in my previous project I was using AC and my oscilloscope was in AC mode, and understand the issue, the tension really needs to be DC. thank you to ask me, often we do not realize simple mistakes and alternating voltage could be really a problem.
and all the times I wrote RMS was DC voltage , so that little ambiguity. I wrote wrong!

I Used #device adc=16 to try justify the bits in the var and some things changed: the pwm lost the linearity and stability of frequency. I am reading the datasheet of device to know the registers address and I will try to read the values directly, or clear the bits 10 to 15 from the var teste to test.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 5:56 pm     Reply with quote

Here is sample code to control the PWM duty cycle with a trimpot:
http://www.ccsinfo.com/forum/viewtopic.php?t=40222&start=1
This example is for a 16F877 with a 4 MHz crystal, but you can also
use it with a 12F683 with the internal (INTRC_IO) 4 MHz oscillator.
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 6:20 pm     Reply with quote

I do not know exactly what's going on but I cleaned the bits 10-15 of the teste var and it worked fine! it's ok! The PWM and the value of var test have the same

The code was:

bit_clear(teste,10);
bit_clear(teste,11);
bit_clear(teste,12);
bit_clear(teste,13);
bit_clear(teste,14);
bit_clear(teste,15);

the bits of high (00000000) and 2 bits (00) from the low... the rest seems being filled with 1 thereby : ADC Value(10 bits):0000000000+1111 of the 16bits var.

What is happen for it do this?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 17, 2015 7:02 pm     Reply with quote

Quote:
The code was:

bit_clear(teste,10);
bit_clear(teste,11);
bit_clear(teste,12);
bit_clear(teste,13);
bit_clear(teste,14);
bit_clear(teste,15);

Post the full test program that has those lines in it. Post the compiler
version you are using for this test.
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

Problem with AD PIC12F683 Solved!
PostPosted: Thu Jun 18, 2015 5:59 am     Reply with quote

The problem was in the unused bits of the 6 var test ( int16 ) que was filled with 1 instead 0. Its unknown why, but I used a bitmask to correct this.
Here is the complete code:
Code:

#include <12F683.h>
#device ADC=10;
#fuses INTRC_IO,NOWDT,PROTECT, NOMCLR   
#use delay(internal=8000000,RESTART_WDT)
#include <internal_eeprom.c>

#DEFINE min_led pin_a1
#DEFINE max_led pin_a0

//timer
int time=0;
int base_sec=0;
int base_led=0;
//fim timer

//DAC
int8  offset=0; //adjust of minimal voltage of sensor
int16 lco=200; //Low current output
int16 hco=1000; //High current output
float span=0;
int16 DAC=0;
unsigned int16 teste=0;
int32 x=0;

int16 s=0;


//adc
int32 adc=0;
// fim adc

void keys(void);

#int_timer2
void timing_dsy()
{
  time++;
  keys();
  if (time>12) //timebase 12ms
  {
  time=0;
  base_sec++;
  base_led++;
  }
  if (base_led>4) //timebase 64ms 15.6 Hz
  {
  base_led=0;

if (teste>1022)
{
output_toggle(max_led);
}
  output_toggle(min_led);
  }
  if (base_sec>99)//timebase 1s
  {
  time=0;
  base_sec=0;
}
}



void keys(void)
{
  if (!input(pin_a3))
  {
output_high(max_led);
  }
 
  if (!input(pin_a5))
  {
output_high(min_led);
  }
}
                     
 
 
void main() // Função  principal
{

   setup_adc(ADC_CLOCK_DIV_2);
   setup_adc_ports(sAN3 | VSS_VDD);  // Configura analógicos
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  // Configura  Timer 0
 
 setup_timer_1(T1_DISABLED);
   
 setup_comparator(NC_NC_NC_NC);

 setup_timer_2(T2_DIV_BY_4,255,1);
 
 setup_ccp1(ccp_pwm);

   
   enable_interrupts(int_timer2);
//   enable_interrupts(int_ad); 
   enable_interrupts(global);

 
 
 
while (true)
 {
   set_adc_channel(3);
   teste=(read_adc(ADC_START_AND_READ));

//This can be used
/*   
   bit_clear(teste,10);
   bit_clear(teste,11);
   bit_clear(teste,12);
   bit_clear(teste,13);
   bit_clear(teste,14);
   bit_clear(teste,15);
*/
//or   
//   teste=teste & 0b0000001111111111;
//or
//   teste=teste & 0x3FF;
//its a simple bitmask that clear the unused 6 bits of the var teste
//and done!
   teste=teste & 0x3FF;
   
   set_pwm1_duty(teste);
   delay_ms(1);
 }
}

Thank you very much!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 18, 2015 12:31 pm     Reply with quote

Your clock divisor is too small, resulting in a ADC clock that is 8 times
faster than allowed.
Quote:

#use delay(internal=8000000,RESTART_WDT)

setup_adc(ADC_CLOCK_DIV_2);

The 12F683 data sheet tells you what clock divisor to use in this table:
Quote:
TABLE 9-1: ADC CLOCK PERIOD (TAD) VS. DEVICE OPERATING FREQUENCIES (VDD > 3.0V

http://ww1.microchip.com/downloads/en/DeviceDoc/41211D_.pdf

Also,
pcm programmer wrote:
Post the compiler version you are using for this test.
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Tue Jun 23, 2015 7:54 am     Reply with quote

PCM programmer wrote:
Your clock divisor is too small, resulting in a ADC clock that is 8 times
faster than allowed.
Quote:

#use delay(internal=8000000,RESTART_WDT)

setup_adc(ADC_CLOCK_DIV_2);

The 12F683 data sheet tells you what clock divisor to use in this table:
Quote:
TABLE 9-1: ADC CLOCK PERIOD (TAD) VS. DEVICE OPERATING FREQUENCIES (VDD > 3.0V

http://ww1.microchip.com/downloads/en/DeviceDoc/41211D_.pdf

Also,
pcm programmer wrote:
Post the compiler version you are using for this test.



Code:
#include <12F683.h>
#device ADC=10;
#fuses INTRC_IO,NOWDT,PROTECT, NOMCLR   
#use delay(internal=8000000,RESTART_WDT)
#include <internal_eeprom.c>

#DEFINE min_led pin_a1
#DEFINE max_led pin_a0

//timer
int time=0;
int base_sec=0;
int base_led=0;
//fim timer

//DAC
int8  offset=0; //adjust of minimal voltage of sensor
int16 lco=200; //Low current output
int16 hco=1000; //High current output
float span=0;
int16 DAC=0;
unsigned int16 teste=0;
int32 x=0;

int16 s=0;


//adc
int32 adc=0;
// fim adc

void keys(void);

#int_timer2
void timing_dsy()
{
  time++;
  keys();
  if (time>12) //timebase 12ms
  {
  time=0;
  base_sec++;
  base_led++;
  }
  if (base_led>4) //timebase 64ms 15.6 Hz
  {
  base_led=0;

if (teste>1022)
{
output_toggle(max_led);
}
  output_toggle(min_led);
  }
  if (base_sec>99)//timebase 1s
  {
  time=0;
  base_sec=0;
}
}



void keys(void)
{
  if (!input(pin_a3))
  {
output_high(max_led);
  }
 
  if (!input(pin_a5))
  {
output_high(min_led);
  }
}
                     
 
 
void main() // Função  principal
{

   setup_adc(ADC_CLOCK_DIV_32);
   setup_adc_ports(sAN3 | VSS_VDD);  // Configura analógicos
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  // Configura  Timer 0
 
 setup_timer_1(T1_DISABLED);
   
 setup_comparator(NC_NC_NC_NC);

 setup_timer_2(T2_DIV_BY_4,255,1);
 
 setup_ccp1(ccp_pwm);

   
   enable_interrupts(int_timer2);
//   enable_interrupts(int_ad); 
   enable_interrupts(global);

 
 
 
while (true)
 {
   set_adc_channel(3);
   teste=(read_adc(ADC_START_AND_READ));

//This can be used
/*   
   bit_clear(teste,10);
   bit_clear(teste,11);
   bit_clear(teste,12);
   bit_clear(teste,13);
   bit_clear(teste,14);
   bit_clear(teste,15);
*/
//or   
//   teste=teste & 0b0000001111111111;
//or
//   teste=teste & 0x3FF;
//its a simple bitmask that clear the unused 6 bits of the var teste
//and done!
   teste=teste & 0x3FF;
   
   set_pwm1_duty(teste);
   delay_ms(1);
 }
}
CCS PCM C Compiler, Version 5.015
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 24, 2015 1:59 pm     Reply with quote

I installed compiler vs. 5.015 and shortened your program down to the
essential parts to read and display the ADC results. It worked. The
upper 6 bits are set to 0 by the compiler without any masking needed.
I slowly turned the trimpot and got ADC output from 0000 to 03FF.
That's correct operation:
Code:

0000
0000
0000
0058
00d3
0104
012a
015c
0193
01ff
0260
02a8
0300
0362
03a0
03ff
03ff
03ff


I don't know how you could possibly get an ADC result with all the upper
bits set to 1. It's not caused by the compiler. Your program below has
some minor bugs, but for this test, they are not important. They don't
affect the result.
Code:
#include <12F683.h>
#device ADC=10  //; *** COMMENTED OUT the ';'
#fuses INTRC_IO, NOWDT
#use delay(internal=8000000,RESTART_WDT)
#use rs232(baud=9600, xmit=PIN_A2)  // *** ADDED ***

unsigned int16 teste=0;
                     
void main()
{
setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(sAN3 | VSS_VDD);   

while(TRUE)
 {
   set_adc_channel(3);
   teste=(read_adc(ADC_START_AND_READ));

   printf("%lx \n\r", teste);  // *** ADDED ***

   teste=teste & 0x3FF;
   
   //set_pwm1_duty(teste);  // *** COMMENTED OUT
   delay_ms(1000);   // *** SET to 1000
 }

}
Linxroot



Joined: 16 May 2011
Posts: 17

View user's profile Send private message

PostPosted: Sun Jun 28, 2015 4:19 pm     Reply with quote

PCM programmer wrote:
I installed compiler vs. 5.015 and shortened your program down to the
essential parts to read and display the ADC results. It worked. The
upper 6 bits are set to 0 by the compiler without any masking needed.
I slowly turned the trimpot and got ADC output from 0000 to 03FF.
That's correct operation:
Code:

0000
0000
0000
0058
00d3
0104
012a
015c
0193
01ff
0260
02a8
0300
0362
03a0
03ff
03ff
03ff


I don't know how you could possibly get an ADC result with all the upper
bits set to 1. It's not caused by the compiler. Your program below has
some minor bugs, but for this test, they are not important. They don't
affect the result.


In my report states that the problem to occur there must be three conditions:
The ADC must be activated;
The PWM too;
The oscillator config must be one that not use the CLK OUT pin;
The clock out pin is the same pin of the ADC input. Curiously If the clock out is actived the adc convertions works fine, but the microcontroller warms because the pot cause short circuit to the signal of clock out.
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