Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

AD conversion in a PIC18F2550

Status
Not open for further replies.
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
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top