Hallo zusammen, ich habe ein Programm, was die eingelesene Spannung in Lux ausgeben soll. Ich kann zwischen 3 Bereiche umschalten. Jenach bereich wird mit 25000, 2500 oder 250 multipliziert. Ich bekomme aber komischerweise kein Wert ausgegen. Startanzeige etc. geht. Danke im voraus.
:
Bearbeitet durch User
Denis B. schrieb: > Danke im voraus. Fuck! Was ist an dem Text der bei jedem zu postenden Beitrag steht nicht zu verstehen? Oder gilt der Text nicht für dich?
Denis B. schrieb: > Angehängte Dateien: > > Code.docx (21 KB) Sourcecode in Office-Dokument? Echt jetzt?
Denis B. schrieb: > Ich bekomme aber komischerweise kein Wert ausgegen. Vielleicht versteht der ADC bzw. der Compiler kein docx
<takt100ms> wird nie auf TRUE gesetzt, vermutlich immer null. Dann wird auch doAdc() und calculateLux() nie aufgerufen. sei() bewirkt nichts da keine Interrupts definiert sind und keine ISRs angelegt sind.
Wolfgang schrieb: > Vielleicht versteht der ADC bzw. der Compiler kein docx Vielleicht hängt am ADC-Eingang auch gar nichts dran? Der Pin hängt zum Beispiel in der Luft oder die Leiterbahn geht im Layer ins Nirwana. Dann kannst Du noch Jahrzehnte weiter im Code suchen.
<takt1s> wird auch nie auf TRUE gesetzt, es sei denn du verheimlichst irgendwelchen Code.
Dieter schrieb: > Vielleicht hängt am ADC-Eingang auch gar nichts dran? Denis B. schrieb: > Ich bekomme aber komischerweise kein Wert ausgegen.
> lcd_putc(tempValue/100 + ASC_NULL);
Funktioniert es auch mit einem Integer?
Danke für die Tipps, ISR und Timer hat gefehlt. Habe jetzt angepasst. Bekomme aber beispielsweise 10 anstatt 100 Lux.
Denis B. schrieb: > Danke für die Tipps, > ISR und Timer hat gefehlt. > Habe jetzt angepasst. Dann lese dir auch noch durch wann man volatile verwenden sollte: AVR-GCC-Tutorial: Datenaustausch mit Interrupt-Routinen >float index; Da ich vermute dass du einen Controller ohne Floating Point Unit verwendest würde ich mir die ganzen floats sparen. Denis B. schrieb: > Bekomme aber beispielsweise 10 anstatt 100 Lux. Dein Erwartungswert weicht um einen Faktor 10 ab. Deine Messwertumschaltung hat pro Stufe einen Faktor 10. Da liegt die Vermutung nahe dass die nicht richtig funktioniert. Setze sie Mal auf einen festen Wert und schau ob Erwartungswert und Messwert zusammenpassen. Allgemein passt an mehreren Stellen Code und Kommentar nicht zusammen. Evtl ist das dein Problem dass dein Faktor nicht richtig berechnet wird:
1 | DDRD = DDRD & 0b11110000; // Port B auf Eingabe schalten |
:
Bearbeitet durch User
Denis B. schrieb: > Ich bekomme aber komischerweise kein Wert ausgegen. wie wäre es, wenn du im allerersten Anlauf gar nichts "korrigierst", sondern einfach direkt den ADC-Wert auf das Display ausgibst? Und gleichzeitig mit dem Multimeter die Spannung am ADC-Pin nachmisst und nachrechnest, ob der angezeigte Wert passt? Oder andersrum: es funktioniert nicht, die Mondrakete von der Idee weg komplett fertig zu machen und dann das komplett neu aufgebaute Ding in Richtung Mond zu starten. Stattdessen nimmt man nacheinander einzelne Teile der Mondrakete in Betrieb und untersucht, ob der jeweilige Teil wie geplant funktioniert. Und wenn jedes Teil für sich tut, dann wird die Mondrakete Stück für Stück zusammengefügt und dabei immer wieder getestet. Ersetze im obigen Text das Wort "Mondrakete" durch irgend eine andere Gerätebezeichnung wie z.B. "Luxmeter". Denis B. schrieb: > ISR und Timer hat gefehlt. Ist hier überhaupt eine ISR und ein Timer nötig? Wofür? Ein "Interrupt" ist eine "Unterbrechung" im Programmablauf, weil etwas Wichtiges dringend dazwischenkommt. Bei deiner Anwendung ist 1. nichts schnell oder dringend und 2. muss nichts unterbrochen werden. Und ein Timer wird benötigt, wenn etwas in konstanten Zeitabständen passieren soll. Auch das ist in deiner Anwendung unnötig.
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Ist hier überhaupt eine ISR und ein Timer nötig? Prinzipiell kann man das zwar überlegen, aber ganz verkehrt empfinde ich den Timer hier nicht. Ob mit ISR oder ohne. Was wäre die Alternative? Ein SW-Zähler der die Main Durchläufe zählt? Das ist in meinen Augen aus mehreren Gründen hässlich: Man kann allgemein die Zeiten nur schätzen weil man nicht genau weiß wie lange ein Durchlauf ist. Die Zeiten verändern sich mit jeder Zeile Code die er hinzufügt. Ist zwar momentan nicht kritisch, aber trotzdem unschön. Mit dem richtigen Timer + ISR kann er am Ende der while sogar noch ein Sleep einfügen falls notwendig. Allgemein ist ein Timer meist nicht verkehrt für Anzeige, Entprellen, ADC (äquidistante Abtastung), ... usw. Und der Interrupt tut selbst in einem anspruchsvollen Programm (was das hier ja eindeutig nicht ist) meist nicht weh, wenn er kurz genug ist.
:
Bearbeitet durch User
N. M. schrieb: > Lothar M. schrieb: >> Ist hier überhaupt eine ISR und ein Timer nötig? > > Prinzipiell kann man das zwar überlegen, aber ganz verkehrt empfinde ich > den Timer hier nicht. Ob mit ISR oder ohne. > > Was wäre die Alternative? Eine (dämliche) Warteschleife, in der das ADC-Flag abgefragt wird.
Teo D. schrieb: > Eine (dämliche) Warteschleife, in der das ADC-Flag abgefragt wird. Und dann mit 20kHz das Display aktualisieren? Zahl nur beispielhaft. Je nach dem wie schnell der ADAC wandelt.
:
Bearbeitet durch User
N. M. schrieb: > Teo D. schrieb: >> Eine (dämliche) Warteschleife, in der das ADC-Flag abgefragt wird. > > Und dann mit 20kHz das Display aktualisieren? > Zahl nur beispielhaft. Je nach dem wie schnell der ADAC wandelt. Wenn das Display das macht?! Aber wozu braucht man den ADAC dabei?
STK500-Besitzer schrieb: > Wenn das Display das macht?! Geil, wild zappelnde Werte bis man nichts mehr lesen kann. Top. STK500-Besitzer schrieb: > Aber wozu braucht man den ADAC dabei? Herzlichen Glückwunsch, du hast einen Typo gefunden.
:
Bearbeitet durch User
N. M. schrieb: > Teo D. schrieb: >> Eine (dämliche) Warteschleife, in der das ADC-Flag abgefragt wird. > > Und dann mit 20kHz das Display aktualisieren? Wow, du hast aber schnelle Augen.... Du hast nach Alternativen gefragt, nicht nach einer passenden Lösung deines Problems. Ich nannte sie dir und gab dir sogar einen Hinweis, dass das dämlich ist. .... Mir scheint, du bist schlau genug, um das selbstständig zu erarbeiten. BB :)
N. M. schrieb: > STK500-Besitzer schrieb: >> Wenn das Display das macht?! > > Geil, wild zappelnde Werte bis man nichts mehr lesen kann. Top. Das ist doch ein ganzh anderes Problem. Die Display-Refresh-Routine sieht nicht so aus, als würde sie non-blocking funktionieren. Ergo, bremmst die den Messprozess auch noch aus. Ich gebe dir aber Recht, dass das momentan noch nicht optimal ist. > STK500-Besitzer schrieb: >> Aber wozu braucht man den ADAC dabei? > > Herzlichen Glückwunsch, du hast einen Typo gefunden. Sehr gerne... Einfach mal drüber lachen und gut.
N. M. schrieb: > Allgemein ist ein Timer meist nicht verkehrt für Anzeige, Entprellen, > ADC (äquidistante Abtastung), ... usw. Ich habe nirgends was anderes behauptet. Er ist aber eben für genau diese "fortgeschrittenen" Anwendungen nötig. Und nicht für die urschleimige Inbetriebnahme und das Debuggen eines ADC. N. M. schrieb: > Und dann mit 20kHz das Display aktualisieren? Für solche Programme auf Bastelinbetriebnahmeniveau tue ich mir eben genau den Schuh nicht an, erst mal das komplette Framework mit Interrupts und Timer zum laufen zu bekommen und dann an die Lösung der eigentlichen Aufgabe zu gehen. Für solche Programme auf Bastelinbetriebnahmeniveau verplempere ich dann einfach wissentlich Rechenzeit und nehme ein delay(). Wohl wissend, dass man das hinterher noch "richtig" machen muss (weil in meinem Programm sowieso ein 1ms-Zähler laufen wird). STK500-Besitzer schrieb: > dass das momentan noch nicht optimal ist. Wir sind hier noch weit weg vom "Optimieren". Zum "Optimieren" müsste das Programm ja erst mal überhaupt das tun, was es soll.
:
Bearbeitet durch Moderator
Teo D. schrieb: > Mir scheint, du bist schlau genug, um das selbstständig zu erarbeiten. > BB :) Ich schon. Aber ich bin auch nicht der TO :-) Die Frage habe ich gestellt da man einem Anfänger den bereits laufenden Timer Ausreden möchte. Ich finde den Timer gut, deshalb die Frage wie er es ohne Timer machen soll.
Lothar M. schrieb: > Für solche Programme auf Bastelinbetriebnahmeniveau verplempere ich dann > einfach wissentlich Rechenzeit und nehme ein delay(). Klar, mache ich teilweise auch. Der Timer/ISR bei den AVRs benötigt ja aber wirklich nur ein paar Register Werte. Gerade bei Anfängern ist das delay zwar schnell gelernt, aber meist nur schwer wegzubekommen.
N. M. schrieb: > Die Frage habe ich gestellt da man einem Anfänger den bereits laufenden > Timer Ausreden möchte. Darum geht es doch überhaupt nicht. Ich sag es einfach mal andersrum: auch wenn er in seinen Code nochmal 10 Timer und 20 Interrupts einfügt, wird er damit das eigentliche Problem nicht lösen. Das ist also eine völlig unnötige Kompensationshandlung.
:
Bearbeitet durch Moderator
N. M. schrieb: > Ich schon. Aber ich bin auch nicht der TO :-) Ubs.... :D N. M. schrieb: > Ich finde den Timer gut, deshalb die Frage wie er > es ohne Timer machen soll. Eine etwas elegantere Methode were, das Program weiterlaufen zu lassen und jedes mal, beim eintritt in die ADC Routine, das Flag zu prüfen und den "alten" Wert der vorherigen Messung auszuwerten. Dann die neue Messung starten....
Lothar M. schrieb: > STK500-Besitzer schrieb: >> dass das momentan noch nicht optimal ist. > Wir sind hier noch weit weg vom "Optimieren". Zum "Optimieren" müsste > das Programm ja erst mal überhaupt das tun, was es soll. ja, genau. Was anderes meinte ich auch nicht.
Lothar M. schrieb: > Für solche Programme auf Bastelinbetriebnahmeniveau tue ich mir eben > genau den Schuh nicht an, erst mal das komplette Framework mit > Interrupts und Timer zum laufen zu bekommen und dann an die Lösung der > eigentlichen Aufgabe zu gehen. Wenn du damit quasi als Template starten würdest, könntest du dir grundsätzlich das "zum Laufen bekommen" sparen. Es würde einfach funktionieren. Du hast für die eigentliche Aufgabe gleich ein solides Gerüst und nicht irgendeine Bastelei. Spätestens wenn du sinnvoll filtern willst, um z.B. für die Anzeige stabile Mittelwerte zu erzeugen, ist eine äquidistante Abtastung (unabhängig vor irgendwelchen sporadischen Verzögerungen durch die Displayroutinen) sinnvoll.
Wolfgang schrieb: > Wenn du damit quasi als Template starten würdest, könntest du dir > grundsätzlich das "zum Laufen bekommen" sparen. Es würde einfach > funktionieren. Du hast für die eigentliche Aufgabe gleich ein solides > Gerüst und nicht irgendeine Bastelei. Spätestens wenn du sinnvoll > filtern willst, um z.B. für die Anzeige stabile Mittelwerte zu erzeugen, > ist eine äquidistante Abtastung (unabhängig vor irgendwelchen > sporadischen Verzögerungen durch die Displayroutinen) sinnvoll. Und jeder Anfänger hat auch schon die Übersicht, wie man sowas aufbaut - ganz mein Humor.
Wolfgang schrieb: > Du hast für die eigentliche Aufgabe gleich ein solides Gerüst Ja, genau richtig erfasst. Ich habe tatsächlich einige Erfahrung mit etlichen µC und verwende so ein "Standardframework" mit (am allerwichtigsten) einem 1ms-Tick. Der Witz dabei: ich kenne dieses Framework in- und auswendig. Der TO Denis hat diese Voraussetzungen nicht. Wie oft hast du als Anfänger wegen unerklärlicher Effekte an irgendwelchen Interrupts (je nach µC am besten noch priorisiert, verschachtelt und verreigelt) herumgesucht? Genau das wird auch dem TO passieren. Und wenn es klemmt, dann bin ich trotz Framework blitzschnell beim "Dreizeiler", wo nichts läuft ausser das, womit ich grade Probleme habe. Teo D. schrieb: > N. M. schrieb: >> Ich finde den Timer gut, deshalb die Frage wie er >> es ohne Timer machen soll. > Eine etwas elegantere Methode were, das Program weiterlaufen zu lassen > und jedes mal, beim eintritt in die ADC Routine, das Flag zu prüfen Ich kenne da solche Spezialisten, die verlassen sich auf den Timer, rechnen sich (korrekterweise) aus, dass der ADC mit den gewählten Einstellungen nach 1ms sicher fertig ist, lesen den in der Timer-ISR aus ohne(!) auf das Flag zu schauen (war ja berechnet, dass der ADC sicher fertig sein wird) und starten den ADC nach dem Auslesen gleich wieder neu. Funktioniert tadellos, bis einer nach geraumer Zeit mal was am Timer oder der ADC-Konfiguration ändert... Denis B. schrieb: > ich habe ein Programm Noch ein Tipp dazu: schreib alle paar Sekunden auch mal den statischen "Festtext" nochmal raus:
1 | lcd_putstr("Luxmeter"); // Ausgabe Festtext: 8 Zeichen |
Denn wenn irgendwelche Störimpulse (ESD, Handy, ...) auf die Leitungen zum display kommen, dann könnte es sein, dass in diesem Text ein Müllzeichen auftaucht. Und das bleibt dort, weil es erst beim nächsten einschalten wieder geschrieben wird.
:
Bearbeitet durch Moderator
Lothar M. schrieb: >> Eine etwas elegantere Methode were, das Program weiterlaufen zu lassen >> und jedes mal, beim eintritt in die ADC Routine, das Flag zu prüfen > Ich kenne da solche Spezialisten, die verlassen sich auf den Timer, > rechnen sich (korrekterweise) aus, dass der ADC mit den gewählten > Einstellungen nach 1ms sicher fertig ist Da wäre ich alleine schon, viel zu faul, um das auszurechnen/abzuschätzen.... :D
Lothar M. schrieb: > N. M. schrieb: >> Und dann mit 20kHz das Display aktualisieren? > Für solche Programme auf Bastelinbetriebnahmeniveau verplempere ich dann > einfach wissentlich Rechenzeit und nehme ein delay(). Für eine Fehlersuche ja. Später macht es Sinn, sich den Anzeigewert zu merken und das Display nur zu beschreiben, wenn der neue Wert eine relevante Änderung ergibt. Zum Beispiel bei meiner Lötstation, da ist der Meßintervall dynamisch. Die Zeit, das komplette Display zu beschreiben, war bei einigen 10ms und damit störend. Ich schreibe nur eine Zeile neu, wenn sich die Temperatur um 2° geändert hat und gewinne damit Zeit für die Hauptaufgabe, die Regelung.
Manfred schrieb: > Später macht es Sinn Bezweifelt ja keiner. Zu allerletzt ich. Aber wir sind eben im Jetzt, wo der ADC nicht läuft. Und der kommt auch nicht ans Laufen, wenn man weiterhin am Framework rumfrickelt. Dass man sich dur diese Interrupt-Geschichte auch noch die für Anfänger verwirrende Volatile-Geschichte einhandelt, das macht die Sache nicht nachvollziehbarer. Manfred schrieb: > Die Zeit, das komplette Display zu beschreiben, war bei einigen 10ms und > damit störend. Aber nicht für den User, sondern nur für deinen Programmablauf. > Ich schreibe nur eine Zeile neu, wenn sich die Temperatur > um 2° geändert hat und gewinne damit Zeit Ich schreibe den gesamten Text in einen Buffer im RAM und in der 1ms-Timer-ISR wird jeweils 1 Zeichen ausgegeben. Weil dafür keine Wartezeit nötig ist, ist da in der ISR kaum Overhead und ein 4x20 Display wird 12x pro Sekunde komplett neu beschrieben. Aber das alles ist ewig weit weg vom hiesigen Problem "ADC wird nicht eingelesen".
:
Bearbeitet durch Moderator
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.