So ich habs geschafft und den MCP3422 (Microchip's 18-Bit ADC) am I2C-Bus zum laufen gebracht; betrieben wird er im 16Bit-Modus. Problem: Der Chip hat eine interne Referenzspg. von 2.048V; diese entsprechen 0111111111111111 = 2^15-1 Wie wandle ich das in Dezimal um? Hat jemand da einen guten Trick zur Hand? Der Fakto wäre ja 2.48/32767, aber wie macht man das möglichst elegant? Auf sprut.de habe ich gefunden: X / 1,024 = X - X/64 - X/128 (http://www.sprut.de/electronic/pic/programm/adclcd/adclcd.html) Wie kommt man auf solche Tricks bzw. wie findet man solche Ersetzungen von Divisionen?
2048mV Referenz, 32768 Counts? Vorkommaanteil in mV bekommst du sehr easy durch Shiften:
Also um 3 nach Links schieben. Den Nachkommaanteil der mV eben als 500µV, 250µV und 125µV separat aus den 3 "weggeshifteten" Bits des AD berechnen und hintenan hängen. Dazu die geshifteten Vorkommastellen in mV mit 1000(schnelle Multiplikation mit 1000(*)) multiplizieren und 500, 250 oder 125 je nach gesetzten Bits dazuaddieren. Dann in der Anzeige an entsprechender Stelle das Komma hardcoden oder so. mfg mf PS: 1000 * x = ( (32 * x - x) * 32 ) + 8 * x weil 1000 = ( 31 * 32 ) + 8
kent schrieb: > betrieben wird er im 16Bit-Modus. > > Problem: Der Chip hat eine interne Referenzspg. von 2.048V; diese > entsprechen > 0111111111111111 = 2^15-1 Warum nicht 2^16 ??
Die eigentliche Frage ist ja gewesen: kent schrieb: > wie findet man solche Ersetzungen > von Divisionen? Ersatz von Zehnerpotenzen durch eine möglichst kurze Addition von Zweierpotenzen. Darüberhinaus hat man dir mit Referenz = 2,048V versucht, das Leben leichtzumachen. Nur ein bisschen Bitfummelei ist nötig. 10 = 8 + 2 100 = 64 + 32 + 4 1000 = 1024 - 8 - 16 = (wie bereits gesagt) 10000 = 8192 + 2048 - 256 + 16 usw. mfg mf
Matthias Laubnitz schrieb: > kent schrieb: >> betrieben wird er im 16Bit-Modus. >> >> Problem: Der Chip hat eine interne Referenzspg. von 2.048V; diese >> entsprechen >> 0111111111111111 = 2^15-1 > > Warum nicht 2^16 ?? Weil es im 2er-Komplement ist; der Chip hat differenzielle Eingänge und kann auch negative Eingangsspannungen.
kent schrieb: > Weil es im 2er-Komplement ist; Dann eben auf "MSB Gesetzt" prüfen. Wenn gesetzt, dann Zweierkomplement der Zahl bilden und das "Minus" in einer Flagvariable speichern. Weiter wie bereits besprochen^^. Dann kannst du lustig Shiften und es zerhaut dir nicht gleich deine ganze Zahl. Oder du bindest eine Mathematiklibrary ein und rechnest in float. Sofern du in C programmierst und Rechenzeit keine Rolle spielt. Sonst kann ich dir echt nur Festkommaarithmetik empfehlen. Oder hat dein Proz eine Fließkommaeinheit? mfg mf
Mini Float schrieb: > kent schrieb: >> Weil es im 2er-Komplement ist; > > Dann eben auf "MSB Gesetzt" prüfen. Wenn gesetzt, dann Zweierkomplement > der Zahl bilden und das "Minus" in einer Flagvariable speichern. Weiter > wie bereits besprochen^^. > > Dann kannst du lustig Shiften und es zerhaut dir nicht gleich deine > ganze Zahl. Oder du bindest eine Mathematiklibrary ein und rechnest in > float. Sofern du in C programmierst und Rechenzeit keine Rolle spielt. > > Sonst kann ich dir echt nur Festkommaarithmetik empfehlen. Oder hat dein > Proz eine Fließkommaeinheit? > > mfg mf Nein es wird nur ein billiger PIC16F628 verwendet; alles in Software (I2C und 16-Bit Arithmetik).
Benutz aber einen genug "longen" Datentyp, sonst wird das mit dem schnellen Multiplizieren usw. nichts. mf
der PIC kann nur 8-Bit Rechnungen, ich nehm normalerweise 2 Register um 16-Bit rechnen zu können. Muss mal überlegen ob ich damit hinkomme wenn ich Multi/Div. in einer sinnvollen Reihenfolge mache... jetzt gehts erstmal in die Heia ;) Gruß, kent
So ich hab mir jetzt mal was überlegt :) Aalso... gemessen werden Spannungen von 0...15V. Diese kann man mit einem Spannungsteiler auf die max. Eingangsspannung des ADC von 2.048V runterteilen (Faktor 2.048/15). Der ADC macht daraus einen binären Wert von 0..2^15-1 (Faktor 2^15-1/2.048). Ich würde jetzt im PIC den Wert mit 15000/2^15 malnehmen um dezimale Zehntelmilivolt rauszubekommen. 10.000/2^15 = (2^13 + 2^11 + 2^4 - 2^8) / 2^15 = 2^-2 + 2^-4 + 2^-11 - 2^-7 Also angewendet auf das binäre Ergebnis e des ADC: e>>2 + e>>4 + e>>11 - e>>7 Jetzt habe ich das beispielhaft mal für ein paar Werte durchgerechnet, und leider kamen da ziemliche Abweichungen bei raus. Eine Eingangsspg. von 15V ergibt einen Wert von 149970 (ist ok). Eine EIngangsspg. von 0.1234V ergibt einen Wert von 0.1275 (nicht ok). Frage: Woher kommt dieser Fehler? Ich denke mal durch das Rechtsschieben verliert man ja definitiv Genauigkeit (Information geht verloren). Müsste man das irgendwie binär runden? Außerdem wird durch 2^15 geteilt obwohl der max. Wert des ADC bei 2^15-1 liegt. Irgendein Vorschlag wie man es verbessern kann? Eine Verwendung von float scheidet leider aus; hatte gestern versucht die float-Bibliothek von Microchip einzubinden und die passt nicht mehr in den Controller :( Die Integer-Bibliothek würde wohl noch reinpassen. Ist da eine bessere Genauigkeit zu erwarten als bei der Bitshift-Methode? Danke schonmal für Vorschläge & schönen Sa. -Kent
Du machst dir das Leben leichter, wenn du den Eingangsspannungsbereich auf 16,384 V festlegst, auch wenn das die Auflösung minimal reduziert.
Klar, wenn du einfach rechtsschiebst, fallen hinten Bits runter. "Tip" hat die für dich optimale Lösung für dein "wie bekomme ichs in den Controller". Dein Threadtitel fragt aber eigentlich nach was anderem. Runden, wie wir es gewohnt sind, geht indem du die Hälfte der neuen niederwertigsten Stelle vor dem Abschneiden/Rechtsshift dazuzählst. mfg mf PS: kent schrieb: > (Faktor 2.048/15) Nach allem was wir dir erzählt haben is das nicht dein Ernst oder?
Da brauche ich das ergebnis ja nur einmal nach rechts schieben... genial, danke!
Und um die 16,384V auf 2,048V abzubilden, muss vorher Analog durch 8 geteilt werden. Da würde ich dir ein Widerstandsnetzwerk 10x 10k empfehlen. mfg mf
> Wie kommt man auf solche Tricks bzw. wie findet man solche > Ersetzungen von Divisionen? Indem man die Binärdarstellung der beteiligten Zahlen unter die Lupe nimmt und darüber meditiert, was dies eigentlich bedeutet. Ich würde schon den Spannungsbereich voll ausnutzen. Dein Maximalwert bei 15,000V ist 32767, Du willst also 32767 nach 15000 umrechnen: um 1 Bit nach rechts schieben --> 16383 um 4 weiter nach rechts schieben --> 1023 subtrahieren = 15360 um 2 weiter nach rechts schieben --> 255 subtrahieren = 15105 um 2 weiter nach rechts schieben --> 63 subtrahieren = 15042 um 1 weiter nach rechts schieben --> 31 subtrahieren = 15010 um 2 weiter nach rechts schieben --> 7 subtrahieren = 15003 um 1 weiter nach rechts schieben --> 3 subtranieren = 15000 oder um 1 Bit nach rechts schieben --> 16383 um 4 weiter nach rechts schieben --> 1023 subtrahieren = 15360 um 1 weiter nach rechts schieben --> 511 subtrahieren = 14848 um 2 weiter nach rechts schieben --> 127 addieren = 14975 um 2 weiter nach rechts schieben --> 31 addieren = 15006 um 2 weiter nach rechts schieben --> 7 subtrahieren = 14999 um 2 weiter nach rechts schieben --> 1 addieren = 15000 bei ausreichend genauem Ergebnis kann man schon eher abbrechen, z.B. nach der 4. Zeile. Eine weiter Möglichkeit ist eine erweiterte Multiplikation: und anschließendes Kürzen mit 2^17: 32767 * 60000 = 1966020000 / 131072 = 14999,542236328125 32767 * 60003 = 1966118301 / 131072 = 15000,292213439941 Das Kürzen um 2^17 ist einfach: Du nimmst das Upper-Word des Mult-Ergebnisses und schiebst es um eins nach rechts. Wenn Du runden willst, merkst Du dir das bit0 der Mult und addierst es zum Ergebnis. Dieses Vorgehen hat den Vorteil, dass 60003 der Kalibrierfaktor ist. Stimmt Dein Spannungsteiler nicht exakt, kannst Du das mit diesem Faktor kompensieren. Auch eine Temperaturkompensation ist damit möglich, z.B. mit LookUp-Table. Eine schnelle 32x32-->64-Bit Mult findest Du z.B. hier: Beitrag "Re: Rechnen mit AVR" Weiter unten auch in AVR-asm.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.