Hallo Leute
Ich habe versucht einen Tacho mit Kilometerzähler zu bauen.
Als Prozessor kommt ein 8515 mit 2*16 LCD zum Einsatz. Über Tasten wird
der Umfang der Reifen eingegeben und Trip kann zurückgesetzt werden. Die
aktuellen Daten werden bei Power off gespeichert. Ich habe noch einen
kleinen Fehler drin, den ich aber nicht herausbekomme. Vielleicht hat
jemand einen Rat?? Je höher die Geschwindigkeit, desto mehr "springt"
die Anzeige.
(z.B. zwischen 118 und 122 km/h). Versuche auch ein DOGS 102*64. Klappt
aber noch nicht. (Naja fange auch erst mit Mikroproz an....)
In welchem C Dialekt ist das geschrieben ?
Ich sehe LCD Ausgaben und Berechnungen in den ISR, sowie ein
delay_ms(1000);. Jedes delay blockiert dein Programm in seiner
Ausführung und es kann nicht mehr auf ext. Ereignisse reagieren.
Vom Systemher würde ich alle ISR so kurz als möglich machen und per
Event Flag (1Bit) dem Hauptprogramm (main) das Ereignis mitteilen.
Dann kann man dort in aller Ruhe reagieren.
In der Main kann über eine Zustandsmachine, der serieller Prozess
abgebildet werden, ohne dass man auf ext. Ereignisse Interrupt
verzichtet und dass man überhaupt noch ein delay in der main() benötigt
!
TASTER müssen entprellt werden, sonst erzeugen sie dir viele Interrupts
bei schließen und öffnen des Selben.
_
Hi Uwe Sorry war noch die ältere ( zuviel Klammern). Erstellt wurde das
mit Codevision. Die LCD Ausgabe und der Delay beim INT1 habe ich
deswegen so gemacht, weil dies eh nur im Stand und beim Ausschalten der
Zündung vorkommen sollte. Das mit den Tasten hast du Recht, wobei ich
Trip und DIAMETER Key ja deswegen auf 500 ms bzw 1000ms gedrückt halten
gemacht habe, um ein versehentliche drücken zu unterdrücken. Deine Info
mit übergeben der Parameter und rechnen im Main muss ich mal sehen, wie
ich das umsetzte.
Bin halt Anfänger..... :-)) Danke Dir auf alle Fälle für die Infos.
Gruss Peter
Mir fällt auch gerade auf, das ich dies eigentlich bei Codesammlung
posten wollte. Ich glaub dann schliessen wir das hier und ich mach einen
Neuen im Bereich Codesammlung auf.... Vielleicht kann ein Admin den auch
verschieben ? :-))
Peter R. schrieb:> Mir fällt auch gerade auf, das ich dies eigentlich bei Codesammlung> posten wollte.
Ist denn das was du da postest, FERTIGER code, von den andere Nutzen
ziehen könnten? Dann ist er bei "Codesammlung" gut aufgehoben.
Code-Leichen, und Codesegmente, welche mal funktionierender Code werden
wollen, haben in der Codesammlung nichts verloren.
> Ich glaub dann schliessen wir das hier und ich mach einen> Neuen im Bereich Codesammlung auf....
Welchen Sinn und nutzen sollte es machen, hier einen Thread zuzumachen,
um dort einen identischen Tread aufzumachen? Außer den geneigten Leser
mit auseinander driftenden Threads zu nerven oder zu verwirren, fällt
mir kein weiterer Zweck ein, den Thread nochmal neu irgendwo aufzumachen
> Vielleicht kann ein Admin den auch verschieben ? :-))
Ja, nämlich dann wenn es funktionsfähiger "vorführbarer" Code ist (siehe
oben). Ok, nach offtopic oder /dev/nulll kann auch nicht
funktionsfähiger Code rein ;-)
Wie verhalten sich Variable, wenn Sie per ISR verändert werden und in
anderen Programmteilen auch angefasst werden?
Unter avr gcc gibt es "volatile" zur Beschreibung dieses Sachverhaltes.
Uwe S. schrieb:> Hallo,>> mindestens ein Problem wurde nicht gelösst.>> Hier wird mit 8Bit gerechnet
Es wird schon 16 Bit gerechnet. Das ist erst mal bis zum Beweis des
Gegenteils kein Problem.
(circ/PULSE_TURN)*SPEED_MULTIPLIER
.. ist natürlich eine Rechenreihenfolge, die durch die vorgezogene
Division dazu prädestiniert ist, Genauigkeit zu verschenken.
23 / 5 * 8
ergibt nun mal 32, wohingegen
23 * 8 / 5
eine 36 ergibt. Das exakte Ergebnis wäre 36.8
Ich würde mir auch mal den 'count' ausgeben lassen um zu sehen in
welchem Zahlenbereich sich die ganze Sache hier bewegt. Und dann mal ein
wenig mit dem Taschenrechner die Berechnungen kontrollieren wobei man
die speziellen Gegebenheiten der int-Rechnerei ins Kalkül ziehen muss.
> Wie verhalten sich Variable, wenn Sie per ISR verändert werden und in> anderen Programmteilen auch angefasst werden?> Unter avr gcc gibt es "volatile" zur Beschreibung dieses Sachverhaltes.
Volatile ist eine Sache. Obwohl ich nicht denke, dass der Compiler hier
großartig die Zugriffe wegoptimieren kann. Was aber natürlich im Raum
steht, ist der atomare Zugriff auf speed. (bzw. eben der nicht atomare
Zugriff)
Hallo Karl-Heinz,
wie war das mit der Definition von |circ|:
1
unsignedcharcirc;
somit wird die Division als 8 Bit durchgeführt, das Ergebnis ist auch 8
Bit.
Natürlich stimmt dein Beispiel, und ich ziehe auch erst die
Multiplikationen vor die Division, solange ich keine Datentyp Überlauf
erhalten.
_
Uwe S. schrieb:> Hallo Karl-Heinz,>> wie war das mit der Definition von |circ|:
1
unsignedcharcirc;
> somit wird die Division als 8 Bit durchgeführt, das Ergebnis ist auch 8> Bit.
C Regeln.
Gerechnet wird nicht kleiner als int.
Es sei denn der Compiler kann beweisen, dass sich das Ergebnis nicht
ändert, wenn er anstelle einer vollständigen int Berechnung nur ein
8-Bit Anteil berücksichtigt. Bei dem Beweis wird er sich hier aber
schwer tun.
Und natürlich: Es sei denn der Compiler weicht hier vom C-Standard ab.
Aber selbst dann greifen hier die beiden Begründungen nicht
#define PULSE_TURN 12
.... circ/PULSE_TURN
12 ist ein int. Damit wird hier unsigned char durch int dividiert. Und
damit als int Division ausgeführt. Du musst immer die Datentypen beider
Operanden berücksichtigen. Auch numerische Konstanten haben einen
Datentyp.
UUPS so eine folgenschwere Diskusion wollte ich gar nicht auslösen.
Ich habe nochmal mit dem Code experimentiert.
Der jetzige Code funktioniert am besten......... ich habe alle möglichen
Variationen probiert. Das Dingen zeigt bis etwa 150 Hz ca. 90Km/h ohne
Probleme an. Aber danach "springt" die Anzeige um ca 3-4 Km/h.
Ich glaube fast, es liegt an der Geschwindigkeit des Timer1.
Die Kilometer als solches werden auf alle Fälle richtig.
hosentraeger schrieb:> und ein> delay_ms(1000);>> in einer Interrupt Routine wuerde ich auch> nicht unbedingt haben wollen...
Wenn du nach siehst, ist diese Routine NUR für den Fall von Power Off
zum "sicheren" Speichern der Daten und nichts anderes. D.H. du stellst
dein Auto ab und machst es aus.
Karl Heinz Buchegger schrieb:> Ich würde mir auch mal den 'count' ausgeben lassen um zu sehen in> welchem Zahlenbereich sich die ganze Sache hier bewegt. Und dann mal ein> wenig mit dem Taschenrechner die Berechnungen kontrollieren wobei man> die speziellen Gegebenheiten der int-Rechnerei ins Kalkül ziehen muss.
Hallo Karl-Heinz. Wie gesagt, bin ich Mikro-Proz- und Programier-
Anfänger.
Wenn du mir einen Tipp geben könntest, wie ich das am besten ausgeben
lassen kann??
Achso an Uwe:
Geschrieben mithilfe des Codewizzard und Compiliert von/mit Codevision.
Freewareversion. (Ich weiß es gibt besseres aber ich fange erst an. :-))
)
Und bitte mich nicht steinigen.
Peter R. schrieb:> Wenn du mir einen Tipp geben könntest, wie ich das am besten ausgeben> lassen kann??
Ähm.
Du hast eine Anzeige, auf der du momentan deine km/h ausgibst.
Da wird sich doch noch ein Eckerl finden, auf dem du den count ausgeben
lassen kannst.
Karl Heinz Buchegger schrieb:> Ähm.> Du hast eine Anzeige, auf der du momentan deine km/h ausgibst.> Da wird sich doch noch ein Eckerl finden, auf dem du den count ausgeben> lassen kannst.
Äh wie war das mit dem Wald und den Bäumen. ich werde einfach die untere
Zeile nehmen und dort vorrübergehend Trip und ODO ersetzen, dann habe
ich vielleicht auch einen Vergleich zur aktuellen Speed. Wird aber
wahrscheinlich erst am WE etwas.
Gruss Peter
An Karl-Heinz und Uwe:
Sakrischen Dank für die Denkanstöße.
Es funktioniert einwandfrei. Hab den Timer auf 125kHZ eingestellt und
(Uwe ich bin lernfähig....) bei dem Interrupt1 soweit möglich alles
raus.
Hab nach anweisung von Karl-Heinz mal alle "wichtigen" Parameter der
Reihe nach aufs Display geschrieben und dann mit Rechner und Papier
weitergemacht.
Was jetzt natürlich toll wäre: Ich hab hier ein 102*64 LCD, aber ich
hab, zumindest im Moment, keine Peilung wie ich das hier reinkriege.
Vielleicht kann mich ja jemand freundlicherweise tatkräftig
unterstützen.
An den Admin: Nun könntest du das in Codesammlung verschieben :-))
Peter R. schrieb:> Hab nach anweisung von Karl-Heinz mal alle "wichtigen" Parameter der> Reihe nach aufs Display geschrieben und dann mit Rechner und Papier> weitergemacht.
Machs nicht so spannend.
Und?
Hat es dich weiter gebracht, wo in deiner Programm-Berechnung der Hund
sitzt?
> An den Admin: Nun könntest du das in Codesammlung verschieben :-))
Immer langsam mit den jungen Pferden :-)
Das hier
> timer=overflow*65536+count;
solltest du auf jeden Fall mit einer DEI/SEI Klammerung versehen.
Während diese Berechnung läuft, darf dir auf keinen Fall ein Interrupt
dazwischenfunken. Sonst stammen count und overflow nicht mehr aus
derselben Messung.
Das mit dem lcd_clear() ist so eine Sache.
Eigentlich willst du genau das nämlich nicht tun, weil sonst dein
Display flackert. Wenn immer möglich, willst du eigentlich auf dem LCD
nur über bestehenden Text drübermalen.
Wenn du aber schon lcd_clear benutzt, dann schieb es so dicht wie
möglich an die eigentliche Ausgabe ran. Zwischen deinem clear und dem
tatsächlichem Neubeschreiben hast du Berechnungen, noch dazu in Floating
Point. Die kosten Zeit. Zeit in der das LCD ... leer ist, ehe es neu
beschrieben wird. Und das siehst du dann auch als kurzen Flackerer.
Aber eigentlich solltest du dein Schirmbild möglichst statisch machen.
Es macht nicht viel Sinn, in jedem Durchlauf durch die Hauptschleife zb
den Text "km/h" wieder neu hinzuschreiben, wenn er ohnehin schon am LCD
steht (und nur deswegen hingeschrieben werden muss, weil du vorher das
LCD komplett gelöscht hast)
Karl Heinz Buchegger schrieb:> Es macht nicht viel Sinn, in jedem Durchlauf durch die Hauptschleife zb> den Text "km/h" wieder neu hinzuschreiben
MMhh, wenn ich den LCD_Clear aber rausmache (Nur einmal beim Start),
habe ich plötzlich (je nach Geschwindigkeit) mehrere Zahlen, da die
Geschwindikeit ja vorne anfängt und 2 bis (im Moment durch kommastelle)
4 stellig ist. Deswegen dachte ich ja daran, das Display durch
dispint>2000 zu "verzögern".
Peter R. schrieb:> MMhh, wenn ich den LCD_Clear aber rausmache (Nur einmal beim Start),> habe ich plötzlich (je nach Geschwindigkeit) mehrere Zahlen, da die> Geschwindikeit ja vorne anfängt und 2 bis (im Moment durch kommastelle)> 4 stellig ist.
Ein Tip:
Es ist der Lestauglichkeit extrem zuträglich, wenn auf einer Anzeige die
Einerstelle immer an derselben Position auftaucht!
D.h. deine Ausgabe sollte nicht sein
+---------------------------+
| Geschwindikeit: 78.5 km/h |
+---------------------------+
| Geschwindikeit: 9 km/h |
sondern die Einzelteile haben fixe Positionen (die Einer sind immer an
der gleichen Stelle)
+---------------------------+
| Geschwindikeit: 78.5 km/h |
+---------------------------+
| Geschwindikeit: 9.0 km/h |
Das heißt: es genügt wenn du die nicht benutzten Positionen, an der
sonst nicht gezeigte führende 0-en stehen, mit Leerzeichen übermalst. Du
kannst auch den Zahlenbereich als ganzes vor der Ausgabe der Zahl erst
mal mit Leerzeichen komplett übermalen und so frei bekommen. Aber
eleganter ist natürlich wenn du nur soviele Leerzeichen vor der Zahl
ausgibst, dass die Einerstelle wieder an dieselbe Position kommt. Und
das ist ja bei einem Tacho nicht so schwer. Schneller als 999.9 km/h
wirst du ja selten fahren. D.h. es kann nur maximal 2 unterdrückte
führende 0-en geben.
Gerade bei Dingen, auf die man nur kurz draufsehen kann, ist es enorm
wichtig, dass am LCD dieselben Dinge immer an derselben Position
auftauchen ohne dass man mit dem AUge lange suchen muss. Wenn deine
Anzeige bei Zwischenwerten ständig zwischen 9.9 und 10.0 hin und
herspringt und jedesmal der Dezimalpunkt da links/rechts rutscht, dann
wird dir dein Benutzer in kurzer Zeit an die Gurgel springen.
Äusserst überzeugendes Argument.....
Hab auch mal
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F
angeschaut, aber irgendwie steh ich da auf dem Schlauch. Vielleicht
brauch ich auch erst mal ein paar Tage....
Oder du könntest mir ein Beispiel geben. Wenn ich es richtig gelesen
hab, wäre sprint auch nicht gerade die Wahl für mein vorhaben.
Peter R. schrieb:> Äusserst überzeugendes Argument.....> Hab auch mal> http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F> angeschaut, aber irgendwie steh ich da auf dem Schlauch. Vielleicht> brauch ich auch erst mal ein paar Tage....> Oder du könntest mir ein Beispiel geben. Wenn ich es richtig gelesen> hab, wäre sprint auch nicht gerade die Wahl für mein vorhaben.
Würd ich so nicht sagen.
Solange du deine Ausgabegeschwindigkeit sowieso drosseln musst (und das
musst du, denn mehr als 3 bis 5 Updates in der Sekunde kann sowieso kein
Mensch verarbeiten) UND du den Speicher hast, spricht nichts dagegen
sprintf zu benutzen. Für nicht verbrauchten Flash kriegst du kein Geld
zurück.
Karl Heinz Buchegger schrieb:>> Würd ich so nicht sagen.> Solange du deine Ausgabegeschwindigkeit sowieso drosseln musst (und das> musst du, denn mehr als 3 bis 5 Updates in der Sekunde kann sowieso kein> Mensch verarbeiten) UND du den Speicher hast, spricht nichts dagegen> sprintf zu benutzen. Für nicht verbrauchten Flash kriegst du kein Geld> zurück.
Hallo Karl-Heinz. Nach langer Ruhepause noch eine Frage. Ich habe
sprintf genommen. Was ich aber im Moment nicht ganz verstehe ist
folgendes:
ich springe mit lcd_gotoxy(0,0); doch 1te Zeile ganz links??? mit dem
nachfolgenden Befehl sprintf((g_temp)," %3s", tempstr);
lcd_puts(g_temp);
bleibt aber immer die erste Stelle frei, soll heißen, die Null der Km
steht
immer an 4ter Stelle. Genauso wie Trip.???
Ansonsten bin ich bis jetzt "stolz" auf mich, dass ich soweit mit eurer
hilfe gekommen bin.
Gruss Peter
Peter R. schrieb:> Karl Heinz Buchegger schrieb:> bleibt aber immer die erste Stelle frei, soll heißen, die Null der Km> steht> immer an 4ter Stelle. Genauso wie Trip.???
Hier steht
sprintf((g_temp)," %3s", tempstr);
****
* Als erstes soll in den Ausgabestring ein Leerzeichen eingefügt werden.
* Danach soll ein String ausgegeben werden, ...
* Wobei dieser String in ein (gedachtes) Ausgabefeld der Breite 3
eingepasst werden soll
* Wie bei allen anderen Ausgaben, gilt für printf: Wenn der
tatsächlich auszugebende Wert NICHT in die im Formatstring
angegebene Feldbreite hineinpasst, sondern zu klein ist, dann wird
die Ausgabe rechtsbündig in das Feld gestellt und links mit
Füllzeichen aufgefüllt. Im Falle eines Strings sind das nun
mal Leerzeichen.
In Summe führt das dazu, dass
* In der Zeile auf jeden Fall erst mal 1 Leerzeichen ausgegeben wird.
* Ein String "0" in einem Feld der Länge 3, dann eben als " 0" erzeugt
wird
* Und damit kommt die 0 an die Cursorposition 4 zu liegen.
Wenn du sowieso nur am Vorkommaanteil interessiert bist, ist es ein
bischen von hinten durch die Brust ins Auge, wenn du vorher mittels ftoa
dir einen String erzeugen lässt und dann den String mittels sprintf in
ein Feld einpassen lässt
1
ftoa(speed,0,tempstr);
2
lcd_gotoxy(0,0);
3
sprintf((g_temp)," %3s",tempstr);
4
lcd_puts(g_temp);
so, ist es wesentlich einfacher
1
sprintf(g_temp," %3d",(int)speed);
2
lcd_gotoxy(0,0);
3
lcd_puts(g_temp);
(Im Grund ist es auch dann einfacher, wenn du Nachkommastellen haben
willst
Karl-Heinz du bist mir unheimlich. Keine 6 Minuten und du Antwortest.
Vielen Dank für den Tip. Hab ihn schon verwirklicht. Bin gerade dabei
noch RPM
"rein zu bauen".
Danke Dir Sakrisch.
Schönen Abend.
Gruss Peter