Hallo, ich musste feststellen das das Rechnen eine richtig harte Nuss ist und könnte ein wenig Hilfe gebrauchen. Ich will die Luftfeuchtigkeit messen und den Wert dann anzeigen. Dazu lese ich die Spannung des Sensors über den TWI-Bus vom AD-Wandler (PCF8591) ein und schicke den Anzeigewert zum LED-Treiber SAA1064. kurze Info: der Sensor liefert eine Spannung von 0,8..4,0V = 1..100% Feuchte, daraus ergibt sich eine Nullpunktverschiebung von 0,8V und 0,032V je 1% Feuchte ein Beispiel: ich lese ein Byte mit dem Wert 163 - multipliziere mit 0,0196 und erhalte 3,2V (gerundet), entspricht der gemessenen Sensorspannung am AD-Wandler - subtrahiere 0,8V für die Nullpunktverschiebung und teile durch 0,032 dann erhalte ich 75% Feuchte. Diese zwei Zahlen muss ich als zwei Bytes an die Anzeige senden. Zahl 1: 7 = LED-Segmente: a, b, f = bitfolge: 00100011 = 0x23 Zahl 2: 5 = LED-Segmente: b, c, e, f, g = bit: 01110110 = 0x76 Ich krieg das alleine nicht gebacken. Wäre nicht schlecht wenn wir dieses Beispiel mal komplett durchrechnen könnten. Gruss Uwe
- Welcher Controller soll das tun? - Wie hoch ist die Auflösung des Signals vom Sensor? - Brauchst du den Zwischenwert in Volt? - Hast du an eine Lookup-Tabelle mit den Bitmustern gedacht?
meine 2ct (solange sich von den Cracks keiner rührt): in 16-bit-Ganzzahl: -41 *5 /2 (1mal rechts schieben) *125 /512 (1mal rechts schieben, high-byte) dual->BCD wandeln BCD->LED falls Atmel-AVR: falls tiny: MUL-Routinen siehe AVR200.asm oder AVR200B.asm dual->BCD: siehe AVR204.asm BCD->LED: selbst schreiben, Stelle für Stelle Die genannten Routinen gab es mal für die classics, sind hoffentlich noch bei Atmel zu finden. Oder Tabelle: 256 Bytes sollten reichen.
Hi, also sowas macht man am besten mit fixed-point arithmetik. Dein Wertebereich ist 0,8..4V, d.h. Du brauchst zwei Bit um die Vorkommazahl darzustellen. Das wiederrum läßt 14-bit für die Kommastellen einer 16bit Zahl übrig. Die Auflösung ist damit 1/2^14. Also: 0,032 = 525/2^14 0,8 = 13107/2^14 Wenn Du nun 3,2*0,8 berechnen musst (3,2=52429/2^14), gehtst Du wie folgt vor: Berechne 13107*52429*(2^14*2^14) und dividiere anschließend durch 2^14 (Das rechtsschieben sollte direkt in der Multiplikation erfolgen damit Du keinen Überlauf hast). Das sollte 41943(*2^14) ergeben. Das richtige Ergebniss ist damit: 41943/2^14 = 2,55... D.h. Du kannst mit ganzen Zahlen rechnen, hast am Ende aber doch eine Kommazahl vorliegen. Gruß Mario
Vielleicht gehts ja auch mit einer Tabelle, wo du für entsprechende Spannungen die %-Werte der Luftfeuchte ablegst. Es reicht ja eine Auflösung von 1-2%, dann reichen 50-100 Werte.
Warum so kompliziert ueber die Spannung rechnen. Letztendlich brauchst Du eine Umrechnung vom ADC-Wert zu Luftfeuchte. Bestimme die entsprechenden Konstanten und rechne direkt vom ADC-Wert zur Luftfeuchte um. (Nimm alles mal 10 und arbeite komplett in den ganzen Zahlen).
Hallo und dank für die Tipps, die Berechnung geht wirklich viel einfacher. (Byte vom ADC - 41) / 1,63 = %rF. Allerdings können die Bytes für die Anzeige nicht berechnet werden, die muss ich mit Hilfe einer Tabelle o.ä. zuweisen. Und da kam der Vorschlag das ganze gleich mit einer Tabelle zu machen. So werd ichs machen. Könnte aber noch mal Hilfe gebrauchen. Und B I T T E - - mit Beispiel wie ich das im Studio schreiben muss. Ich bin noch nicht so lange dabei! Also wenn ich z.B. vom AD-Wandler 165 (=76%) lese muss ich die Bytes 35 und 126 zur Anzeige schreiben und wenn ich 166 oder 167 (=77%) lese muss ich die Bytes 35 und 35 schreiben. Vielleicht kann man die Tabelle auch im Eeprom unterbringen, dass muss ich nämlich auch noch lernen. Gruss Uwe
Ich würde die Werte erstmal auf 0..99 skalieren (versuchen mit einer Zahl (Konstante) zu multiplizieren, so, dass beim Weglassen des/der unteren Bytes (Division durch 256 bzw. 65536) das obere Byte im gewünschten Bereich von 00..99 liegt. Dann die Zahl in BCD zerlegen und zu jeder Ziffer (0..9) mittels LookUp-Tabelle (über Z-Pointer und Flash) das Bitmuster holen und ausgeben. Schau mal in die Codesammlung, da gibt es glaube was mit Drehzahlmesser oder Tacho und 7-Segment-Anzeige. ...
Hallo, so weit, so gut, lassen wir mal das Rechnen beiseite. Ich glaub ich krieg das jetzt hin. Aber wie legt man so eine Lookup-Tabelle im Studio an? Ich konnte bisher nichts passendes finden, was mir weiter hilft. Und der erwähnte Drehzahlmesser ist mit Basic geschrieben. Vielleicht könnte mir jemand ein paar Code-Zeilen schreiben nur so als Beispiel. Gruss Uwe
> Aber wie legt man so eine Lookup-Tabelle im Studio an?
Man legt die Tabelle am Programmende an, indem man ein Label setzt und
danach mit der Direktive ".db" die Datenbytes anlegt.
tabelle1:
.db 0b11000000,0b11111001 ;0,1
.db 0b10100100,0b10110000 ;2,3
und so weiter, wobei 0 für ein leuchtendes Segment steht. Da müssen
also deine Bitmuster rein. Und darauf achten, dass immer eine
geradzahlige Anzahl Bytes in einer Zeile steht, da der Flash 16 Bit
breit adressiert ist.
Um darauf zuzugreifen, muss man zuerst den Z-Pointer auf den Anfang der
Tabelle setzen. Da das Lesen byteweise erfolgt, muss der Pointer auf den
doppelten Wert der Adresse gesetzt werden:
ldi zl,low(2*tabelle1) ;Low-Byte setzen,
ldi zh,high(2*tabelle1) ;High-Byte setzen
Nun wird zum Z-Pointer der Index addiert, damit er auf das gesuchte
Byte zeigt. Da hierbei ein Übertrag stattfinden kann, sollte es ein
Register mit dem Namen 'null' geben, dass 0 enthält.
add zl,zahl ;Zahl (Wert 0..9) addieren
adc zh,null ;Übertrag addieren
Der Z-Pointer zeigt nun auf das gesuchte Byte.
lpm ;liest den Inhalt der per Z-Pointer
;adressierten Zelle nach r0
Das gesuchte Bitmuster steht nun im Register r0.
out portb,r0 ;an Port ausgeben
...
Hallo, D A N K E genau das war es, was mir gefehlt hat. Ich liebe es wenn ein Programm funktioniert !!! Gruss Uwe
Zu früh gefreut... in der Simulation sah es gut aus, aber als ich es auf dem STK500 testen wollte, tat sich gar nix. Wäre vielleicht mal jemand so nett sich das anzugucken. Da ich es dokumentiert habe sollten die Funktion zu verstehen sein. War nur mal so ein Test - immer wenn ich eine Taste drücke soll die entsprechende Nummer angezeigt werden. Sollte mein erstes Programm sein was auch praktisch funktionieren sollte !!! Ist aber typisch -- nichts geht beim ersten Mal. Gruss Uwe
Hallo, Jungs und Mädels...seid ihr alle im Urlaub...lasst mich doch bitte nicht im Regen stehen !!! Die Sache ist folgende: der Eingang PortD tut was er soll Spannung 4,98V und wenn ich aufs Knöpfchen drücke geht er auf 0V. Aber der Ausgang PortB ärgert mich. Wenn ein Bit auf 1 gesetzt wird, dann erreicht die Spannung des Pins gerade mal 0,5 .. 1V. Im unbelasteten Zustand direkt am Pin gemessen. Meine 7-Segm-Anzeige hat eine gemeinsame Anode. Die Katode liegt über Vorwiderstand am Mega8. Bei Bit=0 soll das Segment leuchten. Habe ich den Port nicht richtig initialisiert, oder können es falsche Einstellungen am STK500 sein? Das Teil habe ich gebraucht gekauft und weiss nicht, ob mein Vorgänge irgendwelche Einstellungen verändert hat. Bitte gebt mir doch nen Tipp. Gruss Uwe
kann es sein das du portB als eingang konfiguriert hast und das was du misst nur die pullups sind???
Hallo... die beiden Ports habe ich folgendermassen konfiguriert: ; PortB auf Ausgang setzen ldi temp, 0xFF out DDRB, temp ; PortD auf Eingang setzen ldi temp, 0x00 out DDRD, temp ist meiner Meinung nach richtig so. Der Kontroller (Mega8) ist auch neu, dürfte also nicht kaputt sein. Kann mir keiner einen Tipp geben, warum der den Pegel bei "1" nicht auf 5V zieht? Gruss Uwe
Hast du auch am Eingang die internen PullUp-Widerstände eingeschaltet?
1 | ; PortD auf Eingang setzen |
2 | ldi temp, 0x00 |
3 | out DDRD, temp |
4 | ; PullUps an PortD einschalten |
5 | ldi temp, 255 |
6 | out PORTD,temp |
Wenn du das nicht tust, sind die Eingänge hochohmig... ...
hab ich gerade eben ausprobiert...keine Veränderung. Die Spannung der einzelnen Pins ist unterschiedlich, geht aber nicht über 1,2V bei Pin=1 und im unbelastetem Zustand. Ich bin am Verzweifeln ! Können es vielleicht noch irgendwelche "Fuse-Einstellungen" sein? Gruss Uwe
> geht aber nicht über 1,2V bei Pin=1 > und im unbelastetem Zustand. Was verstehst du unter Pin=1??? Das Register pind ist beim Mega8 ein reines Leseregister, da wird nix reingeschrieben. Beim Mega48/88/168 ist das anders, aber hier geht es wohl um den Mega8. Also: - in ddrx die Datenrichtung schreiben - in portx die Ausgänge schreiben bzw. PullUps schalten, wenn ddrx als Eingang geschaltet ist - aus pinx die extern angelegten Daten einlesen. ...
Hallo Uwe, ich habe mir erlaubt deinen Code etwas abzuändern. Ich denke, so sollte es gehen. Geänderter Code im Anhang. Es grüsst, Arno
Hallo... Arno danke für die Mühe, die du dir gemacht hast, hat aber nichts gebracht...selbes Resultat. Aber jetzt weiss ich, der Fehler liegt nicht im Programm. @...HanneS - richtig hier geht es um den Mega8 und mit "Pin=1" meine ich: wenn ich z.B. am Ausgang PortB 0b00000001 habe, dann sind die Pins1..7 = 0 also 0V und Pin0 = 1 also 5V. Die Spannung kommt aber nur auf max. 1,2V (ohne angeschlossene LED), was bedeutet, bei 5V sollten die LED's ausgehen da ich aber nur ca. 1V habe werden sie nur ein klein wenig dunkler - bei genauem Hinsehen. Vielleicht sollte ich mal PortC als Ausgang benutzen, um den Fehler weiter einzugrenzen? Kann man, mal abgesehen von der ext. Beschaltung, einen Port oder sogar den ganzen Kontroller durch falsche Programmierung o.ä. zerstören? Gruss Uwe
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.