Help 3. Using a A/D in a PIC18F2550

Discussion in 'The Projects Forum' started by KansaiRobot, Jan 21, 2010.

  1. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    First of all I would like to say thank you to everybody who helped me in my previous questions, "how to wire a Potentiometer" and "how to wire a solenoid valve". Your help has proved really valuable to me.

    This time my question is about using a PIC 18F2550 that I have with me. Particularly the A/D function. The value I am going to be entering is the voltage from the potentiometer. (0-5V)

    so the questions I have so far are:

    1) Is there a place you can recommend to find examples or tutorials on this theme?
    2) Does the PIC 18F2550 needs any particular wiring (apart from putting I suppose the wiper of the pot to a port (any resistor needed? maybe not)

    I know the questions seems too general so far but I am just starting to read the docs about this. I suppose I will have more concrete questions later.

    Thank you in advance for all the help you can give me.

    Kansai
     
  2. SgtWookie

    Expert

    Jul 17, 2007
    22,182
    1,728
    Have you tried the Microchip website? They have quite a bit of documentation and "How To" examples along with the Application Notes. The datasheet for your particular PIC will have quite a bit of information in the ADC documentation already.
    The ADC needs a pretty low-impedance source to sample. A small capacitor, say 10nF to 100nF, at one of the ADC-accessible inputs will help to assure that it gets a low impedance source.
     
  3. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Yes, I am checking that right now. The information is enourmous, say the datasheet is 438 pages!
    I found a place with examples too. So far the ones I ve looked are in assembler and although I would go there if it is needed, my first language is C, so I was hoping for examples in C.
    Anyway if I can find some more focused info (examples in C for A/D) it would save me time.


    Yes, thanks. I ve already applied a 10 nF cap so I am hoping that would be alright.
    I am wondering more in the sense of setting the RESET pin or something of that sort. I still have to read about this...

    thanks for the support :)

    Kansai (back to the books)
     
  4. eng1ne

    Member

    Dec 4, 2009
    97
    3
    www.gooligum.com.au

    Absolutely excellent tutorials, highly recommend it. I learnt a great deal simply reading them and refer to them very often.
     
  5. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,017
  6. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Thank you for the help.

    QUick question. Which C compilers are there for programming the PICs?

    I have heard of some already:

    • MPLAB C for PIC18 V3.34 in LITE mode
    • HI-TECH PICC-Lite
    • CCS PCB
    Any comment or recommendation on those?

    Due to the availability of libraries it seems that the codes in one and another can be quite different!
     
  7. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
  8. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Thank you very much for your useful suggestions :)

    I have a question regarding initial settings of the microcontroller. I am using a board in which the PIC18F2550 is already connected to a crystal oscillator (pins 9 and 10).

    Now when in the program we put "clock to be derived from the internal oscillator (as in #pragma config FOSC=INTOSCIO_EC
    or CONFIG FOSC=INTOSCIO_EC)
    what are we refering to???
    Does the microcontroller have an oscillator "inside"???

    Does the oscilator I see in the circuit of my board is an "external oscillator"??

    if yes, which should I use??

    the crystal oscillator I have in the board is 20MHz (X110) connected to ground with two caps of 22pF.

    Thank you for any help about this. The project is going fine!!:)
     
  9. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,017
    Yes, many MCUs have internal oscillators. Tou don't really need to use the external crystal osc unless you have something that is timing critical. For example a real time clock. There are also methods for measuring voltage by measuring the amount of time it takes to charge a capacitor that would require precise timing.

    I think the internals are pretty limited on speed too, but probably plenty fast enough for most hobby purposes.
     
  10. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Thank you very much for all your responses.
    Here is the state of things so far.

    I have managed to write a ADC program for my pic, compile it and write it in the PIC18F2550.
    I am just not sure if the ADC is working or not.

    Can someone please take a look and tell me what I am doing wrong??

    1. First, a program that reads the analog value from AN0 and display it as 4 leds in binary (somehow the leds are always on):(
    Code ( (Unknown Language)):
    1.  
    2. /***********************************************************************************
    3. *  This is a ADC conversion program for the  MPLAB C18-Lite compiler
    4. *  Continuosly sample analog input
    5. *  copy value to 4 leds
    6. *   this program is made for the PIC18F2550 ********************************************************************************
    7. * PIN assignments:
    8. *           AN0 :  voltage to be measured
    9. *           RB0-3:  output LEDs (RB3 is MSB)
    10. *
    11. **************************************************************************************/
    12.  
    13. // Includes
    14. #include <p18f2550.h>
    15. #include "adc.h"
    16. unsigned int ADCResult=0;
    17. /********************CONFIGURATION**************/
    18. #pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB
    19. #pragma config WDT = OFF //Disable watchdog timer
    20.  
    21. // Pin assignments
    22. #define LEDS PORTB  // output LEDs in port B
    23. /**********MAIN PROGRAM*************/
    24. void main()
    25. {
    26.  unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00,i=0;
    27.   // initialization
    28.   TRISB=0b110000;    // configure RB0-RB3 as outputs
    29.  
    30.  
    31.   // configure ADC
    32.   config1 = ADC_FOSC_RC | ADC_RIGHT_JUST | ADC_2_TAD ;
    33.   config2 = ADC_CH0 | ADC_INT_OFF | ADC_REF_VDD_VSS ;
    34.   portconfig = ADC_1ANA ;  // Only A0 is analog. the rest are digital (so as to allow us digital output on B)
    35.   OpenADC(config1,config2,portconfig);
    36.  
    37.   // main loop
    38.   while(1)
    39.     {
    40.       ConvertADC();   // start conversion
    41.  
    42.       while(BusyADC()); // wait for result
    43.  
    44.       ADCResult=(unsigned int) ReadADC();
    45.  
    46.  
    47.         LEDS=ADCResult>>6; // copy highes nybble (6 since this is a 10-bit ADC)
    48. //  LEDS= ADRESL>>4; // copy high nybble of result to LEDs (this is for 8-bit ADC)
    49.       }
    50.  CloseADC();         //turn off ADC
    51. }
    52.  
    53.  
    2. A program that converts the value from ADC to angles (0 to 320 degrees and based on that turns on or off a led (somehow, the led is always on:()

    Code ( (Unknown Language)):
    1.  
    2. /***********************************************************************************
    3. *  This is the LED-on/off based on ADC conversion from a potentiometer program
    4. *  (compiled with MPLAB C18-Lite compiler)
    5. *  Continuosly sampled analog input
    6. *  based on the value from that input (after ADC) the LED is going to be
    7. *  turn ON/OFF,
    8. *   this program is made for the PIC18F2550
    9. *
    10. *   The range of value of the 10-bit ADC is 0~1024 which correspond to a voltage 0~Vmax
    11. *
    12. *   The range of motion of the potentiometer is 320 degrees
    13. *
    14. *   We have to make a conversion between degrees and values of the ADC
    15. *
    16. *     ZERO DEGREE  ---->  0
    17. *     320 DEGREE   ---->  1024
    18. *
    19. *
    20. *
    21. ********************************************************************************
    22. * PIN assignments:
    23. *           AN0 :  voltage to be measured
    24. *           RB3:  output
    25. **************************************************************************************/
    26. /*********************Includes********************/
    27. #include <p18f2550.h>
    28. #include "adc.h"
    29. unsigned int ADCResult=0;
    30. double  angle=0;
    31. /********************CONFIGURATION**************/
    32. #pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB
    33. #pragma config WDT = OFF //Disable watchdog timer
    34. /**********PIN Assignment*************************/
    35. #define LEDPin3   LATBbits.LATB3  // the only one we will be using
    36.  
    37. /***********Other Definitions************************/
    38. #define  LOWANGLE   45
    39. #define  HIGHANGLE  135
    40. #define  TOTALANGLE 320
    41. #define  TOTALADC   1024
    42. #define  CONVADCTOANGLE  (TOTALANGLE/TOTALADC)
    43. #define  CONVANGLETOADC  (TOTALADC/TOTALANGLE)
    44.  
    45. /**********MAIN PROGRAM*************/
    46. void main()
    47. {
    48.  unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00,i=0;
    49.   // initialization
    50.   TRISB=0b110000;    // configure RB0-RB3 as outputs
    51.  
    52.    LEDPin3=0;  // turn off the pin
    53.  
    54.   // configure ADC
    55.   config1 = ADC_FOSC_RC | ADC_RIGHT_JUST | ADC_2_TAD ;
    56.   config2 = ADC_CH0 | ADC_INT_OFF | ADC_REF_VDD_VSS ;
    57.   portconfig = ADC_1ANA ;  // Only A0 is analog. the rest are digital (so as to allow us digital output on B)
    58.    OpenADC(config1,config2,portconfig);
    59.  
    60.   // main loop
    61.   while(1)
    62.     {
    63.      ConvertADC();   // start conversion
    64.      while(BusyADC()); // wait for result
    65.      ADCResult=(unsigned int) ReadADC();
    66.      angle=ADCResult*CONVADCTOANGLE;   // we get the angle here.
    67.  
    68.      if(angle>HIGHANGLE) // turn off the LED
    69.         LEDPin3=0;   // turn off the LED
    70.  
    71.      if(angle<LOWANGLE)  // turn on the LED
    72.         LEDPin3=1;
    73.  
    74.  
    75.     }
    76.  CloseADC();         //turn off ADC
    77. }
    78.  
    79.  
    80.  
    81.  
    Can someone please tell me what am I doing wrong?

    Thanks a lot again :)

    Kansai
     
  11. t06afre

    AAC Fanatic!

    May 11, 2009
    5,939
    1,222
  12. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Yes thanks I have taken a look at it and studying it
    I have modified my code to see if the AD is actually working or not. And yes it is working. I set a LED toogle everytime a AD operation is finished. At first it didnt work, but then I introduced a delay and it works.

    So I am guessing my problem is in how I am configuring the Tad and the timings. But I am lost at this. Any advice will be appreciated. In the meantime I post the code and will keep thinking about this

    Code ( (Unknown Language)):
    1.  
    2. /*********************Includes********************/
    3. #include <p18f2550.h>
    4. #include <delays.h>
    5. #include "adc.h"
    6. unsigned int ADCResult=0;
    7. double  angle=0;
    8. /********************CONFIGURATION**************/
    9. #pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB
    10. #pragma config WDT = OFF //Disable watchdog timer
    11. /**********PIN Assignment*************************/
    12. #define LEDPin3   LATBbits.LATB3  // the only one we will be using
    13. /***********Other Definitions************************/
    14. #define  LOWANGLE   45
    15. #define  HIGHANGLE  135
    16. #define  TOTALANGLE 320
    17. #define  TOTALADC   1024
    18. #define  CONVADCTOANGLE  (TOTALANGLE/TOTALADC)
    19. #define  CONVANGLETOADC  (TOTALADC/TOTALANGLE)
    20.  
    21. /**********MAIN PROGRAM*************/
    22. void main()
    23. {
    24.  unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00,i=0;
    25.     // initialization
    26.      TRISB=0b110000;    // configure RB0-RB3 as outputs
    27.      TRISAbits.TRISA0=1;  // configure TRISA0 as input
    28.      LEDPin3=0;  // turn off the pin
    29.  
    30.  // configure ADC
    31.  config1 = ADC_FOSC_2 | ADC_RIGHT_JUST | ADC_20_TAD ;
    32.  config2 = ADC_CH0 | ADC_INT_OFF | ADC_REF_VDD_VSS ;
    33.  portconfig = ADC_1ANA ;  // Only A0 is analog. the rest are digital (so as to allow us digital output on B)
    34.  OpenADC(config1,config2,portconfig);
    35.  
    36.  // main loop
    37.  while(1)
    38.     {
    39.      ConvertADC();   // start conversion
    40.      while(BusyADC()); // wait for result
    41.  
    42.          LEDPin3=~LEDPin3; // toggle LED when finished
    43. // HERE, THIS ONLY WORKS WHEN THE NEXT DELAY IS INTRODUCED!!!
    44.          Delay10KTCYx(25);//Delay 250K cycles (1 second at 1MHz since each instruction takes 4 cycles)
    45.  
    46. //     ADCResult=(unsigned int) ReadADC();
    47.    //     angle=ADCResult*CONVADCTOANGLE;   // we get the angle here.
    48.  
    49. /*
    50.      if(angle>HIGHANGLE) // turn off the valve
    51.         LEDPin3=0;   // turn off the LED
    52.  
    53.      if(angle<LOWANGLE)  // turn on the valve
    54.         LEDPin3=1;
    55. */            
    56.     }
    57.  CloseADC();         //turn off ADC
    58. }
    59.  
    60.  
    61.  
    Thanks for all the help.

    Kansai
     
  13. eng1ne

    Member

    Dec 4, 2009
    97
    3
    Make use of the MPLAB Simulator. It serves as a reasonable debugging tool, with a watch window for certain memory locations etc. Set up some stimuli on your ADC memory location, calculate what you expect to see and step through your code.

    First watch this video: http://www.youtube.com/watch?v=S1QCZW92fU4

    Then, watch this video: http://www.youtube.com/watch?v=pnkUOL0mmyA&feature=related

    Pretty sure the second one I referred to explains stimulus etc. Let me know if it doesn't, and the only way you will be able to tell me if it does or doesn't is by watching it :)
     
  14. KansaiRobot

    Thread Starter Active Member

    Jan 15, 2010
    318
    5
    Thanks
    I watch the videos. the Stimulus seems like a great idea. Now I am reading the HELP but still can not figure how to infuse a voltage stimulus into my analog pin.....

    my deadline is gettin near and I still dont know how to run this:(

    I am pretty sure the problem must be in the timing. I have no idea how to select the correct values for oscilators Tads and I dont understand the table 21-1 in the datasheet and what Tosc or Fosc is....:(

    -----

    when you say "ADC memory location".... is this what? my PORTA??? but how can I say 3.5V on pin 0 of Port A???
    I dont get it....
     
    Last edited: Jan 30, 2010
  15. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi,
    When it comes to library functions, I think you should take a look at mikroC. I found that the best C compiler while programming PICs, although I mainly use mikroBASIC.
    I suggest you take a look at the compiler.
    Tahmid.
     
  16. Tahmid

    Active Member

    Jul 2, 2008
    344
    25
    Hi KansaiRobot,
    The TAD settings are very important.
    1 TAD = 1 ADC conversion clock. It takes 12 TAD to complete a conversion.
    Minimum TAD time = 1.6us
    So, if you are using 4MHz clock,
    (a) FOSC/2 = 2MHz
    1/2MHz = 400ns.
    Invalid since this is faster than 1.6us
    (b) FOSC/8 = 500kHz
    1/500kHz = 2us
    Valid since slower than 1.6us
    Hope you understood.
    Tahmid.
     
  17. spinnaker

    AAC Fanatic!

    Oct 29, 2009
    4,887
    1,017
    Doesn't 1/2 = 500? Or am I missing something?
     
Loading...