AD conversion in a PIC18F2550

Thank you very much for all your responses and help so far to my question. I am humbled by your generosity.

Here is the state of things in my project 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 if and what I am doing wrong??


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:
/***********************************************************************************

*  This is a ADC conversion program for the  MPLAB C18-Lite compiler

*  Continuosly sample analog input

*  copy value to 4 leds

*   this program is made for the PIC18F2550 

********************************************************************************

* PIN assignments:

*           AN0 :  voltage to be measured 

*           RB0-3:  output LEDs (RB3 is MSB)

*

**************************************************************************************/

 

// Includes

#include <p18f2550.h>

#include "adc.h"

unsigned int ADCResult=0;

/********************CONFIGURATION**************/

#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB 

#pragma config WDT = OFF //Disable watchdog timer

 

// Pin assignments

#define LEDS PORTB  // output LEDs in port B

/**********MAIN PROGRAM*************/

void main()

{

 unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00,i=0;

  // initialization

  TRISB=0b110000;    // configure RB0-RB3 as outputs

 

 

  // configure ADC

  config1 = ADC_FOSC_RC | ADC_RIGHT_JUST | ADC_2_TAD ;

  config2 = ADC_CH0 | ADC_INT_OFF | ADC_REF_VDD_VSS ;

  portconfig = ADC_1ANA ;  // Only A0 is analog. the rest are digital (so as to allow us digital output on B)

  OpenADC(config1,config2,portconfig);

 

  // main loop

  while(1)

    {

      ConvertADC();   // start conversion

 

      while(BusyADC()); // wait for result

 

      ADCResult=(unsigned int) ReadADC();

 

 

        LEDS=ADCResult>>6; // copy highes nybble (6 since this is a 10-bit ADC)

//  LEDS= ADRESL>>4; // copy high nybble of result to LEDs (this is for 8-bit ADC)

      }

 CloseADC();         //turn off ADC

}



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:
/***********************************************************************************

*  This is the LED-on/off based on ADC conversion from a potentiometer program

*  (compiled with MPLAB C18-Lite compiler)

*  Continuosly sampled analog input

*  based on the value from that input (after ADC) the LED is going to be 

*  turn ON/OFF, 

*   this program is made for the PIC18F2550 

*

*   The range of value of the 10-bit ADC is 0~1024 which correspond to a voltage 0~Vmax 

*

*   The range of motion of the potentiometer is 320 degrees

*

*   We have to make a conversion between degrees and values of the ADC

*

*     ZERO DEGREE  ---->  0

*     320 DEGREE   ---->  1024

*

*

*

********************************************************************************

* PIN assignments:

*           AN0 :  voltage to be measured 

*           RB3:  output 

**************************************************************************************/

/*********************Includes********************/

#include <p18f2550.h>

#include "adc.h"

unsigned int ADCResult=0;

double  angle=0;

/********************CONFIGURATION**************/

#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB 

#pragma config WDT = OFF //Disable watchdog timer

/**********PIN Assignment*************************/

#define LEDPin3   LATBbits.LATB3  // the only one we will be using

 

/***********Other Definitions************************/

#define  LOWANGLE   45

#define  HIGHANGLE  135

#define  TOTALANGLE 320

#define  TOTALADC   1024

#define  CONVADCTOANGLE  (TOTALANGLE/TOTALADC)

#define  CONVANGLETOADC  (TOTALADC/TOTALANGLE)

 

/**********MAIN PROGRAM*************/

void main()

{

 unsigned char channel=0x00,config1=0x00,config2=0x00,config3=0x00,portconfig=0x00,i=0;

  // initialization

  TRISB=0b110000;    // configure RB0-RB3 as outputs

 

   LEDPin3=0;  // turn off the pin

 

  // configure ADC

  config1 = ADC_FOSC_RC | ADC_RIGHT_JUST | ADC_2_TAD ;

  config2 = ADC_CH0 | ADC_INT_OFF | ADC_REF_VDD_VSS ;

  portconfig = ADC_1ANA ;  // Only A0 is analog. the rest are digital (so as to allow us digital output on B)

   OpenADC(config1,config2,portconfig);

 

  // main loop

  while(1)

    {

     ConvertADC();   // start conversion

     while(BusyADC()); // wait for result

     ADCResult=(unsigned int) ReadADC();

     angle=ADCResult*CONVADCTOANGLE;   // we get the angle here.

 

     if(angle>HIGHANGLE) // turn off the LED

        LEDPin3=0;   // turn off the LED

 

     if(angle<LOWANGLE)  // turn on the LED

        LEDPin3=1;

 

 

    }

 CloseADC();         //turn off ADC

}



Can someone please tell me what am I doing wrong?



Thanks a lot again



Kansai
 
Basically the LEDs are not displaying correctly.
The compilation is quite good, no errors at all.



I tried to reflect in b 4 LEDS the binary value of the AD conversion and that doesnt work.
And in the other example I wanted to turn on and off the LED based on the value of the AD and that doesnt work either. basically the leds just stay ON

I have used another program to check if the AD is being performed (toogle a LED after every AD conversion) and if I put a delay it works. so I guess the AD conversion is taking place. I just dont know why the results are not being relfected in the previous programs...


I guess I need a night sleep
 
Last edited:
Ok.

Some suggestions, for the first program:

Code:
config1 = ADC_FOSC_RC [B]&[/B] ADC_RIGHT_JUST[B] &[/B] ADC_[B]12[/B]_TAD ;
config2 = ADC_CH0[B] &[/B] ADC_INT_OFF[B] &[/B] ADC_REF_VDD_VSS ;

You want ADC_FOSC_RC AND ADC_RIGHT_JUST AND... don't you agree with me?
Raise the TAD a bit, just for experienting, in that case I changed to 12 machine cycles.

You chosed RIGHT JUSTIFY, what means that a 10 bit will be stored as 0x03FF, the high byte will store the 2 leftmost bits and the low byte will store the low byte.

So, if you want to overlay the lower byte by bringing the high byte down, you have to shift 8 times, not six. observe:

If I shift left 0x03FF 6 times and mask with 0x000F, I'm gonna get: 0x000F -> WRONG!

If I shift left 0x03FF 8 times and mask with 0x000F, I'm gonna get: 0x0003 -> RIGHT!

So:
Code:
// main loop

  while(1)

    {

      ConvertADC();   // start conversion

 

      while(BusyADC()); // wait for result

 

      ADCResult=(unsigned int) ReadADC();

 

 

       [B] LEDS=(ADCResult>>8)&(0x0003)[/B]; // copy highes nybble ([B]8[/B] since this is a 10-bit ADC) [B]and mask with 0x0003, to throw out the garbage[/B]

[B]      DelayMs(1000); //Wait for 1 s so that you can see the LEDs[/B]

//  LEDS= ADRESL>>4; // copy high nybble of result to LEDs (this is for 8-bit ADC)

      }

Why did I mask?
Lets imagine we have the 0x020F value at the ADCResult:
Think about it, when I RR the byte 8 times, this is going to happen, assuming that the [Carry] is 0:
Code:
Original:  [0]-0010.0000.1111
1st:       [1]-0001.0000.0111 
2nd        [1]-1000.1000.0011                     
3rd        [1]-1100.0100.0001                     
4th        [1]-1110.0010.0000                     
5th        [0]-1111.0001.0000
6th        [0]-0111.1000.1000
7th        [0]-0011.1100.0100
[B]8th        [0]-0001.1110.0010[/B] -> 0x1E2, not 0x002!

So we mask with 0x0003:
0001.1110.0010
                     &
0000.0000.0011
------------------
0000.0000.0010 -> [B]0x002[/B]
 
Thanks for the help. It is very much appreciated. I have a different issue now, so I will post another thread.
Again thanks

Kansai
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…