"voltmetr" s pic18 - prevod 10bit registru ADC

zdravim,
mam problem s rozchozenim “voltmetru” na PIC18F4520. Problem neni (alespon myslim) v nastaveni ADC, ale v samotnem algoritmu prepoctu z 10 bitove binarni hodnoty na skutecnou hodnotu napeti, kterou potrebuju zobrazit na LCD.

Zkousel jsem voltmetr od spruta
sprut.de/electronic/pic/prog … dclcd.html
prepsal jsem prikazy a vysledkem bylo zobrazeni 0-1022 s podivnou inkrementaci po 11 vzdy od 00.

Snazil jsem se odhalit chybu, tak jsem vzal jen ciste ten kod pro prepocet (tam jsem jeste nasel nejake “chyby”/asi rozdilny instrukcni set pro pic16xx a pic18xx), v debuggeru rucne nastavil do vstupnich registru napr ADRESH=0x00, ADRESL=0x01, ale ten prepocet nefunguje spravne.
Jde o Uadc*5/1024=Uout[mV]. Konkretne jde o to deleni. To v programu funguje jinak nez by melo, resp. nefunguje. Deleni 16bitoveho registru (f1 a f0) n^2 je provedeno rotaci o n bitu kazde jeho poloviny…??? Nemel by se spis posouvat cely 16 bitovy registr o n bitu vpravo? Ale to pak bude vysledek binarni cislo s desetinou carkou, nebo ne? :confused:

[code] s cz prekladem :slight_smile:
;*****************************************************
; Division durch 2 wird w-mal ausgeführt ;(deleni 2 se provede w-krat)
; die zu dividierende Zahl steht in xw ;(vydelene cislo bude v xw)
Div2
movwf counter ; Anzahl der Divisionen speichern ;(ulozi pocet deleni dvemi)
Div2a ; 16 bit xw:=xw/2
bcf STATUS, C ; carry löschen ;(smaze carry)
rrf xw1, f
rrf xw0, f

     decfsz  counter, f      ; fertig?				;(hotovo?)
     goto    Div2a           ; nein: noch mal		;(ne: jeste)
     return

;*****************************************************
[/code]
Nevim, jestli je ten projekt odzkouseny, treba to jen nechapu… jsem zacatecnik :slight_smile: Nicmene to potrebuju nejak vyresit.
Napadlo me, tabulkou pro 1024 hodnot:) (pro 00 00000001 -> v bcd 0005mV … 11 11111111 -> 4996mV), ale to je asi sileny.

Nebo jestli to jde spocitat v C a vysledek ulozit do registru? nikdy jsem ale v C neprogramoval a nevim, jestli je mozny nejak kombinovat v jednom projektu ASM i C. Komplet projekt z mam vicemene hotovej v asm. Do toho potrebuju nejak zakomponovat ten prepocet.

Nebo mate nekdo ten “voltmetr” (pripadne neco podobnyho) funkcni…?
Predem dekuju za pomoc a vysvetleni.

Mám postavený voltmetr s 18F4523 ten má 12bit A/D převod. Přepočet jsem vzal z těchto stránek, hledej “Voltmetr-Přepočítadlo”-
Vstupní napětí měřím 0 - 40V s rozlišením 0.01V.

doveda.byl.cz/

Petre diky,
ta stranka ale uz bohuzel moc nefunguje doveda.byl.cz/konstrukce/voltpr/index.htm
nenasel bys prosim nekde ty zdrojaky a reupnul to nekam, pripadne neposkutnul svoje? staci mi jen .asm jak to spravne prepocitat. nebo poradit, jak udelam v asm (nebo v C ktery do asm pridam) podprogram, kterej kdyz zavolam, tak udela se zakrouhlenim neco v tomhle smyslu.
f1 & f0 <= 4.8828125 * (ADRESH & ADRESL)
potrebuju aby to bylo presny maximalne (tz. tech cca 5mV na 0 - Vdd(5V))
dekuju

Na té stránce co jsem ti poslal je až dole ke ztažení tabulka přepočtu v Excelu. Do té dosadíš tebou naměřené hodnoty dle popisu a vyjde ti konstantní číslo které dosadíš do vzorce, kterým budeš přímo v podprogramu počítat napětí. Záleží na nastavení vstupního rozsahu napětí které bude u tebe jiné, proto můj zdroják ti bude k ničemu, používám jinou konstantu a 12bit převod.

Popiš trochu víc, jak velké napětí chceš měřit, s jakou přesností, v jakém časovém intervalu atd.

na tabulku jsem koukal, ale zda se mi nejaka prilis komplikovana
potrebuju merit 0-5V. Napajeci napeti (5V) mam nastaveny jako referenci. AD prevodnik mi podle toho vyhodi vysledek v 10bitech 0x0000 - 0x03FF (0000-1023). Tz konstanta je 0.0048828125 (5/1024). resp 4.8828125.

Rychle to byt moc nemusi (radove stovky ms by mely byt ok), presnost potrebuju maximalni, aby se mi pri 0x0001 zobrazilo 0005mV

Tak když budeš registr ADRESH a ADRESL násobit 5ti, tak by to mělo vyjít, ne ?

no, to by sice slo :slight_smile: jenze ja potrebuju nasobit 4.8828125…

da se to nejak snadno udelat v C? vzit hodnotu z registru, vynasobit touhle konstantou, zaokrouhlit nebo useknout desetiny mista a zase nacpat do registru? teda jenom zavolat rutinu, ktera bude v C napsana, z asm…? hledam na netu a zatim jsem nevypatral, jak na to. zda se mi to nejsnazsi reseni, …pokud by to tak teda slo.

Mě se to dnes taky nechtělo načítat; jen bych doplnil k tomu odkazu, že autor této konstrukce má stránky jinde, na “Dovedovi” je to jen převzato.

Když budeš násobit 5ti a poslední nulu zahodíš, tak máš výsledek s přesností na jednu setinu 0.01V, to by ti mělo stačit.
Jinak program pro přesnější výpočet se dá samozřejmě napsat.

To není moc profesionální ztrácet přesnost výpočtem, který lze zpočítat přesně, ono už jen samotné měření, je zatíženo značnou chybou… už když jenom koukám, že používá jako referenci napájecí napětí s chybou minimálně ±3% a těžko definovatelným kolísáním jeho hodnoty.
Takže bych zaokrouhlil konstantu podle požadované přesnosti výpočtu, ale minimálně na 2 desetinné místa, tj. 4.88, vynásobil 100, tj. 488, a tímto číslem násobil výsledek AD převodu, výsledek výpočtu musí být samozřejmě uložen minimálně v typu short long, poslední dvě dekadické číslice tohoto výsledku budou desetina a setina výsledku…
Samozřejmě je to také možné řešit pomocí typu float z matematické knihovny, ale myslím, že zbytečné při takto málo náročných výpočtech, určitě by to bylo výpočetně a paměťově náročnější.

A jsme zase u toho, konstanta vychází z předpokladu, že napájecí napětí a tím i referenční bude přesně 5V, jinak bude zase nepřesný výsledek.

To máš pravdu, ale pokud spočítáš nepřesně výsledek, bude výsledná nejistota měření ještě větší…

Proto jsem navrhnul přepočítadlo ze stránek dovedy, ale to se mu zdá složité.

Na to není potřeba žádné přepočítadlo, postup, který jsem popsal, je hodně jednoduchý.

Vyresil jsem to myslim hned druhej den. V pripade, ze by nekdo potreboval, zdrojak ze sprut.de - misto subrutiny Div2 ma byt kod (nize). Mozna je to vidlacky napsany, ale funguje to.
Je potreba odecitat posunutej 16b registr 8+8bitu o 6 a pak o 7 bitu. Od spruta to bylo napsany s “rrf” pro kazdej registr, coz vyhodi jako vysledek nesmysl.
Ale diky za komentare a rady.

Div2
		clrf	xw1
		clrf	xw0

		;f1       f0
		;00011111 11111111 ->
		;xw1      xw0
		;00000000 01111111		

		btfsc	f1,4	
		bsf		xw0,6	
		btfsc	f1,3
		bsf		xw0,5
		btfsc	f1,2
		bsf		xw0,4
		btfsc	f1,1	
		bsf		xw0,3	
		btfsc	f1,0	
		bsf		xw0,2	
		btfsc	f0,7
		bsf		xw0,1
		btfsc	f0,6
		bsf		xw0,0
		
		call	Sub16	; 16 bit f:=f-xw 
		
		;f:=f-xw/128
		;xw1      xw0
		;00011111 11111111 ->
		;xw1      xw0
		;00000000 00111111

		rrncf	xw0		;xw0 posun jeste o 1 
		bcf		xw0,7	;a bit 7 vynuluj (kdby se nahodou presunula '1' z bitu 0
		
		call	Sub16	; 16 bit f:=f-xw 

	return			; fertig