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

Basics Working - PIC18 ADC/PWM
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

Basics Working - PIC18 ADC/PWM
PostPosted: Sat Apr 21, 2012 4:31 pm     Reply with quote

To start off I am about as green as a beginner can get. I don't know C very well, I don't know assembly, and I have never used uC's. I however am pretty proficient at building circuits and learning from others coding examples.

I am using a PIC18F26K80 with MPLAB v8.84 and CCS PIC C DEMO 4.13 & PICkit 3

The goal: To blink an LED

I started by using the wizard and the supplied example but I cannot get the LED to power on let alone blink.

Circuit Setup:
uC(Pin) PICkit 3
VDD(20) +5V/Pin2
VSS(19) GND/Pin3
VSS(08) GND
MCLR(1) Pin1 R10k->VDD
PGD(28) Pin4
PGC(27) Pin5
RC4(15) LED+ -> R220 ->GND

Code:

#include <18F26K80.h>
#device adc=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP

#use delay(int=4000000)

#define LED PIN_C4
#define DELAY 1000
#include <LED FLASH2.h>


void main()
{
   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);

   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
   setup_oscillator(OSC_4MHZ|OSC_NORMAL|OSC_31250|OSC_PLL_OFF);

   //Example blinking LED program
   while(true)
   {
      output_low(LED);
      delay_ms(DELAY);
      output_high(LED);
      delay_ms(DELAY);
   }

}




The code compiles in PIC C and also in the MPLAB project with no errors.
The code is loaded to the pic with the PICkit and verified however the LED doesn't blink light flash or anything. Help Please


Last edited by ounvme on Mon Jun 04, 2012 5:02 pm; edited 2 times in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Apr 21, 2012 5:48 pm     Reply with quote

Try a more simple program. I'm not at a location where I can test this in
hardware, but you need to start with a simple program:
Code:

#include <18F26K80.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT
#use delay(clock=4M)

//======================================
void main(void)
{

while(1)
  {
   output_high(PIN_B0);
   delay_ms(500);
   output_low(PIN_B0);
   delay_ms(500);
  }

ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Sun Apr 22, 2012 10:36 am     Reply with quote

The simple program worked and I was able to go step by step in debug mode. I figured the problem to be the fuses that I was using. So now I have both programs running in debug mode. When I unplug the programmer and apply power I get nothing. I assume I am missing a fuse or something in the circuit. Does it have to do with the MCLR pin?
temtronic



Joined: 01 Jul 2010
Posts: 9163
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Apr 22, 2012 10:43 am     Reply with quote

You'll have to change from 'debug' to 'release' and then recompile/download code into PIC.
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Sun Apr 22, 2012 5:31 pm     Reply with quote

Awesome I can work in debug and external power mode. I am going to have to read more about how the fuses work as those seem to be very important.

The next step is to learn the hardware A/D and see if I can change the blinking speed with a pot.

The device I am using has 8 12bit a/d. For my application 8 or 10 bit would work fine. Can I use the internal a/d at a lower resolution?

I would like to use AN0 internally referenced to VDD. The data sheet states that for 12bit I need 14Tad what about 10 and 8 bit?
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Mon Apr 23, 2012 9:03 pm     Reply with quote

Can someone "dumb" down the setting of adcon2?
To begin I won't be using an interrupt until I learn more about those also.

What I have so far from the data sheet
Code:

ADCON0 = 0b00000000
7=0               UNUSED
6-2=00000     AN0
1=0               NOT IN PROGRESS
0=0               OFF
 
ADCON1 = 0b00000001
7=0
6=0               ECCP1?? WHAT IS THIS?
5-4=00          VREF+ =VDD
3=0               VREF- =VSS
2-0=001        AN0
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Apr 23, 2012 9:28 pm     Reply with quote

Here is a description of how to make a program that controls the
blink rate of an LED by reading the ADC:
http://www.ccsinfo.com/forum/viewtopic.php?t=44762
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Tue Apr 24, 2012 7:47 am     Reply with quote

Thanks PCM. I will look more into that after I understand how the A/D timing functions and how to properly configure the ADCON2 register.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 24, 2012 11:15 am     Reply with quote

This post has an example of using the ADC on the "K80" series PICs:
http://www.ccsinfo.com/forum/viewtopic.php?t=46255&start=5
The ADC clock divisor shown in that code is for the PIC running at 4 MHz.
If you use a different PIC oscillator frequency, then look in the ADC
section of the 18F26K80 data sheet and find the table that gives the
correct divisor to use. Then look in the 18F26K80.h file, in the ADC
section, and see what constant to use with the setup_adc() function to
select that divisor value.
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Wed Apr 25, 2012 11:03 pm     Reply with quote

The 18F26K80 uses 12 bit and the registers are setup much differently. It is a good reference but still does not make it clear for how I would calculate TAD and Tacq for my application. With the ADCON0 the data sheet does not specify how to configure more then one input as analog. But uses ANCON0 to specify port settings. How does this work if ADCON0 only configures 1 pin?

What I am trying to achieve. 3 A/D pins with VSS/VDD reference using a 1Kohm pot(DC circuit max impedance 2.5Kohm according to the data sheet) with 12bit resolution.

Its seems as the data sheet over complicates how to configure this or I am just not capable of understanding what it is trying to say. It is frustrating non the less.

From the Data Sheet: Where is the 2048 coming from? Could that be 10bit*2?

TACQ = Amplifier Settling Time + Holding Capacitor Charging Time + Temperature Coefficient
= TAMP + TC + TCOFF
VHOLD = (VREF – (VREF/2048)) • (1 – e(-TC/CHOLD(RIC + RSS + RS)))
or
TC = -(CHOLD)(RIC + RSS + RS) ln(1/2048)
TACQ = TAMP + TC + TCOFF
TAMP = 0.2 s
TCOFF = (Temp – 25C)(0.02 s/C)
(85C – 25C)(0.02 s/C)
1.2 s
Temperature coefficient is only required for temperatures > 25C. Below 25C, TCOFF = 0 ms.
TC = -(CHOLD)(RIC + RSS + RS) ln(1/2048) s
-(25 pF) (1 k + 2 k + 2.5 k) ln(0.0004883) s
1.05 s
TACQ = 0.2 s + 1.05 s + 1.2 s
2.45 s
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Apr 25, 2012 11:31 pm     Reply with quote

Quote:

The 18F26K80 uses 12 bit and the registers are setup much differently.

The 18F46K80 in the example I linked to, is in the same PIC family
as the 18F26K80. They both have 12-bit A/D's. It's not setup differently.
In my linked example, I tell the compiler to return a 12-bit right-justified
result by this statement:
Code:

#device adc=12


Quote:

does not specify how to configure more then one input as analog

The ADC section of the 18F26K80.h file tells you exactly how to select
multiple A/D channels. See the following file:
c:\program files\picc\devices\18f26k80.h

Quote:

What I am trying to achieve. 3 A/D pins with VSS/VDD reference using a
1Kohm pot(DC circuit max impedance 2.5Kohm according to the data
sheet) with 12bit resolution.

Try the example code that I posted. Get it running for one channel, then
add the other channels.
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Sun May 27, 2012 10:39 pm     Reply with quote

Well I have had some free time to play with some examples and do some testing. I am having an issue with A/D above 8 bit. Using 8 bit I can adjust a potentiometer and change the blink rate of the led. Anything else and the behavior is eratic. Why is this?
Code:

#include <18F26K80.h>
#device adc=10

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP

#use delay(int=4000000)

#define LED PIN_C4

void main()
{
int temp;   
setup_adc_ports(sAN0);
   setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_2);
   setup_timer_2(T2_DIV_BY_16,155,1);      //2.4 ms overflow, 2.4 ms interrupt

   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);

   setup_ccp2(CCP_PWM);
   set_pwm2_duty((int16)20);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard

   while(true)
   {
      set_adc_channel(0);// AN0 reading
                delay_us(20);// 20us delay
                temp=read_adc(); // AN0 reading: 0<=temp<=255

                output_high(LED);
      delay_ms(temp);
      output_low(LED);
      delay_ms(temp);
   }

}


Ttelmah



Joined: 11 Mar 2010
Posts: 19337

View user's profile Send private message

PostPosted: Mon May 28, 2012 1:19 am     Reply with quote

A very old one. Smile

What can an 'int' hold in CCS?. Not a 10bit, or 12bit value.....

This is why I like to use int8, and int16 types. This way the code 'shows' the size of the selected type.

Best Wishes
ounvme



Joined: 21 Apr 2012
Posts: 13

View user's profile Send private message

PostPosted: Mon May 28, 2012 8:07 pm     Reply with quote

That seems to have fixed the error. I tried int10 and 12 but not int16. For what I am using the 8 bit adc is more than enough. I wanted to test with 10 12 and 16. Here is the beginning of my work in progress. So far adjusting a 1k pot will change the blink rate and PWM. The 0-255 is scaled by a multiplier to adjust the duty cycle from 0-100. This may not be the correct way to handle this but so far it works. The next phase will be to add in the other 2 hardware A/D and PWM. After I get the whole thing working I will start to look into using making the code more efficient.

Please discuss my logic.

Read ADC
Set initial PWM
Check for change in ADC1,2,3
Loop

Adjust PWM if ADC

I am a big fan of using sub routines. It was the way I learned basic programming and it delivers code that is very easy to follow. If anyone can give me a 30 second crash course on calling subs and passing variables that would be great.

Here is the latest working code
Code:

#include <18F26K80.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOBROWNOUT               //No brownout reset
#FUSES WDT_NOSLEEP              //Watch Dog Timer, disabled during SLEEP

#use delay(int=4000000)

#define LED PIN_C4
#define DELAY 1000


void main()
{
int8 pwm2;
int16 temp;   
int8 pwm1;
setup_adc_ports(sAN0);
   setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_2);
   setup_timer_2(T2_DIV_BY_16,155,1);      //2.4 ms overflow, 2.4 ms interrupt

   setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);

   setup_ccp2(CCP_PWM);
   set_pwm2_duty((int16)20);
   setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard

   //Example blinking LED program
   while(true)
   {
      set_adc_channel(0);// AN0 reading
      delay_us(20);// 20us delay
      temp=read_adc(); // AN0 reading: 0<=temp<=255
pwm1=temp/2.44;   
set_pwm2_duty(pwm1);
output_high(LED);
      delay_ms(temp);
      output_low(LED);
      delay_ms(temp);
   }

}
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue May 29, 2012 12:11 am     Reply with quote

Quote:
If anyone can give me a 30 second crash course on calling subs and passing variables that would be great.
First reaction is that you should get yourself a book on C as you are now asking our time for something that is easy to look up yourself.

Here a quick hint though:
In Basic there is a difference between calling a subroutine and a function. In C there is no such difference. When writing a function you can specify it to return a value or not.

Also: in Basic the goto command is often used. In C it is considered bad practice to use 'goto' it results into spaghetti code. It can always be replaced by other constructs like if-then-else, for-loops, switch cases and do-while.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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