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

ADC not playing nice

MrDEB

Well-Known Member
trying to read the portA.o ADC value but the dang LED doesn't even blink.
I tested the LCD and it works. Eventually want to read the ADC on portA.0 and portA.1
using Swordfish
Code:
Device=18f43k22     
Clock = 8            '8MHz
'Config FOSC = INTIO7   'internal oscillator   
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
// import LCD library...
Include "SetDigitalIO.bas"
'Include "IntOSC.bas"
'Include "LCD.bas"
Include "utils.bas"
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
End Function

// sampled AD value...
Dim ADVal As Word
Dim led As PORTC.7 
// initialise and clear LCD...
ADCON1 = $07       // PORTE as digital (LCD)
TRISA.0 = 1        // configure AN0 as an input
ADCON1.7 = 1       // set analogue input on PORTA.0
DelayMS (500)
LCD.Cls
Output(led)
SetAllDigital
// main program loop...
While true
led=1
DelayMS(500)
led=0
DelayMS(500)
   ADVal = ADInAsVolt
   LCD.MoveCursor (1,1)
   LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
   DelayMS(2500)
Wend
 

Visitor

Active Member
The words all have meanings, and this has been explained to you before.

What does the first circled area do?

What does the second circled area do?

Screenshot_20201119-123911_Edge.jpg
 

MrDEB

Well-Known Member
got it working with two ports
Code:
Device=18f43k22     
Clock = 8            '8MHz
Config FOSC = INTIO7   'internal oscillator   
#option LCD_DATA = PORTD.4
#option LCD_RS = PORTD.2
#option LCD_EN = PORTD.3
// import LCD library...
Include "utils.bas"
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
End Function
Function ADInAsVolt2() As Word
   result = (ADC.Read(1) + 1) * 500 / 1024
End Function

// sampled AD value...
Dim ADVal As Word
dim adval2 as word
// set this option true if building with the SE compiler
Dim led As PORTC.7
Output(led)
 led=0
// program start... 
SetAllDigital
While true
'led=1
'DelayMS(500)
'led=0
'DelayMS(500)
Cls

ADVal = ADInAsVolt
adval2= ADInAsVolt2
  LCD.MoveCursor (1,1)
  LCD.Write("DC Volts = ", DecToStr(ADVal / 100), ".", DecToStr(ADVal, 2), " ")
  writeat(2,1,"dc volts = " ,DecToStr(ADVal2 / 100), ".", DecToStr(ADVal2, 2), " ")
  DelayMS(50)
'WriteAt(1,1,"Hello World")
'DelayMS(2000)
 Wend
the circled area got put in by mistake from SAMPLE ADC CODE
my working code doesn't have porte it was an oversite
the circled area sets the ports up for adc input. I think the ADC.bas sets all the registers.
 

Visitor

Active Member
Actually learning what the words mean rather than copy&pasting an example from somewhere else might help you understand programming.
 

Visitor

Active Member
MrDEB, you may have noticed the number of people willing to help you is pretty close to ZERO. If you haven't, you should take notice of that fact.

You, with an inordinate amount of help, usually manage to make something work with a lot of trial and error, but it takes a lot out of those few folks willing to try to help you. It's time you actually learn to code, rather than copy&pasting random bits of code together. I tried to get you to actually think with my post with the circles, but your reply was you pasted the wrong thing. You will not learn anything that way.

So, start with the simple stuff.

¤ What does SETALLDIGITAL do and why is this necessary?

This is a simple question, yet essential for programming.

¤ What do the TRIS and ADCON statements in the first circle do?

Again, simple question and the answer is in the remarks.

¤ What happens to whatever the TRIS and ADCON accomplish when followed by SETALLDIGITAL?

If you can answer the first two questions, this will be easy to figure out.


Your problem is an extremely simple troubleshooting exercise that should have taken 30 seconds to spot. This isn't a complex problem; it's something that should be easy to recognize and fix.
 

gophert

Well-Known Member
Most Helpful Member
If computer and microcontroller manufacturers knew anything about product design, they would design their products to do what users wanted them to do, rather than what the user literally tell them to do.
 

Visitor

Active Member
If computer and microcontroller manufacturers knew anything about product design, they would design their products to do what users wanted them to do, rather than what the user literally tell them to do.
"Do what I meant, not what I said"?
 

gophert

Well-Known Member
Most Helpful Member
And before anyone gets out of control, post 6 was a joke.
 

gophert

Well-Known Member
Most Helpful Member
One could argue that that post isn't the only joke on this thread.
Every time I read new posts in this thread or the in famous (infamous) Christmas tree star thread, I think to myself, either Visistor has the patience of Job or he loves to be tormented. Then I looked up he current spelling of Job's name and discovered that Job was not patient at all. The word "patience" was a mistranslation in the King James Version of the Bible. It should have been Endurance. And, the quotes of Job are pretty in line with the quotes of Visitor as as he complains about his toils situation. The only difference between Job and Visitor, Job couldn't walk away from his source of torment.
 

MrDEB

Well-Known Member
SETALLDIGITAL sets all the IO pins to analog/ digital
Trisx configures the port
adcon1.7 =1 sets analog input to porta
 

Visitor

Active Member
SETALLDIGITAL sets all the IO pins to analog/ digital
Trisx configures the port
adcon1.7 =1 sets analog input to porta
Ha ha ha. This "understanding" explains so much.

Try again and answer the questions as asked. You might actually learn something.
 

tumbleweed

Active Member
Here's where copy-paste has gotten you into trouble all over again.

All pic's aren't the same, so what you did/copied for one device may not work for another.
You need to actually read the datasheet for the part you're using, or at least
check that the register settings you have in your code match up to the chip.

For example, here are some comments for what you had:
Code:
Device=18F43K22

// THIS DOES NOT SET "PORTE as digital (LCD)"
// ADCON1 selects the positive and negative reference for the ADC
ADCON1 = $07       // PORTE as digital (LCD)

// THIS IS TRUE
TRISA.0 = 1        // configure AN0 as an input

// THIS DOES NOT "set analogue input on PORTA.0"
// IT SELECTS THE SPECIAL TRIGGER FROM CTMU
ADCON1.7 = 1       // set analogue input on PORTA.0

DelayMS (500)
LCD.Cls
Output(led)

// IF THE ABOVE HAD DONE WHAT YOU WANTED, IT WAS TO NO AVAIL
// SINCE CALLING "SetAllDigital" NOW WILL WIPE OUT MOST/ALL THE ABOVE SETTINGS
SetAllDigital
And here's the real mind-blower... you don't have to set a pin's analog/digital mode to use the ADC.

As long as the pin is an input (use the INPUT statement) you can convert it.
You really only need to set a pin to analog mode to disable the digital input buffer which will not be happy with analog voltages at its input.
You DO, however have to set the "digital" pins to "digital mode" since they all power up as analog by default, and a pin in analog mode will always read as a '0' to the digital input.


Since all of that is probably gibberish, here are some tips

- use SetAllDigital at the beginning or your program, before you start doing anything else.
there is a subroutine called SetAnalogPort in the file SetDigitalIO.bas that you can use after that to set the one or two pins you want to use
with the ADC back to analog mode. That way you won't have to figure out the difference between how this works for all the different chips.

- use 'output' and 'input' statements and skip using the TRISx registers

- don't set a register when you have no idea what it does

Here's an example which sets all pins to digital except for RA0
Code:
device =18F43K22
include "setdigitalio.bas"

SetAllDigital

input(PORTA.0)
SetAnalogPort(AN0, ANA)

// rest of your code...
 
Last edited:

MrDEB

Well-Known Member
Yes a different code was pasted in wrong. I am not using the original posted code that failed to work.
Only using the Include "setdigitalio.bas" and placing it just before the WHILE TRUE statement
will search for the SetAnalogPort sub route.
presently attempting to get two leds controlled using a pot and the ADC function.
Led1 on then led2 on turning the pot slightly more turns off led1 but led2 stays on.
just need to refine the turn on/turn off points
 

tumbleweed

Active Member
Only using the Include "setdigitalio.bas" and placing it just before the WHILE TRUE statement
What part of
- use SetAllDigital at the beginning or your program, before you start doing anything else.
was ambiguous?

You really want it to be the FIRST statement, not later on after you've done other things.
Otherwise it could trash other changes you might have made.

Better yet, change the line where to have
Code:
include "setdigitalio.bas"
to the following and you'll never have to call SetAllDigital again, it will be done automatically for you.
Code:
#option DIGITALIO_INIT = true
include "setdigitalio.bas"
You want to add this at the very top of your program, not after a big long list of 'include' statements.
If you use those two lines, in that order, you can then remove all the SetAllDigital calls
 

tumbleweed

Active Member
If the setdigitalio.bas module sees that '#option DIGITALIO_INIT = true' then it'll automatically call the code for SetAllDigitial for you when the program starts up.

That's why the order of the two statements matters. The '#option' has to be set BEFORE you 'include', otherwise it won't be seen true and the compiler will skip generating the code.

The reason why you want those two lines before all the other 'includes' is that the compiler will process the include files in the order you list them.
If you have a bunch of other files before setdigitalio.bas then they will get processed first and a lot of other code could get
inserted before the code for SetAllDigital gets added.

This works the same way for all '#options'.

You want the program to set the digital/analog mode of the pins before you do anything else, otherwise pins might read as a '0' since the chip powers up with them in analog mode. That could cause your code to not work as intended.
 
Last edited:

Ian Rogers

User Extraordinaire
Forum Supporter
Most Helpful Member
MrDEB !!!! Before Jon pops a gasket..


SETALLDIGITAL .... SET ALL pins to DIGITAL..... Thus turns off the ADC to every pin.... To turn on individual ADC pins either use the ADCON reg's , or the newer chips, the ANSEL reg's
 

tumbleweed

Active Member
Actually, just to clarify, all of this analog/digital mode stuff never disables the ADC inputs...
it just enables or disables the digital input buffer, which is disabled by default for any pins that have analog capability.

It doesn't prevent you from reading an input pin with the ADC, even of the pin is set for "digital mode".
What it DOES screw with is the ability to read the pin normally.

When a pin is set for analog mode (which remember, is the default) its digital input buffer is disabled and it will ALWAYS read as a logic '0'.
That's why it's important to set the pin mode early in the startup sequence.

If a pin is going to be used for analog voltages (ie ADC, comparators, etc) it's a good idea to set it to analog mode.
That way the digital input buffer won't see invalid digital levels. For example, if a digital input sees 1.5V it's neither a valid high or a low.
This can cause the input buffer to oscillate and increase current consumption, which is never a good idea.

That's why they have the chip default to analog mode (which causes everyone to cuss and b*tch).
 

Latest threads

EE World Online Articles

Loading
Top