PDA

View Full Version : Stable ADC readings



dream-
- 22nd January 2011, 03:05
I am trying to get stable ADC readings.

I got a PIC 16F688 hooked up to a battery with a voltage regulator and with proper bypass capacitors. Each time I poll the ADC using ADCIN I get a different reading. Even averaging 50 samples is not enough to get a stable value. I have tried both internal and external oscillators (up to 20MHz).

I am testing it using a simple voltage divider with two resistors of the same value so that I get a value around 512 (ADC in 10 bit mode).

Is there anything I can do to stabilize the readings? And what is the source of all the noise?

Typically I am getting values oscillating from 432 up to 457, that's about a 5% oscillation.

There has to be a way to make the readings more accurate.6

Jumper
- 22nd January 2011, 07:32
If you use VDD as the voltage reference for your AD then it is most likely a not stable powerline. I know you said battery and voltage regulator but have you tried to measure the VDD with an ocsillocope?

If you really need to get high accuracy reading you might have to consider an external high precition voltage reference. That one you can connect to the VREF pin and then you can set up the AD to use that one.

Also if you are switching other stuff while doing the measurement it might affect the power supply to the pic as well.

I would start with making sure the power nice and clean and batteries are not the best source when you start doing new designs.

Acetronics2
- 22nd January 2011, 09:11
Hi,

May we get a scheme , plus your program ???

Crystal ball is out of range ... :D

Alain

sayzer
- 22nd January 2011, 09:51
Adding to what Jumper said, I also face similar issues.
Usually, using 7805 or 78L05 may not provide a stable 5V.
Say it is actually between 4.98V and 5.02V. (approx 5% datasheet statement)

So, if you are using 10-bit reading there is your problem.
Eventually, Jumper's suggestion of having a high precision voltage reference is a good idea.

Another issue :
Pausing 2ms after each ADCIN command may help.

mackrackit
- 22nd January 2011, 10:04
And...

More CAPs.
A capacitor from the ADC pin to VSS will help smooth things out. Will not make up for a bad power supply though.

Acetronics2
- 22nd January 2011, 11:17
Hi, Sayzer



I am testing it using a simple voltage divider with two resistors of the same value so that I get a value around 512 (ADC in 10 bit mode).


That means he works in ratiometric mode and supply changes do not interfere here ...
so, problem is elsewhere ... ;)

Alain

sayzer
- 22nd January 2011, 13:46
Hi, Sayzer



That means he works in ratiometric mode and supply changes do not interfere here ...
so, problem is elsewhere ... ;)

Alain

Yes Alain, I missed that.

Then, may be he should pause ~2ms after each read.

Also, for example, reading lower voltages and reading higher voltages may behave differently.
If reading higher voltages are accurate, but lower voltages are not, then there is something else, too.




---------------------------

mister_e
- 22nd January 2011, 15:00
Input impedance too high, too short of ADC aquisition time, noisy PSU, unstable PSU, no averaging routine, multiplexed function on the ADC pin, loose/dirty bread board contacts, poor wiring, poor oscillator, poor decoupling, etc... quite a few possibilities...

dream-
- 22nd January 2011, 17:47
As mentioned I am decoupling, using averaging, and testing the ratio of two resistors hooked up to the same battery after the regulator.

Let me draw the schematic and I will post.

But before that, let me say that I switched from ADCIN to doing a manual ADCON0.1 = 1 reading, and now I get a stable value. So my problem is an erroneous use of the ADCIN command or a problem in the logic of my routine.

BEFORE:


DEFINE ADC_BITS 10 ' Set number of bits in result (8, 10 or 12)
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in microseconds
...
WSum = 0
Pause 100

For i = 0 to 49
ADCIn PinProbe, W0
Pause 10
WSum = WSum + W0
Next i

W0 = WSum / 50


NOW:


Pauseus 50 'Stabilize
ADCON0.1 = 1 'start the ADC
WHILE ADCON0.1 : WEND

W0.HighByte = ADRESH
W0.LowByte = ADRESL


It works, now the reading stays fixed and it is much faster. (I even didn't have to do any averaging)

Acetronics2
- 22nd January 2011, 18:05
Hi,

What about reinitialising your Wsum value to 0 @ each 50 samples batch ??? don't you run this loop in another continuous loop ... ??? " par hasard " ... :confused:

BTW " PinProbe " is the alias for which pin ???

Alain

dream-
- 22nd January 2011, 18:12
Hi,

What about reinitialise your Wsum value to 0 @ each 50 samples batch ??? don't you run this loop in another continuous loop ... ??? :confused:

Alain

Oh I do. I left that part out of the code I pasted, but it is indeed running in an outside continuous loop.



PinProbe VAR PORTA.2
...
myLoop:

WSum = 0
Pause 100

For i = 0 to 49
ADCIn PinProbe, W0
Pause 10
WSum = WSum + W0
Next i

W0 = WSum / 50
...
LCDout $fe, 1 'Clear Screen
Lcdout $fe, $80
Lcdout "Reading: ", DEC W0

Goto myLoop

The readings I get with the ADCIN method are in the ballpark but move around too much. With the "manual" ADC method I get a stable value.

Acetronics2
- 22nd January 2011, 18:38
ADCIN also polls for the ADCON0.1 bit ...

sooo .... aheum, how to tell it ... :rolleyes:

Alain

mister_e
- 22nd January 2011, 19:06
ADCIN also polls for the ADCON0.1 bit ...

sooo .... aheum, how to tell it ... :rolleyes:

Alain

Yeah but we already say some odds with ADCIN in the past on some specific PIC, Microchip are good to change the way register are done, and how things work for PIC to PIC model...

This said, I never use ADCIN myself, but manually write/read ADC registers... it is also a bit less code hungry... down side "may" be when you port your code on another PIC who's not working the same way, or have different register name, bit assignment. big deal :rolleyes:

dream-
- 22nd January 2011, 19:27
Well if I understood what the problem was I would not be asking here :)

The fact is that the ADCIN code gives me an oscillating reading, and the manual method gives me a stable value.

I don't know the reason, but I would like to know. This is a 16F688.

mackrackit
- 22nd January 2011, 20:01
For what it is worth I agree with Steve.
I tried ADCIN a couple of times and did not like it. Others swear by it though. ..

Keep doing it the way you are.

mister_e
- 22nd January 2011, 20:13
I would love to see the whole code with ADCIN. Sometime if you play with some ADC registers, and you place them Before or After the DEFINEs, it may end-up with unexpected results.

Acetronics2
- 23rd January 2011, 10:58
Hi,

Found in the Datasheet ...




Note: The GO/DONE bit should not be set in the
same instruction that turns on the ADC.
Refer to Section 8.2.5 “A/D Conversion
Procedure”.


a beginning of an explanation ???

Alain

Bruce
- 23rd January 2011, 13:05
ADCIN doesn't work with port pin aliases. Use ADCIN 2,W0, or define PinProbe as a constant. PinProbe CON 2 would work.

Also ADCIN doesn't setup TRIS, ANSEL or ADCON1. So you end up with Fosc/2 for your A/D clock because ADCON1 defaults to all 0's. So you're way out of spec for a 4MHz osc. Fosc/8 would be a good one to use with 4MHz (see datasheet).

Acetronics2
- 23rd January 2011, 13:50
Bruce ... 1K points ... ;)

as always !!!...

Shame on me. :rolleyes:

Alain

mister_e
- 23rd January 2011, 20:33
Blonde moment here too

Disclaimer: "Blonde moment" is a deliberate sentence that belongs to Mister_e user and plah plah plah, shall not be considered as offensive plah plah plah. Complaints about that shall not be send to Admin, Mods, user but only to Mister_e user plah plah plah.... :D

Acetronics2
- 24th January 2011, 08:10
Hi, Steve

I Think the "Blonde" term use rights already belong to KarenHornby ... :D

so, you'll have to buy a licence ...

Alain

mister_e
- 24th January 2011, 16:59
busted :( .....

HankMcSpank
- 8th February 2011, 23:35
So to summarize 'in speak' that won't scare folks who thought if/then statements were an uinsurmountable hurdle.....are we saying that using the ADCIN is not optimum...and if not could someone please post a chunk of code to do this in an alternative method?

mackrackit
- 8th February 2011, 23:42
http://www.rentron.com/PICX2.htm

HankMcSpank
- 9th February 2011, 09:47
Excellent.....many thanks, I shall use that code gratuitously.

Ioannis
- 9th February 2011, 12:13
Have you tested this fast averaging with Hysterisis by Darrel:

http://www.picbasic.co.uk/forum/content.php?r=248-Analog-to-digital-averaging-with-hysteresis

Ioannis

HankMcSpank
- 9th February 2011, 15:57
Yes I have (& very good it is too) , but I'd rather have this jittery AtoD values 'cleaned up' at the source (rather than putting averaging in place to address unstability caused by avoidable factors)

Bruce
- 9th February 2011, 16:06
Just include an RC filter on the A/D input, and put the PIC to sleep just before enabling the A/D conversion. This returns very stable readings in most applications with a stable power supply or Vref.

fratello
- 11th February 2011, 07:19
Nice subject !
I use a similar code for reading the over-current of one DC motor :

check:
vt =0
vs =0
grup=0
cnt =0
pause 50
for cnt = 1 to 10
adcin 3, adval
vt=adval * 5000
vt=div32 1023
grup=vt+grup
pause 5
next cnt
vs=grup / 10
if (vs > checkin) or (T1Count > 50) then
gpio.0=0
gpio.5=0
endif
If the averge of 10 readings it's bigger than checkin value (or time exceed 5 seconds) then gpio.0 and gpio.5 goes low.
It's one good ideea to use ADCON instead ADCIN ? How to do this and keeping average of 10 readings ?

fratello
- 11th February 2011, 20:39
It's this correct ?
In header of code I add :

ADCON0 = %10001101 ' ADC input on GPIO.4/AN3/pin3 (page 41)
' MSB 1 = Right Justify "1"
' 0 = Vdd as voltage reference "0"
' 0 = n/a "00"
' 0 = n/a
' 1 = select channel 03 (bit 2 of 2) "11"
' 1 = select channel 03 (bit 1 of 2)
' 0 = conversion status (see routine) "0"
' LSB 1 = A/D converter module is on "1"
And I modify the "check" subroutine like that :

check:
vt =0
vs =0
grup=0
cnt =0
pause 50
for cnt = 1 to 10
ADCON0.1 = 1
NOT_DONE:
if ADCON0.1 = 1 THEN NOT_DONE
Pause 10
adval.highbyte = ADRESH
adval.lowbyte = ADRESL
PAUSE 10
vt=adval * 5000
vt=div32 1023
grup=vt+grup
PAUSE 10
next cnt
vs=grup / 10
if (vs > checkin) or (T1Count > 50) then
gpio.0=0
gpio.5=0
endif
The hardware it's in picture.
Thanks !

fratello
- 19th February 2011, 19:12
I've tested the code ; it's OK.

HankMcSpank
- 26th June 2011, 18:42
I've used ADCIN pretty much from day one, but I noticed I was getting some *very* jittery readings (255,243,246,255,243,246 etc)...I couldn't get to the bottom of it (spent a good while trying the usual stuff), I'd forgot about this thread but thankfully foiund it with Google)

It's the first time I've used the manual ADC method......but I'm pleased to also report my ADC readings are now solid as a rock.

Just for the record, here's what I used on my 12lf1822 (I'm only using 8 dits ADC)...



ADCON0 = %00000100 ' select ch1 (AN1 Pin 6)
ADCON1 = %00000000 'set ADC +ve reference to VCC
'
main:
gosub Do_ADC
pause 100
hserout [DEC ADC_RESULT,13,10]
goto main
'
'ADC sub routine...
Do_ADC:
PAUSEUS 50 ' Wait for A/D channel acquisition time
ADCON0.1 = 1 ' Start conversion
WHILE ADCON0.1 ' Wait for it to complete
WEND
ADC_Result = ADRESH
return


Many thanks to you all on this thread...I shall never go back to the ADCIN method!

HankMcSpank
- 26th June 2011, 20:53
I wish the edit feature was open longer - I forgot to turn the ADC on above, sohere's the correction....



ADCON0 = %00000101 ' select chan1 (AN1 Pin 6), turn ADC On Bit 0

mazoul72
- 24th August 2011, 18:48
Hello,
i made this to programm ADC

bmf_comm1 VAR PORTB.0
bmf_comm2 VAR PORTB.1
'Variables
bmfsD VAR WORD
bmfs1D VAR WORD
iled var byte
blink1 var byte 'pour clignotement 1ère led
blink2 var byte 'pour clignotement 2ème led
'configuration du port pour lire l'entrée analogique
TRISA = %00000011 ' RA0 et RA1 en entrée
TRISB = %11111100 ' RB0 et RB1 en sortie
ADCON1 = $10000010 'RA0 à RA3

test_depart:
Low bmf_comm1
Low bmf_comm2
High bmf_comm1
high bmf_comm2
pause 2000
goto mainloop
'lecture de la valeur
getad:
PAUSEUS 50 ' Wait for A/D channel acquisition time
ADCON0.2 = 1 ' Start conversion
WHILE ADCON0.2 ' Wait for it to complete
WEND
Return

' Subroutine to get pot x value
getx:
ADCON0 = $41 ' Set A/D to Fosc/8, Channel 0, On
Gosub getad
bmfsD = ADRESL + (ADRESH*256)
Return

' Subroutine to get pot y value
gety:
ADCON0 = $49 ' Set A/D to Fosc/8, Channel 1, On
Gosub getad
bmfs1D = (ADRESH*256) + ADRESL
Return
val_leds:
low bmfs_comm1
low bmfs_comm2
gosub getx
gosub gety

if (bmfsD > 1000) Then Goto val_leds
if (bmfsD > 750) Then Goto boucle_led
if (bmfsD > 500) Then Goto boucle1_led
if (bmfsD > 250) Then Goto boucle2_led

High bmf_comm1
High bmf_comm2
pause 1500
goto val_leds
boucle_led:
iled = 0
while iled < 5
if iled = 1 or 3 or 5 then high blink1:low blink2
if iled = 0 or 2 or 4 then low blink1:high blink2
iled = iled + 1
pause 1000
wend
goto val_leds
boucle1_led:
High bmf_comm1
low bmf_comm2
pause 3000
goto val_leds
boucle2_led:
low bmf_comm1
high bmf_comm2
Goto val_leds
End

The leds works but always lightning , action on button (RB0 only for the moment) don't change anything.
No blinking .
I don't know what .
thanks.

mister_e
- 24th August 2011, 18:58
Salut et Bienvenue sur le forum ;)

I haven't check the whole thing in deep but I think you should modify the boucle_led section to


boucle_led:
iled = 0
while iled < 5
if iled = 1 or 3 or 5 then
high blink1
low blink2
endif

if iled = 0 or 2 or 4 then
low blink1
high blink2
endif
iled = iled + 1
pause 1000
wend
goto val_ledsProbably it will solve your problem though... let me know the PIC you're using and your PBP version.

EDIT: Your code have 2 compilation error
1) no mainloop label
2) adcon1: the way you have written it, it's value should start with a % instead of a $

mister_e
- 24th August 2011, 19:22
Looking at your code, I guess it's your first program, There's quite a few mistakes in and it is also hard to follow what you want to do.

No problem, been there...done that. Tell us what you want to do and we could build something to help you to get started.

Tell us the PIC your're using and post your schematic if you have any, or describe it.

mazoul72
- 24th August 2011, 21:40
Sorry for double post but i tried many many modifications.
my pic is 16F877A , i desire to put multifunctions buttons of steering wheel and decode for command radio car system .
i make a test with leds for ADC value input .
Oh,oh,oh,
i have just see that i don't put MCLR to any connection , a resistor of 4.7kohms to +5V ?

It is a very simple schematic for test but the entire schematic is for steering wheel command and FIS Tachometer car display modification in live .
example : see the kwp1281 protocol codes of line K (not can bus) like VCDS soft but more simple.

This is the first part ( BMF )

For mainloop , it is because i modify the labels and i forgot it (val_leds) .
For $ , it is a mistake , THANKS.
i will try now

Regards

mazoul72
- 24th August 2011, 22:30
my leds light off after 2 sec , it is ok for starting (mainloop replaced by val_leds)
But after i have only two leds lightning together , it is not good with all boutons
and i have no blinking leds

And now i have no actions on leds (off always) , i don 't undertand why , AD not stable or other....
it is the same with or without MCLR .

mister_e
- 24th August 2011, 22:45
Ah ok I see, you read a voltage then act upon. Cool, I did something like that awhile back but it was for car remote starter purpose (Door lock, alarm bypass, Windows roll-up/down) Oh well, those were the days ;)

Yes MCLR must be tied to Vdd. 4.7K is fine.

not sure of what you want to do and how it should flash your LEDs but try this one


bmf_comm1 VAR PORTB.0
bmf_comm2 VAR PORTB.1

LEDBlinkRate CON 200

'Variables
bmfsD VAR WORD
bmfs1D VAR WORD
iled var byte

'configuration du port pour lire l'entrée analogique
TRISA = %00000011 ' RA0 et RA1 en entrée
TRISB = %11111100 ' RB0 et RB1 en sortie

DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in
ADCON1 = %10000010 ' RA0 à RA3

test_depart:
PORTB = 3 ' Turn ON PORTB<1:0>
pause LEDBlinkRate '

val_leds:
PORTB = 0 ' Turn OFF PORTB<1:0>
PAUSE LEDBlinkRate
ADCIN 0,BMFSd ' Read CH0
ADCIN 1,BMFS1d ' Read CH1
if (bmfsD > 1000) Then val_leds
if (bmfsD > 750) Then boucle_led
if (bmfsD > 500) Then boucle1_led
if (bmfsD > 250) Then boucle2_led

goto test_depart

boucle_led:
PORTB = 1
for ILED = 0 to 5
PORTB = PORTB ^ 3
PAUSE LEDBlinkRate
NEXT
goto val_leds

boucle1_led:
High bmf_comm1
pause LEDBlinkRate
goto val_leds

boucle2_led:
high bmf_comm2
PAUSE LEDBlinkRate
Goto val_leds
End seems to work for me here, 4MHz oscillator, some different led blinking opattern depending of the value of AN0.

mazoul72
- 25th August 2011, 15:41
Hello,

it still doesn't work ....I don't understand why .
The leds are still off whenever i select any buttons .
I see 3.96 V between middle point of my buttons and external pull up resistors (on RA0 and RA1) .
When i push buttons , i have 1.44V / 0.80 V / 0.40 V .
Whith quantum 4.88xxx mV , it gives to me 295 , 164 , 82 .
For 3.96V , 811 aproximatively .

LED replace resistors out (to test)

5911

mister_e
- 25th August 2011, 18:17
Simple, there's no voltage in there as it is right now. You'll need to modify the circuit to add some voltage there. The pull-up thing should work.

Do yourself a big favor, output the value of the ADC reading to a LCD or to your computer, push on a single button, note the value and modify the IF-THEN value in the code.

What are your pull-up value?

Ioannis
- 25th August 2011, 18:50
On F877 or F877A there are NO pull-ups on port A. Only on Port B.

Ioannis

mister_e
- 25th August 2011, 19:15
Check this thread, seems you want to do something really alike
http://www.picbasic.co.uk/forum/showthread.php?t=15229&

mazoul72
- 26th August 2011, 00:19
10k for pull up external.
i have only two wires to tie at right and two wires to tie ar left of steering wheel.
So 12 buttons in fact .
If i tie like the thread you provided , so many wires and this is the first part of entire PIC system .
i am not sure there are enough wires after this.
I have 25 inputs/outpouts tie to PIC .(without components reserved operation )
Perhaps the eight outpouts/input reserved to LCD (for test before FIS tachometer connected) .

mister_e
- 26th August 2011, 00:28
The link I provided was about the OUTPUT not the input. It show how to connect your resistor and how to code it.

your whole system to the car should be more than 6 wire... but 3 of them should already be GND or +5v/+12V.

Plug the steering wires, push on each button, for each button you have a diffferent ADC reading.

OR use a multimeter and measure the resistor value when you push on a single button.... also when you don't push on any button. From there we can also work out a solution.

Also, we still have NO information about your radio, no brand, no model no nothing. At least do you know the resistor value needed for each function?

mazoul72
- 26th August 2011, 00:51
Yes i tried last month , i have the value.
I have already put schematic.
my radio is pioneer 6900IP , only a jack remote input.

My intension is to keep the wires buttons .
With more wires , i have to change all connections.

mister_e
- 26th August 2011, 01:33
I know the input... how about the output?

BTW, as per the service manual, this radio seems to use a stereo Jack... maybe you need a resistor on the tip, another on the ring? Whatever, the method on the previous link will work for the OUTPUT section.

5912

5913

mazoul72
- 26th August 2011, 19:35
I try assembler but i have some errors5917

mister_e
- 26th August 2011, 19:38
Assembler, C, Fortran or Pascal will not solve the problem here. The problem is not the ADC reading, it is what you do with.

mazoul72
- 27th August 2011, 00:20
the soft ? picbasic pro ?????
i have the same error with mplab
thanks to be explicit .
it is an example from a guy - it works for him !
it is not easy to spend all days to arrive ( only ADC) to nothing !

Herve

mister_e
- 28th August 2011, 12:20
Hervé, je veux bien t'aider du mieux que je peut, mais tu va devoir faire une partie des devoirs de ton coté.

Ok, let's observe the schematic you posted

http://www.picbasic.co.uk/forum/attachment.php?attachmentid=5911&d=1314282849
OK, please answer the following question:

Q1: The Resistor attached to the button are built-in the remote/Steering and you can't modify anything in right?

A1:_______________________________________

Q2: You have a 10K pull-up On RA0, and another on RA1... true?

A2:________________________________________

Q3: If so, assuming you don't push on any button, Between GND and RA0 AND between GND and RA1 with your multimeter you should read something like 1.4Volt RIGHT?

A3:________________________________________

From there, we need to etablish at least 4 conditions
1) ADC reading when no push button are pressed
2) ADC Reading when you push on Button 1 alone
3) ADC Reading when you push on Button 2 alone
4) ADC Reading when you push on Button 3 alone

We can use maths to do so OR output each ADC reading to a LCD OR send the data do your PC via serial communication OR store them in the PIC EEPROM. Choice is yours. Let's see if the maths could work here.

Without any push button pressed, I said around 1.4. Using the voltage divider theory
(3902/(3902+10000))*5 = 1.403

so the ADC should return something like
(1.4/5)*1023 = 287

Do the same with the other resistor value and you should be able to evaluate
1) when no push button are pressed
V = 1.4
ADC Reading = 287

2) When you push on Button 1 alone
V = 0.37
ADC Reading = 76

3) When you push on Button 2 alone
V = 0.58
ADC Reading = 119

4) When you push on Button 3 alone
V = 0.82
ADC Reading = 168

Now, try this.


'
' Hardware setup
' ==============
'
' I/O
' ---
TRISA = %00000011 ' RA0 et RA1 en entrée
TRISB = 255 ' Disconnect all resistor from the circuit
PORTB = 0 '
'
' ADC
' ---
DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in
ADCON1 = %10000010 ' RA0 à RA3

'
' Software Variable
' =================
ADRes VAR WORD ' ADC Reading
BTN var byte ' Data to be sent to PORTB
i VAR BYTE '
ADCChannel VAR BIT '
ADCButton VAR BYTE [3]'
'
' Software constant
' =================
ADCSafety CON 10 ' min/max range for ADC Reading
'
ADCNone CON 287 - ADCSafety '
ADCButton[0] = 76 ' button 1 or 4
ADCButton[1] = 119 ' button 2 or 5
ADCButton[2] = 168 ' button 3 or 6

Start:
TRISB = 255 ' Disconnect all resistor from the circuit
ADCIN ADCChannel,ADRes ' Read ADC
'
if (ADRes < ADCNone) Then ' Any button down?!?
' - Yes!
FOR i = 2 TO 0 STEP -1 ' Loop through all 3 calculated posibilities
' Test against calculated ADCresult
' and allow a range of +/- ADCSafety
IF (ADRes > (ADCButton[i]-ADCSafety)) AND (ADRes < (ADCButton[i]+ADCSafety)) THEN
' Valid ADC result, clear the coresponding I/O
TRISB = ((DCD i) << (ADCChannel*3)) ^255
PAUSE 200
i=0 ' and getOut of here
ENDIF '
'
NEXT '
'
else ' - NO!
' Switch to the other ADC channel
ADCChannel = ADCChannel ^ 1
ENDIF
GOTO Start '

Button 1, enable PORTB.0, Button 2 PORTB.1 etc etc.

For testing purpose use LEDs to VDD. It works here.

Ioannis
- 28th August 2011, 16:10
I Bet there are no pull ups on port A inputs.

Ioannis

ivanrosales
- 28th August 2011, 18:22
mazoul72, I'm really new to picbasic, but I note in your schematic that you don't have pull-up resistor, so please try something like this:
http://dl.dropbox.com/u/29237304/ADCIN.jpg

Also, try to code something like the below example, if you rotate the bits of your ADC reading, you can leave only the 2 most significating bits, this way, you can know the exact button pressed (of course you must calculate correctly the resistors values):

DEFINE ADC_BITS 8
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 50

ADVal var byte
Switch var byte

Principal:
adcin 3,adval
switch = (adval >> 6) 'Shift for 2 MSB for values 0 to 3 representing each button

SELECT CASE switch
CASE 0
'Put your code here
gpio=0
CASE 1
'Put your code here
high gpio.0
CASE 2
'Put your code here
high gpio.1
CASE 3
'Put your code here
high gpio.2
END SELECT

goto principal
end

mister_e
- 28th August 2011, 18:39
Post #44

10k for pull up external.
I guess it's an omission on it's schematic. At least I hope ;)

ivanrosales
- 28th August 2011, 19:16
That's right Master mister_e, he mention the 10k pull-up before, but I want to be sure he is assembling his circuit properly (just to have peace of mind) ;)

By the way Master, I'm new to this forum as well to picbasic and since I first read your posts you became my "Personal Jesus"
Regards!

mister_e
- 28th August 2011, 19:20
Don't do that, Depeche Mode have some Copyright on that quote :D

Welcome aboard!

mazoul72
- 28th August 2011, 21:17
Hello,
First many thanks to your answers .

OK, please answer the following question:

Q1: The Resistor attached to the button are built-in the remote/Steering and you can't modify anything in right?

A1:_Yes , it is too little inside because it is cms components .

Q2: You have a 10K pull-up On RA0, and another on RA1... true?

A2: Yes , it is an omission but it is 10Komhs for test ( 3.96 Volts with no action)

Q3: If so, assuming you don't push on any button, Between GND and RA0 AND between GND and RA1 with your multimeter you should read something like 1.4Volt RIGHT?

A3: No , i read 3.96 Volts on 10K resistors and RA0,RA1.

So , (3902/(3902+10000))*5 = 1.403 .
i will verify if there is another resistors but i see 3902 ohms (i am sure) , perhaps an error . I will tell you about.

I don't understand : TRISB = ((DCD i) << (ADCChannel*3)) ^255

5922

Best regards
Hervé

mazoul72
- 28th August 2011, 21:55
5924

i don't know why 3.96 V and not 1.4 V ....

mister_e
- 28th August 2011, 22:13
3902 is actually 39K, so the other resistor are also bad... ok then. So be it.

modify what's in red


'
' Software Variable
' =================
ADRes VAR WORD ' ADC Reading
BTN var byte ' Data to be sent to PORTB
i VAR BYTE '
ADCChannel VAR BIT '
ADCButton VAR WORD [3]'
'
' Software constant
' =================
ADCSafety CON 10 ' min/max range for ADC Reading
'
ADCNone CON 814 - ADCSafety '
ADCButton[0] = 90 ' button 1 or 4
ADCButton[1] = 164 ' button 2 or 5
ADCButton[2] = 270 ' button 3 or 6 should work

This is Why I asked to measure with your ohmmeter a couple of post back... and nope I'm not going to decipher a PCB ;)

You have everything on hand....

mister_e
- 28th August 2011, 22:22
I don't understand : TRISB = ((DCD i) << (ADCChannel*3)) ^255
Check your manual about DCD, logical and bitwise operators. It's all there ;)

Anyone wants to explain it?

Yes I've put some black magic in :D

mazoul72
- 30th August 2011, 10:02
Hello Steve ,

i have some erratic values on BTN result ( BTN = TRISB ) under pic smulator ide 6.91 .
like 1 . 2 . 4 .255 and cycle infinite .

But i will try this evening on led test or resistors.

I note in 16f877x datasheet that with "1" TRISB , we have High Impedance so we can choose whose resistor to be put off .
But with other state bit of TRISB , i don't understand how tie to common +5V of car radio (TIP) to the RB0,RB1,RBx..... ???
We have agree that it is a result of a resistor between common ground (sleeve) and +5V (tip) on jack "grip" .

Hervé.

mister_e
- 31st August 2011, 00:40
Never trust a sim... as simple as that. They're on the market for laziness and to make good money out of it. Good enough to replace any xBox, Nintendo... or some porn.

You tie the resistor like the guy in that previous thread. One side on the PIC the other side are tied together and sent to the Radio.

mazoul72
- 31st August 2011, 08:54
Hi Steeve,

i test intensity value with some résistors tie together to one led.

But with your program , trisb stay at 255 , i put some select case for test but no trisbx.0 work (255 always)
I will try to my test platine .
I understand your "voodoo formule" , it is for have only one button put on , no action with 2,3 .. together .

Regards.
Hervé

mazoul72
- 31st August 2011, 11:47
i repeat my question :
how tie the resistors on the side of PIC together to have a resultant resistor in parallele ?
i agree that the other side is tie together to the radio , but on the ground ,yes
but the +5V for PIC RBx ?

Regards.

Hervé

mazoul72
- 31st August 2011, 17:37
in fact , the simulator isn't reactif with adc , i must go slowly with an0/an1 choice .
But step by step around button(i) , it works.

I must add six other buttons in programm and .

mazoul72
- 1st September 2011, 13:54
Can i use btn as word variable for a select case like 1110111111111111 ?
(with your formule dcd(i).... )
i can't for the moment ...
i use adcchannel 0 to 3 .

Regards.
Hervé

mister_e
- 1st September 2011, 19:33
pbp 3 manual section 2.12

mazoul72
- 2nd September 2011, 00:35
Hello,

it works all !
great and many thanks.

I made another "formule" in addition to yours (to work with 12 buttons and 4 channels__3 buttons on a wire)
It is perhaps not proper .
I add to this : PIC Simulator IDE 6.91 works great , all test with it and great.


. btn = ((DCD i) << (ADCChannel*3))^255
. if ADcchannel = 3 and btn = %11111111 then btn = (btn - (3*adcchannel)) << i
. gosub choose
..
..
ADCChannel = ADCChannel + 1 'Switch to the other ADC channel
if ADCchannel = 4 then adcchannel = 0
..
..
choose:
select case btn
' first bloc of 6 buttons
case %11111011 ' AN0-270 --- 47k and 5k = 4.6k
TRISB.0 = 0 ' 5k and 5k = 2.5k
TRISB.1 = 0
case %11111101 ' AN0-164 --- 47k and 10k = 8.2k
TRISB.1 = 0 ' 5k and 5k = 2.5k
TRISB.2 = 0 ' 47k and 47k = 22k
case %11111110 ' AN0-90 --- 47k and 22k = 15k
........


Regards
Hervé

mazoul72
- 2nd September 2011, 13:35
i am so disapointed because it doesn't work on test real card and works on simu.
strange...
i have microcode studio with 15 days trial .(compiler 3.0.0.1)

TRISA = %00001111 ' RA0 et RA1 en entrée

TRISB = 255 ' Disconnect all resistor from the circuit (Haute impédance)

PORTB = 0 '

'

' ADC

' ---

DEFINE ADC_BITS 10 ' Set number of bits in result

DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)

DEFINE ADC_SAMPLEUS 50 ' Set sampling time in

ADCON1 = %10000010 ' RA0 à RA3 and RIGHT JUSTIFIED



'

' Software Variable

' =================

ADCRes VAR WORD ' ADC Reading

btn var byte ' Data to be scan

i VAR BYTE '

j var bit

ADCChannel VAR byte '

ADCButton VAR word [3]'

'

' Software constant

' =================

j = 0

ADCSafety CON 10 ' min/max range for ADC Reading

'

ADCNone CON 814 - ADCSafety '

ADCButton[0] = 90 ' button 1,7 or 4,10

ADCButton[1] = 164 ' button 2,8 or 5,11

ADCButton[2] = 270 ' button 3,9 or 6,12



Start:

TRISB = 255

ADCIN ADCChannel,ADCRes ' Read ADC

'

if (ADCRes < ADCNone) Then ' Any button down?!?

' - Yes!

FOR i = 2 TO 0 STEP -1 ' Loop through all 3 calculated posibilities

' Test against calculated ADCresult

' and allow a range of +/- ADCSafety

IF (ADCRes > (ADCButton[i]-ADCSafety)) AND (ADCRes < (ADCButton[i]+ADCSafety)) THEN

' Valid ADC result, clear the coresponding I/O

btn = ((DCD i) << (ADCChannel*3)) ^255

if (ADcchannel = 3 and btn = 255) then btn = ((btn - (3*adcchannel)) << i)

gosub choix

pause 200

i=0 ' and getOut of here

ENDIF '

NEXT '

else ' - NO!

ADCChannel = ADCChannel + 1 'Switch to the other ADC channel

if ADCchannel = 4 then adcchannel = 0

ENDIF

GOTO Start

choix:

select case btn

' premier bloc de 6 boutons
case %11111011 ' AN0-270 --- 47k and 5k = 4.6k

TRISB.0 = 0 ' 5k and 5k = 2.5k

TRISB.1 = 0

case %11111101 ' AN0-164 --- 47k and 10k = 8.2k

TRISB.1 = 0 ' 5k and 5k = 2.5k

TRISB.2 = 0 ' 47k and 47k = 22k

case %11111110 ' AN0-90 --- 47k and 22k = 15k

TRISB.2 = 0

TRISB.3 = 0 ' 10k and 10k = 5k

case %11011111 ' AN1-270 --- 47k and 2.2k = 2.1k

TRISB.3 = 0 ' 47k and 15k = 11.3k

case %11101111 ' AN1-164 --- 100k and 22k = 18k

TRISB.4 = 0 '

TRISB.0 = 0 '

case %11110111 ' AN1-90

TRISB.5 = 0

TRISB.1 = 0

TRISB.3 = 0

' deuxième bloc de boutons

case %11111111 ' AN2-270 --- 47k and 5k = 4.6k

TRISB.7 = 0 ' 5k and 5k = 2.5k

TRISB.6 = 0

case %01111111 ' AN2-164 --- 47k and 10k = 8.2k

TRISB.5 = 0 ' 5k and 5k = 2.5k

TRISB.4 = 0 ' 47k and 47k = 22k

case %10111111 ' AN2-90 --- 47k and 22k = 15k

TRISB.2 = 0

TRISB.3 = 0 ' 10k and 10k = 5k

case %11011000 ' AN3-270 --- 47k and 2.2k = 2.1k

TRISB.7 = 0 ' 47k and 15k = 11.3k

case %11101100 ' AN3-164 --- 100k and 22k = 18k

TRISB.5 = 0 '

TRISB.0 = 0 '

case %11110110 ' AN3-90

TRISB.5 = 0

TRISB.7 = 0

TRISB.3 = 0

end select

return

mister_e
- 2nd September 2011, 20:34
Dunno buddy, replace your resistor with LED to Vdd and see what happen, Code seems to be OK.

On your PIC16F877, make sure you have all VDD and VSS pin connected, MCLR to VDD and the right capacitor around the crystal. If you're using an >4MHz one, set the HS_OSC fuse. Always make sure you also disable LVP in the configuration fuse too.

mazoul72
- 3rd September 2011, 14:33
Dunno buddy , your program Code works very well with some resistors and one led on my PIC Hardware platform test .
With it , the intensity varies according to different buttons .
Perhaps microcode studio with 15 days trial .(compiler 3.0.0.1) ?
my programmer is willem with winpic800 .

mazoul72
- 3rd September 2011, 15:06
i 've just try compiler 2.60 plus patch 2.60c under microcode studio 3.0.0.5
and verify fuse under willem (hs) , always the same .
arg , no understand why if the code is good .........................../

mazoul72
- 4th September 2011, 20:33
STUPID I AM , no pull-up resistors for RA2 and RA3....

Ioannis
- 4th September 2011, 20:43
Post #52 (http://www.picbasic.co.uk/forum/showthread.php?t=14258&p=106980#post106980)

Ioannis

mister_e
- 5th September 2011, 03:03
----===:D===----

http://www.your3dsource.com/images/headbangsoncomputer_t_01.gif

----===:D===----

mazoul72
- 6th September 2011, 10:43
Hello,

i tried with my car radio , it works well but a little slow for buttons reaction .
Perhaps the pause ...
I will try to integrate interrupts with it.
many thanks Steeve.

regards
Hervé

mister_e
- 6th September 2011, 21:27
Good news! The code itself should be fast enough, I guess the radio need some time to process it, and sure enough, it's not on his high priority task.

Post your code here, I'll check if I see something weird.

PS: when you post a code here use the code tags, this way it appear in a code box, and we don't miss the outdent format. It is really simple to do.


paste your code here

mazoul72
- 7th September 2011, 14:15
Steeve ,

do you know where is the values for other functions like up/down/valid (press 2 or 3 seconds on function button) / EQ/Display ?
I have all general functions under 100kohms .
it is for DEH-6900IP Pioneer .

Thanks.

mister_e
- 7th September 2011, 19:25
Nope, sorry. Their service manual makes no mention of it, and the only thing I found was something like,
http://www.jvde.net/pioneer_wired_remote/pioneer_wired_remote.htm

Even the original wired remote from Pioneer make no mention of this specific feature
http://www.pioneerelectronics.com/PUSA/Car/Accessories/Remote-Controls/CD-MR70

mazoul72
- 11th September 2011, 15:09
Do the diode zener serve to fix no Function if i have no +12V on input regulator ?
Because when i put off +12V , i have a loop function (again and again.....)

mister_e
- 14th September 2011, 04:30
You'll also need to disconect the GND line then. When you apply power to your PIC, the Hi-Z is granted on the output port, while not when you disconnect the power...

Byte_Butcher
- 16th September 2011, 03:03
Look again at the photo of the circuit board. That resistor near the top right is 39K ohms, NOT 3902 ohms!
Remember, the last digit is a MULTIPLIER. It tells how many zeros to add after the other digits.

mister_e
- 16th September 2011, 12:45
it's been said at post 59 ;)

Ioannis
- 17th September 2011, 11:45
it's been said at post 59 ;)

Too long to remember....:eek:

Ioannis

electron
- 20th September 2011, 18:27
How I can set (configure) ADCON1 register when I use 16F877A external Vref on RA2, RA3

mackrackit
- 20th September 2011, 19:39
Take a look at table 11-2 in the data sheet.
ADCON1 = %00001111
Sets the VREF pins and makes AN0 analog with the remainder digital.

Bits 6 an 7 will set for 8 or 10 bit resolution and FOSC/x

karlos
- 4th November 2011, 11:01
Hello to all
I'm new in this forum and there is no other way to tell this: i'm the most ignorant in terms of electronics.
My english also sucks, but i will try my best to communicate.
I have the same Mazoul72's issues. I have the same steering wheel remotes and want to build some interface PIC based to enable the buttons to work with my Kenwood DNX5260BT, but in the last months i have been looking for the kenwood values, but achieve to nothing and i'm so frustrated. It appears that Pioneer's communication protocol is the resistive type, but kenwood is via data and i don't know what to do.
Do you experts think that is possible to build one interface like the mazoul72 did and try to change the values in order to work with kenwood?
Or, what else can i do? I have a ir remote control that works with radio. This is a good think?

Thank you all
Karlos

mazoul72
- 5th November 2011, 13:27
Hello Karl ,
glad to see you in this forum .
I hope that you will find for this new type of Car radio steering wheel command's .
I had news and very usefull help from mister_e , i hope you will have these information .
Do you have a Line-K or Bus can wires behind your radio car ?
Perhaps , it is the best to access to all car radio commands ??

Regards.
Mazoul72

karlos
- 5th November 2011, 14:14
Hello Mazoul72
I think that you will be the one who can help me in this particulary issue. With all the respect for the experts of this great forum, but most of the users use so tecnical language that i don't understand. My formation is in philosophy...
Behind my radio i have the k line, althrought my car is not can bus. As far as i understand the communications protocol is 3LB.
Some months ago i've bought all the wiring for the multifunction steering wheel of the golf4, the relay 452 and the buttons (left and right). But i'm trying to make more buttons enable, because on the Golf4 MFSW there are only 4 buttons for control the radio and 3 buttons for cruise control. At least i would like to have six buttons to radio (volume up and volume down, next and previous track, next and previous source).
I'm very frustrated because it all remain the same and i have a gorgeous multifunction steering wheel without functions...
Perhaps you are kindness and maybe you could make one interface for me. If you want so, i can send you the money for the materias. I don't mind to take a change and i feel that i can trust you.

Regards
Karlos

mazoul72
- 5th November 2011, 14:47
I think it is more reliable to use Kline to access to all functions (i am going to try to use these adresses Kline functions)
i have a code but i have to work on it (Kline access based) .i will give a part of it in a new post to hope that someone can help us about it .
Because my FIS display base code is the same than Golfop...(take on a yahoo group FREELY and freely redistriable but now it is too expensive to buy it---lot of work on it) .
For try it , we have to use a little program to send caracters between DB25// and K-line .(see logs) 6112

mazoul72
- 5th November 2011, 15:49
EDIT :

See logs for what reacts FIS with sent caracters ... 6112

LineK schematics , but we need a program to send values to see how reacts car radio LineK wire ...
6113
code :

data(data line),clk(clock)
suma=0
dat=126
Shiftout data, clk, 5,[dat]
suma=suma ^ dat

Rem High data

dat=237
Shiftout dato, clk, 5,[dat]
suma=suma ^ dat

Rem Low data

dat=15
Shiftout dato, clk, 5,[dat]
suma=suma ^ dat

Rem High data
It is for DATA Line send (ENA/CLOCK/DATA)

For cont=0 To 15
tmp=msg[cont]
Rem dat=255 - tmp
dat= ~ tmp
suma=suma ^ dat
Shiftout data, clk, 5,[dat]
Rem Low data
Next cont

'Somme de controle (sum)

dat=suma + 1
Shiftout data, clk, 5,[dat]
Rem Low data
High ena
posy=255
GoSub display


FisDw:
Low ena
suma=0
dat=169
Shiftout data, clk, 5,[dat]
sum=sum ^ dat

know 255-longitude del msg

dat=241
Shiftout data, clk, 5,[dat]
sum=sum ^ dat

It is for example ,but it is a little part of sent values .

Thanks in advance to ameliorate or given answers .