hallo,
ich verstehe es mal wieder nicht.
an dieser Stelle -
lcd_int4(adc_read()); // <== hier mehrere ADC-Auslesungen angezeigt
- werden mehrere Messungen angezeigt und überschrieben. D.h. die
Funktion 'lcd_int4' wird nur einmal ausgeführt da sonst hintereinander
geschrieben würde - aber der Wert wird mehrfach angezeigt.
Wie kann das sein? Was mache ich falsch?
1
voidmain(void)
2
//
3
{
4
5
clock_prescale_set(clock_div_2);//8mhz
6
7
init_timer_smh();
8
led1_init;
9
10
//usart_init;
11
//USART0_init(9600);
12
//relais_init;
13
i2c_init();
14
lcd_init();
15
adc_init();
16
17
lcd_clear(RED);
18
lcd_int4(adc_read());// <== hier eine ADC-Auslesung
Deine Anfrage ist unklar formuliert. Gebe mal Beispiele der fehlerhaften
Ausgabe und was du srattdessen erreichen willst.
Korrektes Einrücken hilft ungemein, den Quelltext zu verstehen.
Wo sind die Quelltexte von lcd_int4() und adc_read()? Ich will sie
sehen, nicht nur anhand des Namens erraten, was sie tun sollten.
Nemopuk schrieb:> Wo sind die Quelltexte von lcd_int4() und adc_read()? Ich will sie> sehen, nicht nur anhand des Namens erraten, was sie tun sollten.
pardon gehören natürlich dazu:
1
voidadc_init()
2
{
3
// Set the ADC reference to AVcc
4
ADMUX=(1<<REFS0);
5
6
// Enable ADC and set prescaler to 128 (16 MHz / 128 = 125 kHz)
Es ist zwar nicht dein Hauptproblem, ich wollte es aber trotzdem zeigen:
Deine Funktion lcd_int4() gibt positive Zahlen mit bis zu 4 Stellen aus.
Negative Zahlen mit mehr als 3 Stellen führen zu einer fehlerhaften
Ausgabe:
Der Test
if(sec==3&&min%6==0){//alle sechs Minuten auslesen
54
55
if(min==0)//jede Stunde -------
56
{
57
// nichts?
58
}
59
60
//wr_read_reg();
61
//sub_regelung();
62
}
63
64
if(sec%5==1){
65
66
u8i=0;
67
lcd_goto(10+i++,1);
68
69
lcd_int4(i);// <== hier 1mal angezeigt
70
lcd_int4(adc_read());// <== hier mehrere ADC-Auslesungen angezeigt
71
}
72
73
}//while
74
75
}//main
Und auf den problematischen Teil reduziert:
1
voidmain(void){
2
3
while(1){
4
5
if(timer_smh>99){
6
sec=sec++;
7
timer_smh=0;
8
}
9
10
if(sec%5==1){
11
12
u8i=0;
13
lcd_goto(10+i++,1);
14
15
lcd_int4(i);// <== hier 1mal angezeigt
16
lcd_int4(adc_read());// <== hier mehrere ADC-Auslesungen angezeigt
17
}
18
19
}//while
20
21
}//main
Hier fallen mir folgende Dinge auf:
Ist timer_smh als "volatile" und 8 Bit Integer deklariert? Wenn nicht,
können Lesezugriffe im Hauptprogramm durch Schreibzugriffe in der
Timer-ISR gestört werden und zu unerwartetem Verhalten führen.
Allerdings nicht zu dem konkreten Verhalten, dass wir hier sehen. Dafür
muss es noch einen anderen Grund geben.
> lcd_goto(10 + i++
ergibt immer 10, weil i immer 0 ist.
> lcd_int4(i);
gibt immer 1 aus, weil i immer 1 ist.
> lcd_int4(adc_read());
Gibt mit Sicherheit nur eine ADC Messung aus. Denn etwas anderes kann
diese Funtkion nicht tun.
Offenbar kommt die Ausgabe " 1 813" von diesen beiden Aufrufen.
Die unerwarte Ausgabe in der dritten Display-Zeile stimmt nicht mit dem
Quellcode überein. Denn er enthält kein "lcd_goto(3,1)". Sie kann auch
nicht von "lcd_int4()" kommen, weil diese Funktion immer 4 Ziffern
rehtsbündig ausgibt.
Vermutlich ist der Fehler ganz woanders, in einem Stück Code, den du
nicht gezeigt hast. Ich würde mal alle andere Display-Ausgaben
auskommentieren um auszuschließen, dass sie stören.
Nemopuk schrieb:> Die unerwarte Ausgabe in der dritten Display-Zeile stimmt nicht mit dem> Quellcode überein.
stimmt - "lcd_goto(3,1)" hab ich nachträglich eingefügt weil es in der
ersten Zeile sonst blöd aussieht.
lcd_goto(10 + i++
ergibt immer 10, weil i immer 0 ist.
stimmt auch, habe die Deklaration nach oben gezogen. Ergebnis bleibt.
Stelle wird nur einmal aufgerufen.
Nemopuk schrieb:> Negative Zahlen mit mehr als 3 Stellen führen zu einer fehlerhaften> Ausgabe:
Das ist bewusst in kauf genommen. Die Funktion dient zur Positionierung
auf dem Display. Wenn größere negative Werte zu erwarten sind muss man
das anders machen.
Nemopuk schrieb:> Allerdings nicht zu dem konkreten Verhalten, dass wir hier sehen. Dafür> muss es noch einen anderen Grund geben.
Jedenfalls Dank für dein Bemühen. Es hilft schon weiter zu wissen, dass
mein Unverständnis nicht ganz unberechtigt ist.
Karl K. schrieb:> stimmt - "lcd_goto(3,1)" hab ich nachträglich eingefügt> stimmt auch, habe die Deklaration nach oben gezogen
Wenn du hilfreiche Hilfe bekommen willst, solltest du deine Probleme
ordentlich beschreiben. Wenn man sich Mühe gibt, erkennt man die Ursache
beim verfassen der Problembeschreibung sogar oft selbst.
> Ergebnis bleibt. Stelle wird nur einmal aufgerufen.
Damit kann ich nichts anfangen. Ist das jetzt eine gute oder eine
schlechte Nachricht?
Nochmal von vorne: Zeige den kompletten Quelltext (ordentlich
formatiert!), die dazugehörige Ausgabe, und was du stattdessen
erwartest.
Nemopuk schrieb:> Nochmal von vorne: Zeige den kompletten Quelltext (ordentlich> formatiert!), die dazugehörige Ausgabe, und was du stattdessen> erwartest.
ich werde den code noch mal komplett neu aufsetzen und dann hier
einstellen.
Das Merkwürdige ist, dass die Messwerte überschrieben werden obwohl die
Cursorposition bei lcd_write eigentlich mit jedem Wert fortgeschrieben
wird:
Karl K. schrieb:> ich werde den code noch mal komplett neu aufsetzen und dann hier> einstellen.
Aber dann bitte als Dateianhang, nicht im Posting selbst.
Problem gelöst:
lcd_goto(1,7);//
lcd_int2(sec);//
// led1_tog;
} <===
//------------------------------------------------
Die Klammer gehört nach unten damit die Schleife nur einmal je Sekunde
durchlaufen wird. Eigentlich ganz einfach.
Außerdem erklärt das nicht, wieso Ausgaben fälschlicherweise in Zeile 3
landen. lcd_goto(1, 7) geht ja nach Zeile 1.
Zeige mal den vorher/nachher Vergleich mit etwas mehr Kontext. Gerne
auch als zwei komplette Dateien (vorher.c, nachher.c) im Anhang.
Nemopuk schrieb:> falsche Ausgabe in Zeile 3
oben:
Nemopuk schrieb:
> Die unerwarte Ausgabe in der dritten Display-Zeile stimmt nicht mit dem> Quellcode überein.
stimmt - "lcd_goto(3,1)" hab ich nachträglich eingefügt weil es in der
ersten Zeile sonst blöd aussieht.
Nochmals Dank für deine kritischen Nachfragen. Man denkt darüber nach
und das hilft weiter. So z.B. neue Anzeige-Funktion mit Komma:
Ich hätte noch mehr zu sagen....
Was heißt dum, und warum dum?
Wieso ist dum kein C String, obwohl es doch ganz offenbar einer sein
soll?
Karl K. schrieb:> x=x*-1
OK, nicht wichtig, aber warum nicht so: x=-x;
oder:
x=x%100; zu x%=100;
Karl K. schrieb:> i16
Was ist das, und vor allen Dingen, warum ist das?
Für mich wäre an der Stelle der Punkt gekommen, wo ich über sprintf oder
seine Brüder nachgedacht hätte, auch wenn es 2k Flash kostet.
Harald K. schrieb:> Findest Du diese Quelltextformatierung in irgendeiner Weise lesbar?
Er wartet noch darauf, dass endlich ein Werkzeug wie ›astyle‹ erfunden
wird. Und ein Editor welcher automagisch tabs in spaces umwandelt.
;-)
Arduino F. schrieb:> Für mich wäre an der Stelle der Punkt gekommen, wo ich über sprintf oder> seine Brüder nachgedacht hätte, auch wenn es 2k Flash kostet.
Sehe ich auch so, bei 32kB ist doch reichlich Platz.
Zu Zeiten des AT90S2313 oder AT90S4433 hatte ich das auch noch zu Fuß
gemacht.
Peter D. schrieb:> Sehe ich auch so, bei 32kB ist doch reichlich Platz.
Warum einfach wenn's umständlich auch geht. Ich schätze mal dass
der TO von der Existenz von sprintf noch nichts gehört hatte.
Arduino F. schrieb:> Die Funktion ist kaputt!
Wenn man es schon nicht schafft vernünftige, aussagekräftige
Namen für Funktionen und Variablen zu finden dann kann's auch
mit deren Inhalten schwierig werden, um es mal vorsichtig
auszudrücken .... ja, und die Formatierung, ein Graus ....
Wastl schrieb:> TO von der Existenz von sprintf
gehört schon - gebraucht noch nicht.
Das schöne an diesem Forum - man wird zwar moralisch niedergemacht -
aber man lernt noch was.
Karl K. schrieb:> man wird zwar moralisch niedergemacht
Immerhin wirst du hier nicht beschimpft, sondern es werden
sachlich die "Probleme" (und es sind mehrere) angesprochen.
Karl K. schrieb:> aber man lernt noch was
Das bleibt zu hoffen. Wir haben hier aber auch schon jede Menge
beratungsresistente Leute gesehen.
Karl K. schrieb:> gehört schon - gebraucht noch nicht.
Wenn du mal im Detail beschreibst was deine Funktion am LCD
machen soll (ich kann es nicht, will es auch nicht verstehen)
dann könnte man (jemand hier im Forum) dir mit ein paar
"Pinselstrichen" eine vernünftige Funktion mit der Anwendung
von sprintf(...) schreiben.
Ich nehme an dass du das nicht alleine schaffst, denn schon
der Titel deines Threads hat nichts mit dem zu tun was du
wirklich an Problemen hast. Jedenfalls hat das alles (zuerst
mal) nichts mit dem ADC zu tun.
Peter D. schrieb:> #include <stdio.h>> #include <stdint.h>> void lcd_int4(int16_t val)> {> char s[] = "Err ";> if ( val >= -999 && val <= 9999 )> sprintf(s, "%4d", val);> lcd_write(s);> }
Schlechter Stil. Bei sowas kann man sich bei C immer wieder leicht in
den Fuß schießen. Entweder die Einzelanweisung hinter if() in der
gleichen Zeile oder IMMER mit Klammern!
Falk B. schrieb:> Schlechter Stil.
Ja schon gut, du hast ja Recht. Aber es passiert ja im Fall
der Fälle nix Schlimmes. Höchstens etwas was man nicht erwartet.
Falk B. schrieb:> Und wozu soll ein Komma bei Integerzahlen> gut sein?
Sorry ich hab noch nie mit Fließkomma gearbeitet und habe das auch im
Prinzip nie gebraucht. Der ADC liefert bei 10bit 0-1023.
Spannungsmessung Genauigkeit ist 0,1 Volt.
Die Darstellung auf dem lcd muss formatiert sein - sonst sieht es blöd
aus. Also immer 4Stellen für eine Zahl.
Die Funktion lcd_int_10() kann auf 4Stellen also Werte von
+9999 bis -999 darstellen davon den Zahlenbereich 99,9 bis -9,9 als
Dezimalwert mit Komma. Im Prinzip ist das der Sinn meiner Funktion wobei
ihr ganz richtig bemerkt habt, dass die Funktion noch nicht ganz fertig
ist weil die Anzeige von negativen Zahlen nicht funktioniert und die
Ausgaben von Zahlen >99,9 auch noch nicht implementiert ist. (ich muss
nur Spannungen von 0 - 60V auswerten - brauch ich also noch nicht)
Ich fand die Idee gut für Dezimalzahlen aus der ADC-Spannungsmessung
eine eigene Funktion zu schreiben statt bisher
lcd_int2(x/10);
lcd_write(",");
lcd_int(x%10);
Aber irgendwie versteht mich mal wieder keiner.
Karl K. schrieb:> Sorry ich hab noch nie mit Fließkomma gearbeitet und habe das auch im> Prinzip nie gebraucht. Der ADC liefert bei 10bit 0-1023.> Spannungsmessung Genauigkeit ist 0,1 Volt.
Aha, also Festkommaarithmetik. Die ist aus deiner Funktion aber
nicht so recht ablesbar.
> Aber irgendwie versteht mich mal wieder keiner.
Das könnte an deinen Informationen liegen, welche du nicht lieferst.
Karl K. schrieb:> Aber irgendwie versteht mich mal wieder keiner.
denn mache es doch richtig, uint16 reicht doch bis 6000centiVolt
Spannungsteiler
0-60V Kennlinie aufnehmen und Steigung m und Konstante b ermitteln mit
der Geradengleichung y = m * x + b
hinterher Komma an der richtigen Stelle einsetzen per
Stringmanipulation, ganz ohne float.
Joachim B. schrieb:> hinterher Komma an der richtigen Stelle einsetzen per> Stringmanipulation, ganz ohne float.
Man kann auch float Zahlen darstellen ganz ohne float zu
benutzen. Karl hat es im Ansatz schon gezeigt.
Karl K. schrieb:> lcd_int2(x/10);> lcd_write(",");> lcd_int(x%10);
Nur den letzten Schritt, dies vernünftig in einer Funktion zu
vereinen, das scheint für ihn zu schwierig zu sein.