Hoi,

Na een maand zelf testen en zoeken werkt er al een groot stuk van een programma, alleen blijft er 1 struikel blok het berekenen van het aantal pulsen.
Daarmee roep ik jullie hulp in, ik denk dat ik voledig verkeerd aan het denken ben hoe het te berekenen.

Hier onder probeer ik uit teleggen hoe ik alles zie.

Ik heb het volgende probleem, ik zou een 16 Bit waarde moeten berekenen.
Met zo een klein mogelijke afwijking.

De formule die ik ga gebruiken is de volgende
(Teller (16bit) / 255)*waarde = het aantal pulsen(16bit).

Maar nu zit ik de handen in het haar om dit in ASM te verwezenlijken.
IK had al een opzet gemaakt maar dit heeft een veel te grote afwijking.
(Eerste idee dat werkt maar te grote afwijking geeft)

De teller is opgesplitst in 2 stukken TellerL TellerH
In tellerH komen de vollen tellerL ( als tellerL vol is gaat deze een bit setten in tellerH dit heb ik werkend)

Nu dacht ik dit is al het eerste stuk van de formule
Bv tellerH zit 9 dus moesten we alleen tellerH * waarde = en we hadden het aantal pulsen.

Maar dit geeft een grote afwijking, zoals volgend voorbeeld: stel er staat in tellerH 9 en in tellerL 250 dit is bijna 1 byte, maar als ik alleen ga rekenen met tellerH dan krijg een afwijking van 250 bitjes en dat scheelt een hoop pulsen bij de eindafrekening.

Hoe kan ik dit adequaat oplossen?

Als er nog onduidelijkheden instaan, dan hoor ik wel.

Alvast bedankt

Eerst de vermenigvuldiging doen, en dan pas delen door 255.

Is waarde een 8 of 16 bit getal?

Doe het net als je op de basisschool geleerd hebt:

antw=TelL*waarde+TelH*waarde*256

En daar pak je dan de eerste byte van.

Waarde is een 8 bit getal

Alleen teller en aantalpulsen is 16 BIT

Hoe kan ik het beste vermenigvuldigen, voor de kleinste afwijking?

bij tellerL eerst 128 optellen, dan kun je daarna tellerH * waarde doen. dan heb je hem afgerond.
(0 - 127) + 128 < 256
(128 - 255) + 128 >= 256

afhankelijk van je toepassing kan gewoon het 7e bit checken sneleler zijn (7e bit zegt: 128 of hoger):

if (tellerL & 0x80) then tellerH++;
tellerH * waarde

[Bericht gewijzigd door Martijn Berntsen op (36%)]

ik snap je niet helemaal denk ik

Stel er staat 200 in tellerL.
Dan tel je er 128 bij dan zit je aan 328 dus 1 byte en 72 bits.

je telt in tellerH 1 bij op en dan tel bij de 72 nog eens 128 bij of ben ik verkeerd?

Misschien een rare vraag, maar in welke programmeertaal doe je het?

als je een 16 bits optel functie hebt (bijvoorbeeld adiw in geval van avr), dan kun je gewoon zeggen teller + 128, en als je dan alleen tellerH gebruikt, heb je iets gemaakt wat teller / 256 doet, met afronden.

maar checken of je tellerL een bepaalde waarde bereikt heeft is denk ik in jouw geval makkelijker, dus hoger dan X, dan tellerH + 1.

overigens, ik ging uit van teller / 256, moet dit precies 255 zijn? want dan moet je toch echt een routine maken die kijkt hoevaak hij teller met 255 kan verlagen, en dan naar de rest kijken voor het afronden.

(ps: 1 byte = 8 bits, je spreekt niet van 1 byte en 72 bits)

@Daan

om dit in ASM te verwezenlijken.

;-)
Groeten, Bram

ik dacht zo een routine te maken

een lus met de vermenigvuldiging in
dus teller met 6 vermenigvuldigen(= maal)

zou ik dan zo doen

lus:
tel bij resultaat de teller op
trek 1 af van maal
goto lus:
maal 0 ; dan is alles berekent

men taal is ASM

moet je door 255 delen, of bedoel je 256? 256 is easy, 255, dan moet je inderdaad een lus maken, en dan op basis van de rest afronden.

kijk ik zal je het principe uitleggen wat het moet doen

op een ketting zit een encoder op, deze geeft dus pulsen af als de ketting beweegd.

Nu heb ik een register dat ik analoog in lees (heb ik werkend) van 8 bit. dit zal ik waarde noemen.

Nu heb ik voor het opstarten de ketting van helemaal boven tot helemaal beneden laten lopen en dit geeft BV 2000 pulsen.

Nu moet ik te pulsen berekenen die ik moet maken als ik bv een ander getal in waarde stop.

Een voorbeeld:
pulsen = 2000
waarde = 20

hoeveel pulsen moet ik doen :

2000*20/255 = 156.86 pulsen
Dat is het principe

snap je men andwoord?

mijn vraag is dan, waar komt de 255 weg? is dit een waarde die je berekend hebt en afhankelijk is van je hardware? of wat?

als 255 goed is, dan (zoals jij deels voorstelde):

een lus om te bepalen hovaak 255 in 'teller' past,
dan kijken of de rest (wat je over hebt) hoger is dan 255/2, om af te ronden (hoger = afronden naar boven, lager = naar beneden)

als die 255 ook een getal mag zijn wat een macht van 2 is (256, 128, 64, enzovoort) dan kun je de deling doen door te bitshiften, of door het hele laagste byte (tellerL) te laten vallen. en daarna af te ronden.

[Bericht gewijzigd door Martijn Berntsen op (65%)]

de 255 komt van de resolutie van men analoge ingang

ik kan regelen tussen 0 en 255 dus moet dit toch mee verrekent worden

Op 29 oktober 2008 14:38:09 schreef nonkel_dw:
de 255 komt van de resolutie van men analoge ingang

ik kan regelen tussen 0 en 255 dus moet dit toch mee verrekent worden

0 t/m 255 = 256 stapjes, dus dan deel je door een macht van 2, en ook nog eens precies 1 byte, dus mijn advies:

pseudo asm:

als (tellerL < 128) goto next;
tellerH = tellerH + 1
next:
aantal_pulsen = tellerH * waarde

dat is afronden:

dus als je wilt afronden op eenheden:
waarde + (eenheid / 2), en dan het deel achter de komma weglaten, dus:

5.3 afronden geeft 5, want: 5.3 + 0.5 = 5.8, dan het deel achter de komma weglaten, en dan krijg je 5, dat klopt
5.5 afronden geeft 6, want: 5.5 + 0.5 = 6.0, dan het deel achter de komma weglaten, en dan krijg je 6, voila

dat doe ik ook met die digitale variant:

tellerH = deel voor de komma
tellerL = deel achter de komma

voorbeeld:

//1380 / 256 = 5.39
1380 geeft:
tellerH = 5
tellerL = 100
//5.39 + 0.5 = 5.89, deel achter de komma weg = 5
halve eenheid van een byte is 128
tellerL + 128 = 228 (byte is niet hoger dan 255, dus tellerH blijft gelijk)
en deel achter de komma weglaten (tellerL weg) geeft 5

overigens was de methode van (Z)weetvoetje beter, omdat je dan geen nauwkerigheid verliest.
teller = 1380
waarde = 210
pulsen = 1380 / 256 * 210 = 1132.03
als je eerst deelt krijg je 5, dan keer 210 doet, krijg je 1050, wat dus een afwijking oplevert.
als je eerst vermenigvuldigd krijg je 1380 * 210 = 289800, als je dat deelt door 256 krijg je 1132

dus mijn verhaal is leuk over afronden, en als je geen 24 bits getallen wilt gebruiken, maar niet nauwkeurig!

ja ik snap wat je wil zeggen

maar dan heb je nog altijd maar een waarde van 1 byte.
Terwijl het voor een word moet gedaan worden.
Zoals het er al eerder stond.

sorry, was mijn bericht aan het uitbreiden (=slechte eigenschap) heb er wat aan toegevoegd.

ja oke

dan moet ik zoals zweetvoetje zegt zien op te lossen.
Dit gaat nog niet zo simpel zijn denk ik

jazeker wel, supersimpel:

'tellerH * waarde' levert resultaat1H + resultaat1L
'tellerL * waarde' levert resultaat2H + resultaat2L

dan heb je 2 keer een 16 bits getal, dan zeg je:

byte0 = resultaat2L
byte1 = resultaat2H + resultaat1L
byte2 = resultaat1H + (eventueel teveel in byte1)

[bad habit edit mode]
overigens werken veel assembler commando's met carry bits, deze bewaren het 9e bit als je bijvoorbeeld 200 + 200 doet, dan krijg je een getal wat niet meer in 1 byte past, en dan bevat het carrybit (C) je 9e bit. Als je dan daarna weer het optelcommando gebruikt, dan neemt hij dit bit mee, voorbeeld volgens bovenstaande tekst:

resultaat2L = 200
resultaat2H = 150
resultaat1L = 130
resultaat1H = 250

byte0 = 200
byte1 = 150 + 130 = 260 = 4 + carrybit
byte2 = 250 + carrybit = 251

[/bad habit edit mode]

[Bericht gewijzigd door Martijn Berntsen op (48%)]

Nu heb ik wat gevonden alleen zit er nog een fout in :(
Als ik dit simuleer met pic simultor




	list	P=16F628a
	#INCLUDE <P16F628a.INC>
	__CONFIG    _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC


CBLOCK 0X20		
 TELLER
 PULS 
 PULSH 
 TELLER2
 TELLER2H
PP0 
PP0H
PP1
PP1H 
PP2 
PP2H
PP3 
PP3H 
PP6H 
ENDC                 

	ORG	00h
	GOTO	init	;Initialize PIC
;-------------------------------------------

 init
	movlw	d'200'
	movwf	TELLER
	movlw	d'100'
	movwf	PULSH
	movwf	PULS
; teller 2 staat de uitkomt teller2L teller2h
        goto MAIN

MAIN

	Clrf PP3H
	Movf TELLER,W
	Movwf PP3
	Movf PULSH,W
	Movwf PP1H
	Movf PULS,W
	Movwf PP1
	Call m@py
	Movwf TELLER2
	Movf PP2H,W
	Movwf TELLER2H

	Movf TELLER2H,W
	Movwf PP0H
	Movf TELLER2,W
	Movwf PP0
	Clrf PP1H
	Movlw d'255'
	Movwf PP1
	Call d@vd
	Movwf TELLER2
	Movf PP0H,W
	Movwf TELLER2H

	Goto MAIN




d@vd clrf PP2H
	clrf PP2

d@vd2 movlw 16
	movwf PP3
	rlf PP0H,w
	rlf PP2,f
	rlf PP2H,f
	movfw PP1
	subwf PP2,f
	movfw PP1H
	skpc
	incfsz PP1H,w
	subwf PP2H,f
	skpnc
	goto $ + 8
	movfw PP1
	addwf PP2,f
	movfw PP1H
	skpnc
	incfsz PP1H,w
	addwf PP2H,f
	clrc
	rlf PP0,f
	rlf PP0H,f
	decfsz PP3,f
	goto $ - 21
	movfw PP0
	goto i@nt

m@py movlw 16
	movwf PP6H
	clrf PP0H
	clrf PP0
	rrf PP3H,f
	rrf PP3,f
	skpc
	goto $ + 7
	movfw PP1
	addwf PP0,f
	movfw PP1H
	skpnc
	incfsz PP1H,w
	addwf PP0H,f
	rrf PP0H,f
	rrf PP0,f
	rrf PP2H,f
	rrf PP2,f
	decfsz PP6H,f
	goto $ - 15
	movfw PP2
	goto i@nt
i@nt bcf 3,7
i@nt2 bcf 3,5
	bcf 3,6
	nop
	return


	END

Wil iemand hier even mee op kijken?


i@nt bcf 3,7
i@nt2 bcf 3,5
	bcf 3,6
	nop
	return

dit stukje is me voorlopig ook nog een raadsel voor wat dit mag zijn.

Als je een grotere nauwkeurigheid wil ontkom je er niet aan met meer bits te gaan werken.

Dus moet er een 16x8 multiply worden gedaan.
Hiervoor kun je zo een kant en klare subroutine plukken van www.piclist.com
Je krijgt dan een 24 bits getal als uitkomst.

Om het geheel te kunnen begrijpen: Wat heeft de analoge ingang met het verhaal te maken? De puls-counter op de ketting is zo te zien digitaal?

een potensiometer

waar ik de de byt waarde kan mee instellen

dit moet latere met wat extra code de takel omhoog en omlaag sturen.
maar eerst het rekenwerk werkende krijgen

Ah,

Dat is al een stuk duidelijker...
Je wilt dus dat de potmeterstand <min> gelijk is aan '0', en <max> gelijk is aan 2000...
Over dit probleem hebben we het geloof ik al eerder over gehad. Als je de A/D converter zo instelt, dat het aantal pulsen er door deelbaar is, wordt alles veel simpeler en nauwkeuriger.
Als de ketting totaal 2000 pulsen geeft, dan A/D op max. 500 of 1000 zetten.
Je hoeft dan alleen de A/D waarde met 2 of 4 te vermenigvuldigen. (Kan het nog simpeler? :) )