• 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.

setting up ADC port

MrDEB

Well-Known Member
have a resistor ladder for 10 switches but getting the ADC port set up right.
The LCD only displays 5v regardless of which switch is pressed.
The ACON regestors?
Code:
Device = 18F43k22
Clock = 20

// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3

// uses LCD and AD libraries...
Include "LCD.bas"
Include "ADC.bas"
Include "convert.bas"
          
// read the AD port and scale for 0 - 5 volts...
Function ADInAsVolt() As Word
   result = (ADC.Read(1) + 1) * 500 / 1024   //set ADC input  as porta.1
End Function

// sampled AD value...
Dim ADVal As Word
Dim led As PORTA.0
// initialise and clear LCD...
ADCON1 = $07       // PORTE as digital (LCD)
TRISA.1 = 1        // configure AN0 as an input ///
ADCON1.7 = 1       // set analogue input on PORTA.0 ///
DelayMS (500)
LCD.Cls
 Input(PORTA.1)                  // ADC IN on portA.1
    
    ADCON1 = %10000000              //set up ADC regesters
    ADCON0.7 = 1
    ADCON0.6 = 1
 
    ADCON1 = $07               
    TRISA = %111111   
    TRISB = %11111111
    TRISC = %00000000           
    TRISD = %00000000   
    TRISE = %000   

// main program loop...
While true
led=1
DelayMS(1000)
led=0
DelayMS(1000)
   ADVal = ADInAsVolt
   LCD.MoveCursor (1,1)
   LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
   DelayMS(250)
Wend
 

Visitor

Active Member
I don't think the comments line up with which input you're trying to use, which makes deciphering your code virtually impossible.

You set ADCON1 in 3 different places. Best to figure out what you need and do it once.

Binary numbers are 8 bits. While TRISE may only use the last 3 bits, the first 5 are "don't care", so it's less confusing to specify 8 bits.

Here is code I used to read AN0 in a recent project. Unless you have updated Swordfish to the most recent version – which updated most of the include files to handle recent variants – you might be best off to not include ADC.bas and use this code.

Please note: after you go to all the trouble to set up the ADC, don't undo it all with SETALLDIGITAL.

Code:
  'ADC setup
    ADCON2=%10101111 
    ADCON1=%00000000
    TRISA=%00000001
    ANSELA=%00000001
    ADCON0=%00000001
    ADCON0=%00000011
 
    While ADCON1.bits(1) <> 0  'ADC not done yet
        DelayUS(10)
    Wend

    ADCout.byte1=  ADRESH
    ADCout.byte0=  ADRESL
 

Pommie

Well-Known Member
Most Helpful Member
ADCON1.7 = 1 // set analogue input on PORTA.0 ///

How is 7 equal to 0?

Mike.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
Isn't ADCON1.7 supposed to be the old ADCON1 = 7 ie.. all digital!!

It really doesn't matter as the special trigger isn't used... However ADCON1 = 7 does matter as it is setting Avss and Avdd to something other than you need.
Mike.. Don't read the comments as these are copied and pasted from example codes, these have no bearing here..

ADC input appears to be on RA1...
 

MrDEB

Well-Known Member
YES I am using the sample code. Going to rewire and use portA.0 as ADC input.
I did an update couple weeks ago but?
Will use "visitors" code
 

MrDEB

Well-Known Member
Yes in the code I posted I have , or supposed to have ADC input on portA.1
curious how to make it portA.1
??? I think I posted the code tags correctly?
 

Visitor

Active Member
??? I think I posted the code tags correctly?
I strongly suggest you proofread your posts after you click post. Then you will be able to see if what you did worked and see if the post makes sense. If not, edit your post and try again.
 

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
the code I posted looks ok.
Yep!! Looks good, but it's wrong... The ADC on that chip is about as different to the old pic18f4520 as you can get!

ADCON1 = 0
ADCON2 = 173 or binary ( 10101101) I always use FOSC/16 on 20Mhz... I hardly ever use the internal RC
ANSELA = 2
TRISA should be 255 by default, so input anyway..

Then ADC.Read(1) should set ADCON0 for you.... This is all you need....
 

MrDEB

Well-Known Member
just got back from church, rewired the ADC input to port A.0
BUT lets throw a fly into the works!
After looking at my schematic and planning on using an 8 x 8 led matrix into the mess got to thinking that maybe using all 8 bits of portA and all of portB or portC for the matrix. using the entire port for the Cathodes and Anodes should make it easier to program (readability of code) (only one port for each) so looking at using PortE.0 for the ADC input?
First to try out code using portA.0 as per suggestion then ??
 

MrDEB

Well-Known Member
HOUSTON we have touchdown
this code works well for all 10 "switches(have a clip for testing instead of actual switches.
.74, 1.16, 1.56, 1.97, 2.38, 2.79, 3.22, 3.53, 4.08, 4.54
pretty even differential between test points on the resistor ladder IMO.
Code:
Device = 18F43k22
Clock = 20

// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3

// uses LCD and AD libraries...
Include "LCD.bas"
Include "ADC.bas"
Include "convert.bas"
          
// read the AD port and scale for 0 - 5 volts...
Function ADInAsVolt() As Word
   result = (ADC.Read(0) + 1) * 500 / 1024   //set ADC input  as porta.0
End Function

// sampled AD value...
Dim ADVal As Word
Dim led As PORTA.0
dim led1 as portc.0
// initialise and clear LCD...
ADCON1 = $07       // PORTE as digital (LCD)
TRISA.1 = 1        // configure AN0 as an input ///
ADCON1.6 = 1       // set analogue input on PORTA.0 ///
DelayMS (500)
LCD.Cls
 Input(PORTA.0)                  // ADC IN on portA.1
    
   // ADCON1 = %10000000              //set up ADC regesters
    //ADCON0.7 = 1
    //ADCON0.6 = 1
 
    ADCON1 = $07               
    TRISA = %11111111   
    TRISB = %11111111
    TRISC = %00000000           
    TRISD = %00000000   
    TRISE = %000
    
    /////////////////////////////
     'ADC setup
    ADCON2=%10101111
    ADCON1=%00000000
    TRISA=%00000001
    ANSELA=%00000001
    ADCON0=%00000001
    ADCON0=%00000011
    ///////////////////////////////////
 
    While ADCON1.bits(1) <> 0  'ADC not done yet
        DelayUS(10)
    Wend

    //ADCout.byte1=  ADRESH
   // ADCout.byte0=  ADRESL   

// main program loop...
While true
led1=1
DelayMS(1000)
led1=0
DelayMS(1000)
   ADVal = ADInAsVolt
   LCD.MoveCursor (1,1)
   LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
   DelayMS(250)
Wend
 

Visitor

Active Member
Glad it works for you. But why are you converting the ADC reading to volts? Better to leave it as 10 bit data, save some extraneous math, and have higher resolution.

What's the idle state value? I've lost track of how you have the matrix arranged. It should either be pulled high (~1023) or low (~0) when no switch is pressed. Then a simple Case/Select will give you what button is pressed. Start with the idle case. Let's suppose the idle case is high.

Code:
Dim ADCOut as Word

Select ADCOut

    Case > 1000 'value over 1000
        'no button pressed

   Case > 900  'value between 901 – 1000
        'Button 10 pressed

   Case > 800 'value between 801 – 900
        'Button 9 pressed

   Case > 700 'value between 701 – 800
       'Button 8 pressed

'And so on.

End Select
Of course you have to adjust the ranges for the values you are reading.

Remember, the Case/Select is exited when one of the conditions is met – the following tests are ignored. Say the value is 750. The first three tests fail. The 4th test, for value > 700 is met, indicating button 8 was pressed.
 

MrDEB

Well-Known Member
that's where I was headed visitor. Just wanted to get the ADC example working first.\
I used similar several years ago for a beer cooler thermostat.
looking at data sheet, page 301 and 151 for clues to use porte instead of porta. No good results yet.
 

tumbleweed

Active Member
try this...
Code:
Device = 18F43K22
Clock = 20

// some LCD options...
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3

// uses LCD and AD libraries...
Include "LCD.bas"
Include "ADC.bas"
Include "convert.bas"

// ****** change this to select between  0 (AN0, PORTA.0) or 5 (AN5, PORTE.0) ******
const ADC_CHAN = 5

// read the AD port and scale for 0 - 5 volts...
Function ADInAsVolt() As Word
   result = (ADC.Read(ADC_CHAN) + 1) * 500 / 1024
End Function

// sampled AD value...
Dim ADVal As Word
Dim led As PORTA.0
dim led1 as portc.0

// setup IO pins
TRISA = %11111111 
TRISB = %11111111
TRISC = %00000000         
'TRISD = %00000000      // PORTD is set by LCD.BAS 
TRISE = %001

// initialise and clear LCD...
DelayMS (500)
LCD.Cls

// ADC IN
if (ADC_CHAN = 0) then
    Input(PORTA.0)                  // ADC IN on portA.0
    ANSELA=%00000001                // ANSA0
elseif (ADC_CHAN = 5) then
    Input(PORTE.0)                  // ADC IN on portE.0
    ANSELE=%00000001                // ANSE0
endif

/////////////////////////////
'ADC setup
ADCON2 = %10101111
ADCON1 = %00000000
ADCON0 = (ADC_CHAN << 2) or %00000001    // chan + ADON
ADCON0.bits(1) = 1                       // GO (start convert)
///////////////////////////////////

// main program loop...
While true
    led1=1
    DelayMS(1000)
    led1=0
    DelayMS(1000)

    ADVal = ADInAsVolt()
    LCD.MoveCursor (1,1)
    LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
Wend
You have to be careful... ADC.BAS hasn't been updated in eons, but I think Adc.Read() should still work for what you're doing.
 

MrDEB

Well-Known Member
attempting to chop the bits into 1023 pieces but just getting volts. My math is wrong?
want to go w/ case select as suggested in post 14
then attempt to go from portA over to portE as Tumble weed suggested.
 

Visitor

Active Member
attempting to chop the bits into 1023 pieces but just getting volts. My math is wrong?
The value read from the ADC is 10 bits = 0 to 1023. There is no need to chop anything. No math required. Use the value read out, but it must go into a variable dimensioned as a WORD to handle 10 bits.
 

Visitor

Active Member
You have to be careful... ADC.BAS hasn't been updated in eons, but I think Adc.Read() should still work for what you're doing.
Are you aware that there is a recent update (last few months)? I believe that ADC.BAS and most of the other include files have been updated to support new chip variants.
 

MrDEB

Well-Known Member
Does it need to be an integer?
will check the ADC.bas. I think I have the latest as I refreshed with version 2.2.3.0
will keep grinding away.
 

Latest threads

EE World Online Articles

Loading

 
Top