PIC a/d puzzler

Has anyone seen this behaviour before? I've got trim pots hooked up to a PIC18F2455, and my code simply reads ADRESH and ADRESL, converts to decimal and displays the result.

What happens is that the readings seem to span ranges, rather than putting out values from 0 to 1023 as I expected. For instance, as I turn the pot, the reading starts out at 0, then reads 011 for a bit, then 111, 139,

239, 267, 367, etc. It's always the same numbers, running up the sequence or down.

Does this ring any bells for anyone?

TIA

Reply to
Randy Day
Loading thread data ...

What else besides the PIC input are the other terminals of the pot connected to?

Reply to
John Popelish

+5 and ground ... ADCON1 bits 4 and 5 are 0
Reply to
Randy Day

(snip)

(nip)

Well, that should use Vdd for the full scale reference and Vss for the zero scale reference.

Take me through the rest of the bits in ADCON0, 1 and 2. How many inputs are you scanning? How long do you let each settle before converting? What is the resistance of the pots?

Reply to
John Popelish

Some things to check: Which way the result is justified (left or right) Your binary to decimal conversion routine Bypass caps on pots from center terminal to ground

Reply to
Anthony Fremont

ADCON2 bit 7 is 1 = right justify

Which reminds me: can someone explain what left justify gets used for?

BINTODEC ; derive decimal digits from TEMP vars CLRF HUNDRED_S CLRF TEN_S CLRF ONE_S

BTFSC TEMPHI, 1 ; if bit 1 of TEMPHI is one, add 256 to decimal CALL DEC256 BTFSC TEMPHI, 0 ; if bit 0 of TEMPHI is one, add 128 to decimal CALL DEC128

MOVFF TEMPLO, BINDEC_TEMP ; perform standard bin->dec conversion on LO byte MOVLW 0x64 SUBWF BINDEC_TEMP, 1 ; subtract hundreds BTFSC STATUS, 0 INCF HUNDRED_S . BTFSC STATUS, 0 GOTO $-8 ADDWF BINDEC_TEMP, 1

MOVLW 0x0A SUBWF BINDEC_TEMP, 1 ; subtract tens BTFSC STATUS, 0 INCF TEN_S BTFSC STATUS, 0 GOTO $-8 ADDWF BINDEC_TEMP, 1

MOVLW 0x01 SUBWF BINDEC_TEMP, 1 ; subtract ones BTFSC STATUS, 0 INCF ONE_S BTFSC STATUS, 0 GOTO $-8

RETURN

Hadn't thought of that, but won't that just smooth the readings I do get? I don't see how lack of them will cause this...

Reply to
Randy Day

Great when you need only low resolution and want to use only the 8 most significant bits.

Reply to
John Popelish

BSF ADCON2,7 ; right justify BSF ADCON2,4 ; set Tad = 32 BSF ADCON2,2 ; Fosc/4

movlw 0x03 movwf ADCON1 ; set inputs AN0-AN10, vrefs internal

Currently 5; more later. I just thought of something: would leaving the unused inputs floating cause this?

ADCREAD MOVWF ADCON0 ; set A/D to channel defined in WREG BSF ADCON0,0 ; start conversion CALL ONE_US CALL ONE_US CALL ONE_US ; wait 7us for A/D to settle CALL ONE_US CALL ONE_US CALL ONE_US CALL ONE_US BSF ADCON0,1 ; set the GO bit btfsc ADCON0,1 ; GO bit will change to zero when the conversion is complete goto $-2 MOVFF ADRESH, TEMPHI MOVFF ADRESL, TEMPLO

BCF ADCON0,0 ; turn off A/D RETURN

A mix of 50k and 100k pots.

Thanks for helping, BTW.

Reply to
Randy Day

That could be part of the problem. The pot should be equal to or less that the input impedance of the ADC and I think on most PICs that is 25K. The next thing is the MCU should have good power decoupling caps to keep Vref as stable as possible.

Jim

Reply to
James Beck

I see ADCON2,4 as ACQT1, which sets Taq to 4*Tad

So Tad is 4 cycles of Fosc and Taq is 4*4/Fosc, or 16 cycles of Fosc.

What is Fosc?

So, 12 inputs set as analog.

Not normally a problem. Driving current in or out of any input (beyond the supply rails) *will* affect the accuracy of the A/D conversions.

I see ADCON and ADRESH/L are bank one registers. Where do you select that bank?

Shouldn't that comment say 'power up A/D converter'?

Where on the data sheet do you find the time required for the A/D to settle after being enabled? I see the input settling time stuff (ADCON2,3 to 5), but nothing about enable (ADCON0,0) settling requirements.

These should work, though the 100k pots in the middle area (about 25k source impedance) will settle a bit slowly. But the error should be fairly fixed, not the walking steps you are seeing.

Reply to
John Popelish

Bit0, bit1, bit2, bit4 are 'stuck' bits. I'd suggest the binary to decimal conversion routine is messed up.

john

--
Posted via a free Usenet account from http://www.teranews.com
Reply to
john jardine

Ah. Of course.

Reply to
Randy Day

There's a small cap, but power supply fluctuations would cause fluctuations in a steady reading, would it not? If anything, I'm not getting *enough* fluctuation! :)

Reply to
Randy Day

That's one of the parts of this process that still confuses me, but I *think* it's 24 or

48 MHz:

config CPUDIV = OSC1_PLL2 config PLLDIV = 12

Actually 11. I needed one pin for digital.

I can imagine it would. ;-)

I don't need to, do I? IIRC, pic18 devices don't use banks.

The datasheet overview says 'start conversion', so I used that.

I used page 258, equation 21-3 as the example; the worst-case time was 6.4us, and I already had a ONE_US function, so I rounded to 7. If I can just get it to work, I'll shave it down later. ;-)

Reply to
Randy Day

I'm also confused. You will have to help me through your=20 clock set up (including crystal frequency, if any) for me to=20 understand.

I haven't programmed the PIC18F series, yet, so I may be=20 completely off base, here.

(excerpt from data sheet, section 5.3.2, Bank Select=20 Register (BSR))

The data memory in PIC18 devices is implemented as static RAM. Each register in the data memory has a

12-bit address, allowing up to 4096 bytes of data Large areas of data memory require an efficient addressing scheme to make rapid access to any address possible. Ideally, this means that an entire address does not need to be provided for each read or write operation. For PIC18 devices, this is accomplished with a RAM banking scheme. This divides the memory space into 16 contiguous banks of 256 bytes. Depending on the instruction, each location can be addressed directly by its full 12-bit address, or an 8-bit low-order address and a 4-bit Bank Pointer.

Most instructions in the PIC18 instruction set make use of the Bank Pointer, known as the Bank Select Register (BSR). This SFR holds the 4 Most Significant bits of a location=92s address; the instruction itself includes the eight Least Significant bits. Only the four lower bits of the BSR are implemented (BSR3:BSR0). The upper four bits are unused; they will always read =910=92 and cannot be written to. The BSR can be loaded directly by using the MOVLB instruction. The value of the BSR indicates the bank in data memory. The eight bits in the instruction show the location in the bank and can be thought of as an offset from the bank=92s lower boundary. The relationship between the BSR=92s value and the bank division in data memory is shown in Figure 5-6. Since up to sixteen registers may share the same low-order address, the user must always be careful to ensure that the proper bank is selected before performing a data read or write. For example, writing what should be program data to an 8-bit address of F9h, while the BSR is 0Fh, will end up resetting the program counter.

While any bank can be selected, only those banks that are actually implemented can be read or written to. Writes to unimplemented banks are ignored, while reads from unimplemented banks will return =910=92s. Even so, the STATUS register will still be affected as if the operation was successful. The data memory map in Figure 5-5 indicates which banks are implemented.

In the core PIC18 instruction set, only the MOVFF instruction fully specifies the 12-bit address of the source and target registers. This instruction ignores the BSR completely when it executes. All other instructions include only the low-order address as an operand and must use either the BSR or the Access Bank to locate their target registers. (end excerpt)

I think bank select bits are still in use.

I think that is the description of the Go bit.

That calculation refers to the acquisition time, that is=20 controlled automatically by setting ADCON2, bits 3 to 5 (in=20 conjunction with the Fosc setup). The PIC 16F series=20 required you to time out the acquisition time, but this one=20 appears to do that as part of the A/D conversion cycle,=20 automatically. But you adding this delay shouldn't be=20 involved in your problem. It is just wasted code and time.

Reply to
John Popelish

I would be very suspicious of your conversion routine. I seem to get (mostly) 1011 and 1111 in the least significant 4 bits for all those values. I am also suspicious of seeing jumps of exactly 100 - that would opit at a logic error in the conversion.

Can you print out the sequence (you say it always repeats) in binary (no conversion, just print out High/Low

Cheers

PeteS

Reply to
PeteS

I just pointed out 2 quick things that I see often as problems with stability/accuracy in using on board ADCs and PIC MCUs. Truthfully, I didn't pick through the enitire post. I just noticed the pot values and thought I would throw that out there.

Jim

Reply to
James Beck

Since your decimal conversion would produce some weird results, for example an input of 218 would convert to '1;8', I'm assuming that you are not printing what you think you're printing.

--
Ben Jackson AD7GD

http://www.ben.com/
Reply to
Ben Jackson

Reply to
Randy Day
[snip]

You're the second person to suggest the conversion routine. I'll try printing out the binary and decimal output. Thanks.

Reply to
Randy Day

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.