ADC waarden niet constant

Alleen berichten met de trefwoorden “digitale voeding” worden getoond. Alle berichten tonen

Anoniem

Ik heb een projectje gestart om iets met een motorfader te doen. Op het moment loop ik tegen het probleem aan dat de waarden welke ik met de interne ADC van een PIC18F8722 niet echt constant zijn.

Ik lees op de loper van de fader een spanning tussen de 0 en 5v uit. Tussen de loper en ground heb ik een 100nF condensator gezet.

Het eerste probleem waar ik tegenaan loop is het bereik wat ik kan inlezen. Bij 4.6V heb ik de maximale digitale waarde al bereikt en ik krijg de digitale waarde nooit 0. Dit heeft waarschijnlijk te maken met de zeners die intern bij de ADC van de PIC zitten. Ik heb gemerkt dat ik dit kan oplossen door de Vref spanningen anders in te stellen. Door Vref- iets boven 0V en Vref+ iets onder 5V te leggen wordt het bereik van de digitale waarde van 0 tot maximaal. Nu komt het: Ik wil eigelijk geen gebruik maken 'aparte' Vref spanningen. Het is uiteindelijk de bedoeling dat het gaat draaien op een PIC welke geen mogelijkheid heeft om de Vref apart in te stellen. Ik ben totaal niet geweldig met analoge elektronica, vandaar de vraag of hier iemand een oplossing voor heeft :).

Het volgende punt is de waarde zelf. Van de 10 bits gebruik ik er maar 8. De analoge waarde schommelt niet veel (rond de 10mV) maar blijkbaar toch te veel om een constante digitale waarde op te leveren. Ik heb geprobeerd om met een circulaire buffer samples op te slaan en daar het gemiddelde van te nemen zonder de hoogste en laagste waarde mee te rekenen. Met 10 samples in de buffer rammelt de berekende waarde nog steeds met 1 op en neer. Berekening over 100 samples werkt, de digitale waarde rammelt niet. Echter bij het bewegen van de fader veranderd de digitale waarde niet met de zelfde snelheid mee omdat eerst de buffer compleet moet worden herschreven.

Het doel is dat de fader een constante waarde tussen 0 en 255 opleverd, zonder dat deze op en neer rammelt wanneer de fader stil staat. Heeft hier een goede oplossing voor (digitaal of analoog)?

Anoniem

Op 24 februari 2009 21:25:02 schreef JuuL:
- Meet je dezelfde spanningswisseling met een scope oid? Dan ligt het aan je hardware (en eventueel software).
- Gebruik je delays? Je moet wachten totdat je ADC klaar is met converten. Post je code eens.

Code posten is op het moment lastig aangezien ik in Oostenrijk zit en de code op mn pc thuis staat ;). Ik kon het niet laten rusten vandaar dat ik het nu al post :P.

Anyway met het inlezen van de ADC wacht ik totdat deze klaar is:

code:


ADCON0.GO=1;
while(ADCON0.GO);
//Rest van de code

Het zou dus best kunnen dat het aan de hardware-kant al fout gaat. Ik realiseer me ook net dat 10mV speling opzich al best veel is: 5V / 255 = 19mV. Hoe kan ik dit evt. stabieler krijgen? Of evt digitaal oplossen?

Op 24 februari 2009 21:41:07 schreef The Dutchman:
Ik heb dit bij een AVR al ondervonden. Deze heeft een AVCC welke ik was vergeten aan te sluiten . Misschien heeft een PIC ook zoiets ?
Grtz

Dat is in feitte de Vref. Deze kan via een aparte input (AVdd + AVSS) of via de Vref+ en Vref-. In mn print heb ik destijds de AVdd + AVss aan de voedingsspanning en ground gehangen (5V geschakelde voeding). Op de Vref+ en Vref- heb ik nu via een spanningsdeler wat andere waarden gezet (komt ook van dezelfde 5V voeding). Dit vanwege het 1'e probleem wat ik in de startpost heb beschreven.

[Bericht gewijzigd door Anoniem op 24 februari 2009 22:18:12 (28%)

Henry S.

Moderator

Dat moet zonder referenties en andere maatregelen prima lukken.

-Voeding van de uC wel 5V? Dit is standaard je referentie.
-Ingang van de ADC niet te hoog afgesloten? 10k max maar blijf liever rond de 2k7 mbv een buffer opamp.
-Hou je rekening met links of rechts uitlijnen van de ADC?
-ADC krijgt tijd om te herstellen?
-ADC timing correct?
-Voeding van fader stabiel?

Dit mag een digit varieeren, meer niet.

73's de PA2HS - ik ben een radiohead, De 2019 CO labvoeding.
Anoniem

Voeding uC is 5V. Fader is 10K, loper hangt rechtstreeks aan de ADC ingang. Voeding van de fader is de zelfde 5V. Hier zou ik misschien iets mee moeten proberen, aangezien dit een geschakelde voeding is.

Wat bedoel je met 'links of rechts uitlijnen'?

ADC krijgt voldoende tijd om te herstellen lijkt me. Na het inlezen wordt de waarde naar een LCD weggeschreven met wat int to string conversie's ertussen.

[Bericht gewijzigd door Henry S. op 24 februari 2009 22:41:31 (39%)

Henry S.

Moderator

Op 24 februari 2009 22:33:57 schreef M14:
Voeding van de fader is de zelfde 5V. Hier zou ik misschien iets mee moeten proberen, aangezien dit een geschakelde voeding is.

Zorg voor een schone voeding, en ik zet nu helemaal een vraagteken bij 5V.

Wat bedoel je met 'links of rechts uitlijnen'?

Zie datasheet, left/right allignment

BTW: Netter of niet quoten, anders beantwoorden.

73's de PA2HS - ik ben een radiohead, De 2019 CO labvoeding.

Als je een conversie doet, is dan ook echt alleen het ADC bezig. Of gebeuren er tegelijkertijd ook nog vanallerlei andere zaken.
Je kunt de processor in slaap mode zetten tijdens een adc-conversie. Iets van idle-adc oid. Kijk maar eens in de datasheets bij sleepmodes. Zeker een aanrader.

Ik heb er iig al eens profijt van gehad.

En verder is een idd een schone voeding belangrijk. Heb je de aanwijzingen uit de datasheet opgevolgd? GOED ontkoppeld, smoorspoeltje tussen VCC en AVCC, het is niet voor niets dat de ADC een eigen voedingspin cq eigen voeding heeft.

edit: ik zie dat je een geschakelde voeding gebruikt. Heb je een scoop zodat je de rimpel van je voeding kunt meten? In de datasheet staat vast wel ergens wat de max rimpel op je voeding mag zijn. Ik denk dat de combinatie van factoren de storing opleverd. Geen schone voeding, ontkoppeling.

|:( :( Ik zie nu dat het om een PIC-ding gaat, dacht dat het om een AVR ging. stom, stom totaal overheen gelezen. Neemt natuurlijk niet weg dat de voeding erg belangrijk is. Het beste kun je nu eerst die schakelende voeding het raam uitknikkeren en een linieare voeding nemen.

Maak me niet gek, ik ben al gek.
Arco

Special Member

Pic of Avr; een geschakelde voeding is niet geschikt als referentiespanning voor een AD converter. Zoals reeds gezegd, een RF spoeltje ertussen (varkensneusje o.i.d.) en een condensator.
Dat is trouwens zelfs met een lineaire voeding aan te raden...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Anoniem

Op 24 februari 2009 22:43:26 schreef Henry S.:

Zie datasheet, left/right allignment

Deze is '0'. Door alleen ADRESH uit te lezen heb ik als het goed is de 8 meest relevante bits.

Op 24 februari 2009 22:54:16 schreef Arco:
[...]
Datasheet adviseert max. 2K5...

Lezen blijkt weer eens een vak apart te zijn :), had het nog niet in de datasheet gezien. Henry had het over een buffer-opamp, hoe moet of kan dit er concreet uit zien.

Op 24 februari 2009 22:56:30 schreef WilToyo:
Het beste kun je nu eerst die schakelende voeding het raam uitknikkeren en een linieare voeding nemen.

Ik begrijp dat een stabiele voeding belangrijk is alleen wil ik eigelijk niet van die geschakelde voeding afstappen. Is op het moment ook vrij moeilijk omdat dat ding nu eenmaal op de print zit.

Zijn er andere manieren om die voedingsspanning stabieler te krijgen, bijv. door spoelen / condensators te gebruiken?

-----------------------
Hmz, helft is al beantwoord tijdens het typen van deze post :). In ieder geval allen bedankt, ik ga weer eens prutsen zodra ik thuis ben.

Op 24 februari 2009 23:22:49 schreef M14:Ik begrijp dat een stabiele voeding belangrijk is alleen wil ik eigelijk niet van die geschakelde voeding afstappen. Is op het moment ook vrij moeilijk omdat dat ding nu eenmaal op de print zit.

Zijn er andere manieren om die voedingsspanning stabieler te krijgen, bijv. door spoelen / condensators te gebruiken?

Kan, maar of je het helemaal schoon gaat krijgen? Blijven natuurlijk wel lapmiddelen. Goed ontkoppelen is de boodschap. Begin maar vast met een spoeltje (varkensneusje zoals Arco zei) van tussen de 10uH en 100uH. Liefst 100uH. Verder een C-tje tussen de referentie en GND van 100nF en tussen AVCC en GND.

Maak me niet gek, ik ben al gek.

Wat ook helpt, naast alle HW tips:

- software gemiddelde berekening (maakt het geheel wel trager, maar met een 'moving average' heb je alleen een opstart periode).
- Uitschieters weggooien. Je hebt een pool met gemeten waarden. Gooi de uitschieters weg en bepaal dan eventueel het gemiddelde.
- Soms (hangt af van type uC, lees datasheet), moet je nog een bepaalde tijd wachten na het selecteren van een ingang, voordat GO kan wordt gezet. (tijd heeft de Track and Hold nodig om te stabiliseren). Volgens mij gaat dit bij de nieuwere PIC's automatisch (??).

Je meetwaarde zal een stuk rustiger zijn.

(Ikzelf heb eigenlijk nooit meer dan jitter om één bit. In gebruik altijd 'gewoon' de +5V voeding als referentie voor de ADC.)

- Wel altijd de bandbreedte van je ingang zo laag mogelijkhouden. Ga je iets meter met een reactie tijd van een paar seconden, plaats dan een filter voor de ingang met de RC tijd van 10Hz ofzo. Doet ook wonderen.

- Als je ingangssignaal wat hoogfrequentere ruisbevat, dan helpt een 100nF condensator direct bij de PIC ook goed.

FullPower

De grootste moeilijkheden liggen daar waar we ze niet zoeken. [Goethe]
Anoniem

Nu ik weer terug ben heb ik weer het een en ander uitgeprobeerd en ben tot de conclusie gekomen dat een geschakelde voeding voor ADC-metingen geen succes is ;). Ik heb een lineaire 5V op zowel de potmeter als Vref- en Vref+ aangesloten, wat direct een veel beter resultaat gaf.

Ik zit momenteel nog met 1 probleem. De minimale waarde die ik meet is 7 en maximale waarde is 252 op een schaal van 0 tot en met 255. Vref- = 0V en Vref+ = 5V, zelfde voeding als op de fader. De uitgelezen waarden kloppen ook, de spanning op de loper bereikt nooit precies de minimale en maximale waarde. Het is uiteindelijk wel de bedoeling dat de uitgelezen waarde tussen 0 en 255 varieert.

Ik heb dit nu alsvolgt opgelost:

code:


ADC_uit = (ADC_uit - 7) * 1.041;
if(ADC_uit<0)ADC_uit=0;
else if(ADC_uit>255) ADC_uit=255;

ADC_uit is een signed int en bevat het gemiddelde van 10 samples. Van deze waarde haal ik de minimaal gemeten waarde af en vermenigvuldig ik het met 1.041. De if-statements zorgen dat de berekende waarde niet boven 255 of onder 0 komen mocht de ingelezen waarde toch onder 7 of boven 252 zitten.

Opzich werkt het, alleen vraag ik me af of hier betere oplossingen voor bestaan (analoog of digitaal). Is dit misschien op te lossen met een opampschakeling zoals Heenry eerder in dit topic postte? Deze heb ik overigens nog niet gemaakt, de electronica-zaak hier in de buurt heeft op maandag vrij :+.

Henry S.

Moderator

Met een nette uC voeding en interne ref heb je ook geen gedonder, netjes 0-1023 in mijn geval.

Maar de buffer is meestal wel nodig ivm met de aard van de ADC.

73's de PA2HS - ik ben een radiohead, De 2019 CO labvoeding.
free_electron

Silicon Member

float float float.. en wat is er mis met integer arithmetic ? maak een sliding window integrator. in machienetaal is dit mechanisme slechts een 10 tal instrcuties en gebruikt het een 20 tal cycli van de processor. plus een tiental byte ram. je merkt niet eens dat het er in zit.

code:


dim arry[8] as word
dim ptr as byte
dim total as word

function get_adc() as byte
   ptr = ptr+1
   if ptr = 8 then ptr=0
   arry[ptr] = adc_result
   total=0
   dim x
   for x = 0 to 7
    total = total +arry[x]
   next x
   total >> 3 ' schuif 'total' 3 bits naar rechts = delen door 8
   return lowbyte(total)
end function

zet zelf om in picbasic. bovenstaande de code is 'generic' basic

als je veel rotzooi moet wegfilteren kan je naar 16 gaan ( array 16 maken , de for next ook tot 15 laten lopen en de shift operatie met 4 bits in plaats van 3 bits doen.

analoge ingang affilteren. voedingslijnen naar PIC ook.
en de potmeter via een buffertrap op de A/D hangen. de ingang van een pic heeft geen oneindige impedantie en vormt een belasting voor de potmeter.
je kan eventueel nog een 'foefje' uithalen door de pic voeding iets lager te zetten dan de potmeter voeding : zet een shottky diode naar de pic toe. zo draait die op 4.6 volt en de potmeter kan tot 5 volt gaan.

het probleem is de referentie diode . jouw pic heeft er geen. en aangezien je niet aan de vref kunt... ( ik zou anders die omlaag halen met een halve volt )

Professioneel ElectronenTemmer - siliconvalleygarage.com - De voltooid verleden tijd van 'halfgeleider' is 'zand' ... US 8,032,693 / US 7,714,746 / US 7,355,303 / US 7,098,557 / US 6,762,632 / EP 1804159 - Real programmers write Hex into ROM
Anoniem

Op 3 maart 2009 01:36:00 schreef free_electron:
float float float.. en wat is er mis met integer arithmetic ? maak een sliding window integrator. in machienetaal is dit mechanisme slechts een 10 tal instrcuties en gebruikt het een 20 tal cycli van de processor. plus een tiental byte ram. je merkt niet eens dat het er in zit.

code:


dim arry[8] as word
dim ptr as byte
dim total as word

function get_adc() as byte
   ptr = ptr+1
   if ptr = 8 then ptr=0
   arry[ptr] = adc_result
   total=0
   dim x
   for x = 0 to 7
    total = total +arry[x]
   next x
   total >> 3 ' schuif 'total' 3 bits naar rechts = delen door 8
   return lowbyte(total)
end function

zet zelf om in picbasic. bovenstaande de code is 'generic' basic

als je veel rotzooi moet wegfilteren kan je naar 16 gaan ( array 16 maken , de for next ook tot 15 laten lopen en de shift operatie met 4 bits in plaats van 3 bits doen.

Hier doe je eigelijk niks anders dan een circulaire buffer vullen, daar het gemiddelde uit berekenen en vervolgens naar een byte omzetten. Mocht ik het fout hebben, laat het me weten, ik ben niet zo thuis in Basic. C FTW :+. Anyway, dit doe ik al :). Het enige punt waar ik de float gebruik is de berekening om het ingelezen bereik van 7 t/m 252 om te rekenen naar een bereik van 0 t/m 255. Hier word overigens een int vermenigvuldigd met een float (1.041) en weer weggeschreven als een int. Verder word er nergens met floats gewerkt.

analoge ingang affilteren. voedingslijnen naar PIC ook.
en de potmeter via een buffertrap op de A/D hangen. de ingang van een pic heeft geen oneindige impedantie en vormt een belasting voor de potmeter.

Dit ga ik met een beetje geluk vandaag testen.

je kan eventueel nog een 'foefje' uithalen door de pic voeding iets lager te zetten dan de potmeter voeding : zet een shottky diode naar de pic toe. zo draait die op 4.6 volt en de potmeter kan tot 5 volt gaan.

het probleem is de referentie diode . jouw pic heeft er geen. en aangezien je niet aan de vref kunt... ( ik zou anders die omlaag halen met een halve volt )

Opzich kan het, alleen gaat de fader ook niet helemaal naar 0 Ohm dus moet ik een dergelijke truck ook met de gnd uithalen. Dan wordt het wel een erg smerige oplossing denk ik ;).

Ik zou die voeding maar eens aanpakken. Dan heb je al die trucages niet nodig.
Ik heb in diverse projectjes verschillende picjes en potmeters toegepast, dat loopt altijd netjes van 0 tot 1023. Het kan hoogstens eens 1 stapje verschillen.

Even iets anders, de waarden die je nu hebt. Zijn dat gemiddelde waarden?

Zo ja, hoe ziet de data eruit als je niet middeld? Als die nog sterk fluctueren zou ik eerst zorgen dat, dat niet meer gebeurd.
Schone voeding en buffer tussen fader en ADC. Misschien kun je de fader ook nog wat ontdenderen. Klein c-tje van de loper naar de GND.

Maak me niet gek, ik ben al gek.
Anoniem

Dat is geen probleem meer, lineaire voeding is echt noodzakelijk :).

Damn, die 246 was voor een deling door 1.041. Voor een vermenigvuldiging moet je 256 * 1.041 ~= 266 hebben.

Dus vermenigvuldigen met 266, right-shiften met 8, dat geeft een vermenigvuldiging met 266 / 256 ~= 1.039

Met 32-bit registers (die je toch nodig gaat hebben, gezien je 10-bit ADC waarde) zou je op 65536 * 1.041 ~= 68223 uitkomen. Dat geeft een factor van 68223 / 65536 ~= 1.041

Je zou het trouwens ook nog met 16-bit registers kunnen doen, maar dan heb je maar 6 bits voor je vermenigvuldigingsfactor, waardoor de afwijking groter wordt.
64 * 1.041 ~= 67. factor is 67 / 64 ~= 1.047, dus die afwijking lijkt me wat te groot.

@FE: die bitwise AND op de pointer is redelijk standaard, maar dan moet je array lengte natuurlijk wel een macht van 2 zijn.

Ik heb ook nooit gezegd dat je de hele array weg kunt laten, maar dat je die niet steeds hoeft op te tellen. Dat loont wel als je lange array hebt, maar helaas kan dat niet meer met Gaussian of zelfs Chebyshev filters.

Overigens zou in dit geval een moving median filter naar mijn idee beter zijn dan een moving average, maar dan wordt het toch wel moeilijk om aan een hoop branch instructies te ontkomen.

EDIT: ja, digitale signaal bewerking was wel een van mijn favoriete vakken.

Een manager is iemand die denkt dat negen vrouwen in één maand een kind kunnen maken

Op 4 maart 2009 00:35:38 schreef M14:
Dat is geen probleem meer, lineaire voeding is echt noodzakelijk :).

Dat weet ik, maar hoe ziet je data eruit als je niet middeld? Die mag niet meer dan 1 bit fluctueren.

Maak me niet gek, ik ben al gek.