Hallo zusammen!
Ich bin schon seit geraumer Zeit glücklicher Nutzer dieses Forums. Hier
ist schon so manches meiner Probleme kompetent gelöst worden. Unter
Zuhilfenahme anderer Forumseinträge habe ich es nun geschafft, selber
ein Programm für einen Mikrocontroller zusammen zu schustern. Da ich
niemanden persönlich kenne (mich eingeschlossen), der sich gut mit der
Materie des µC-Programmierens auskennt, stelle ich das Programm zwecks
Optimierung nun der allgemeinen Weisheit dieses Forums zur Verfügung.
Was ich sagen will, ist, das das Programm im Großen und Ganzen
funktioniert (es gibt kleinere Probleme, auf die ich später noch
eingehe). Jedoch gibt es bestimmt noch Verbesserungen zu machen.
Villeicht gibt es sogar Fehler, die später noch zu größeren Problemen
führen. Dem möchte ich vorbeugen. Deswegen die Frage: kann jemand bitte
dieses Programm kontrollieren?
Ja klar, das klingt jetzt absolut hochgestochen, aber ich weiss, dass es
Leute da draussen gibt, die gerne ihr Wissen mit Unwissenden teilen. Und
an die wende ich mich. Also, wenn ihr die Zeit und den Willen aufbringen
wollt und könnt, wäre das echt nett.
Und bitte denkt nicht, das läuft hier jetzt nach dem Motto "ICH habe
MEIN perfektes Programm hier reingestellt, damit sich diese
Möchtegern-Schlauen die Zähne ausbeissen. Muahahahaha!". So ist das
nicht. Ich programmiere erst seit ein paar Wochen...die Grundlagen des
Programmierens mit C kenne ich einigermaßen, aber ansonsten bin ich ein
absoluter Noob. Ich bin von mir selbst überrascht, dass das Programm
überhaupt einigermaßen funktioniert :-D
Also, das Programm tut folgendes:
Die Ausgansspannung eines Volumenstrom- (im Programm habe ich das
Flowmeter genannt) und eines Differenzdrucksensors soll mittels ADC
gemessen werden. Die Spannungswerte sollen in die dazugehörigen
physikalischen Werte (mit den Einheiten Liter/min und mbar) umgerechnet
und auf einem Display angezeigt werden. Bei Verlassen vorgegebener
Sollwerte, soll ein piepender Alarmton ertönen, der auf Tastendruck
wieder abgeschaltet werden kann.
Zur Verfügung stehen: - ATmega16L
- STK500
- 16x2 Display im 4bit-Modus
- Volumenstrommesser
- Differendrucksensor
- Taster
- kleiner Lautsprecher
Manchmal taucht das Problem auf, dass nach Abweichung der Sollwerte der
Alarmton nur einmal zu hören ist und danach ausbleibt, obwohl die Werte
immer noch Abweichen. Der Alarmton sollte aber so lange zu hören sein,
bis der Taster gedrückt wird.
Konstruktive Kritik ist absolut willkommen. Was geht besser? Was sollte
lieber gar nicht gemacht werden?
Vielen Dank und einen schönen Weltkindertag noch! :-)
Don Panso schrieb:> Manchmal taucht das Problem auf, dass nach Abweichung der Sollwerte der> Alarmton nur einmal zu hören ist und danach ausbleibt, obwohl die Werte> immer noch Abweichen. Der Alarmton sollte aber so lange zu hören sein,> bis der Taster gedrückt wird.
Wie ist dein Taster angeschlossen.
Ich sehe im Code nicht, dass du für die übliche Tasterbeschaltung einen
Pullupwiderstand einschaltest?
Don Panso schrieb:> Konstruktive Kritik ist absolut willkommen. Was geht besser? Was sollte> lieber gar nicht gemacht werden?
Du hast einen Haufen magische Zahlenwerte mitten im Code
Ich würde mir auch noch Variablen machen, die aussgane ob der Messwert
innerhalb der Grenzen ist oder nicht.
Dadurch:
Sind die magischen Zahlenkonstanten für die Grenzen nur an einer
Stelle
die Abfrage ob der ALarmton eingeschaltet werden soll bzw. die andere
vereinfacht sich und wird leichter lesbar
Hast du auch noch eine simple Möglichkeit, wie du dem Benutzer zb
mit einem zusätzlichen '!' im LCD anzeigen kannst, welcher Messwert
eigentlich abweicht und zum Alarm geführt hat.
Aufteilen in Funktionen!
Die ADC Abfrage ist bis auf die Kanalnummer immer gleich -> perfekter
Kansidat für eine Funktion
Das Konfigurieren von irgendwelchen Steuerregister durch Zuweisung von
magischen Bitkonstanten ist verpönt. Im Datenblatt hat jedes Bit einen
Namen. Mit der 1 << Bitname Syntax arbeiten!
1
hilf_low_flow=ADCL;
2
adcwert_flow=(ADCH<<8);
3
adcwert_flow|=hilf_low_flow;
Dein Compiler weiß schon wie man 16 Bit Register ausliest und hält dafür
Pseudoregister bereit:
1
adcwert_flow=ADCW;
Den ADC liest man nicht nach einem _delay aus, sondern wenn der ADC
'fertig' meldet.
Don Panso schrieb:> Manchmal taucht das Problem auf, dass nach Abweichung der Sollwerte der> Alarmton nur einmal zu hören ist und danach ausbleibt, obwohl die Werte> immer noch Abweichen. Der Alarmton sollte aber so lange zu hören sein,> bis der Taster gedrückt wird.
Das schreit nach einer soliden SW-Entprellung.
Peter
Den ADC kann man in C (avr-libc) auch mit ADCW auslesen, statt sich den
Wert aus ADCL und ADCH zusammenzusuchen.
Wenn die Sache zeitkritisch wäre (wovon ich wegen den vielen delays mal
nicht ausgehe) könnte man die Fließkommaberechnung rauswerfen und durch
Festkommaarithmetik ersetzen.
Die Taste sollte besser in einem Timer-Interrupt abgefragt und entprellt
werden. Dann dauert es nicht 450ms, bis sie im worst-case reagiert. So
wird auch kein kurzer Tastendruck zwischen zwei Abfragen übersehen.
idealerweise nutzt man das loslassen des tasters aus
also merken wenn taster gedrückt ... wenn dieser taster auch nach einer
gewissen zeit losgelassen wurde .. wollte man wirklich was ..
ansonst nix tuen...
anhand der loslasszeit kann man sogar noch dinge unterscheiden..
ich würde ALLE delays raushauen und mich mal an deiner stelle mit
Statemaschines befassen
Don Panso schrieb:> Konstruktive Kritik ist absolut willkommen. Was geht besser? Was sollte> lieber gar nicht gemacht werden?
Wähle doch bitte nächstes mal einen etwas besseren Threadtitel! Was hat
das ganze den Bitte mit Programm"optimierung" zu tun?
ff schrieb:> idealerweise nutzt man das loslassen des tasters aus
Das ist überhaupt nicht ideal, sondern das Gegenteil.
Der Mensch erwartet eine Reaktion beim Drücken!
Ich möchte Dich mal sehen, wenn Deine PC-Tastatur die Zeichen erst beim
Loslassen ausgeben würde. Du würdest das Keyboard in kürzester Zeit auf
den Boden feuern und wutentbrand zertreten.
Peter
Guten morgen allerseits!
Mensch das ging ja schnell mit den Antworten. Vielen Dank dafür! Sorry,
dass ich erst jetzt antworte...
Karl heinz Buchegger schrieb:> Wie ist dein Taster angeschlossen.> Ich sehe im Code nicht, dass du für die übliche Tasterbeschaltung einen> Pullupwiderstand einschaltest?
Der Taster ist auf dem STK500. Dort ist die Stiftleiste des PortB mit
der Stiftleiste der Taster verbunden. Da die Taster active low sind,
habe ich die Abfrage des Tastendrucks mit "if(!(PINB & (1 << PINB0)))"
vollzogen. Der Pullupwiderstand muss rein? Ok, dann füge ich noch ein
"PORTB = 0x01;" ein.
Karl heinz Buchegger schrieb:> Im Datenblatt hat jedes Bit einen> Namen. Mit der 1 << Bitname Syntax arbeiten!
Du hast recht, das ist übersichtlicher, führt aber zuweilen zu ewig
langen Zeilen bzw. zu mehr Schreibarbeit. Da ich faul bin habe ich mir
das abgewöhnt, dennoch werde ich das in der nächsten Fassung des
Programms beherzigen.
Karl heinz Buchegger schrieb:> Ich würde mir auch noch Variablen machen, die aussgane ob der Messwert> innerhalb der Grenzen ist oder nicht.
Meinst du z.B. eine Variable "int flowwert_zu_niedrig;", die man dann in
einem if-Statement beispielsweise zu '1' setzt, wenn der flowwert zu
niedrig wird?
Karl heinz Buchegger schrieb:> Aufteilen in Funktionen!
Stimmt, die ADC-Routine ist gut in eine Funktionen zu fassen. Das wird
übernommen ;-)
Karl heinz Buchegger schrieb:> adcwert_flow = ADCW;
Sehr guter Vorschlag. Das kannte ich noch nicht...kommt auf jeden Fall
rein.
Karl heinz Buchegger schrieb:> Den ADC liest man nicht nach einem _delay aus, sondern wenn der ADC> 'fertig' meldet.
Ok wird auch gemacht. Habe ich mal irgendwo gesehen wie das geht.
@Peter & Uwe
Mal gucken, ob ich das mit dem Tasten-Entprellen mache. Ist das wirklich
nötig? Für den Benutzer ist das denke ich mal kein Problem den Taster
ein bisschen länger gedrückt zu halten...
ff schrieb:> idealerweise nutzt man das loslassen des tasters aus
Auch ein guter Vorschlag. Wird villeicht umgesetzt. Muss zwar noch
herausfinden wie, aber das wird schon.
Läubi .. schrieb:> Was hat> das ganze den Bitte mit Programm"optimierung" zu tun?
Damit will ich sagen, dass das Programm zwar meistens das tut, was es
soll, jedoch nicht perfekt ist. Das will ich mit eurer Hilfe ändern. Die
Effizienz des Programms soll verbessert werden. Meines wissens nennt man
das "Optimierung". Sollte ich aber mal einen anderen Thread eröffnen,
stecke ich ein wenig mehr Gehirnschmalz in den Titel.
Ich kann nur nochmals sagen: vielen Dank für eure schnellen Antworten!
Ich werde das Programm umschreiben und eure Ratschläge auf jeden Fall
befolgen. Das wird wohl etwas dauern, aber wer die Geduld hat diesem
Thread noch ein bisschen zu folgen (was ich natürlich von keinem
verlange), der kann im Laufe des Tages womöglich noch die verbesserte
Version des Programmes betrachten. Ich geh dann mal wieder zurück an die
Arbeit ;-)
Vielen Dank nochmal und einen schönen Tag noch!
Don Panso schrieb:> Der Taster ist auf dem STK500. Dort ist die Stiftleiste des PortB mit> der Stiftleiste der Taster verbunden. Da die Taster active low sind,> habe ich die Abfrage des Tastendrucks mit "if(!(PINB & (1 << PINB0)))"> vollzogen. Der Pullupwiderstand muss rein? Ok, dann füge ich noch ein> "PORTB = 0x01;" ein.
Das weiß ich nicht, weil ich nicht weiß, ob auf dem STK externe Pullup
Widerstände verbaut sind oder nicht.
Irgendeinen Pullup muss es geben, sonst hängt der Eingang in der Luft,
wenn der Taster nicht gedrückt ist.
Da ich allerdings davon ausgehe, dass dein Programm letztendlich nicht
auf dem STK500 bleiben wird, sondern seine eigene Platine bekommen wird,
sind die internen Pullups sicher eine gute Idee :-)
>> Im Datenblatt hat jedes Bit einen>> Namen. Mit der 1 << Bitname Syntax arbeiten!>> Du hast recht, das ist übersichtlicher, führt aber zuweilen zu ewig> langen Zeilen bzw. zu mehr Schreibarbeit.
Regel:
Code schreibt man einmal, man liest ihn aber viele male.
Lieber etwas mehr Aufwand beim Schreiben, als ihn jedesmal beim Lesen
erneut entziffern zu müssen.
> Da ich faul bin habe ich mir> das abgewöhnt,
Das gewöhnst du dir ganz schnell wieder an, wenn du jemals Code von
einem Prozessor zu einem anderen portieren musst, der zwar dieselben
Bits in denselben Registern aber in etwas anderer Reihenfolge hat.
Dann musst du nämlich mit der Bitnamen Syntax gar nichts tun, während du
mit der Bitschreibweise rumpfriemeln musst.
>> Ich würde mir auch noch Variablen machen, die aussgane ob der Messwert>> innerhalb der Grenzen ist oder nicht.>> Meinst du z.B. eine Variable "int flowwert_zu_niedrig;", die man dann in> einem if-Statement beispielsweise zu '1' setzt, wenn der flowwert zu> niedrig wird?
Nein.
ein
uint8_t flowwert_in_range;
wäre angebracht.
denn das ist es doch was dich interessiert: ist der Wert im erlaubten
Bereich oder nicht.
Schon fast ein kompletter Satz. Ich brauch mir nur ein paar Füllwörter
wie der/die/das dazudenken und kann fast im Klartext lesen und verstehen
was da eigentlich passiert.
> Ok wird auch gemacht. Habe ich mal irgendwo gesehen wie das geht.
Für solche Sachen sollte das AVR-GCC-Tutorial deine erste Anlaufstelle
sein, nicht Code den du 'irgendwo' mal gesehen hast.
> @Peter & Uwe> Mal gucken, ob ich das mit dem Tasten-Entprellen mache. Ist das wirklich> nötig? Für den Benutzer ist das denke ich mal kein Problem den Taster> ein bisschen länger gedrückt zu halten...
Es geht nicht darum, dass der Benutzer etwas länger drücken muss. Es
geht darum, dass der Benutzer 1 mal drückt, der Alarm allerdings 2 mal
ausgeschaltet wird. IMHO in deiner Anwendung kein Problem, denn ein
Alarm der bereits abgeschaltet ist kann nicht weiter abgeschaltet
werden.
>> idealerweise nutzt man das loslassen des tasters aus>> Auch ein guter Vorschlag.
Kein guter Vorschlag. Peter hat schon geschrieben warum.
Ausserdem: Was soll das?
Ich will den Alarm ausschalten, während ich Drücke komme ich drauf, dass
ich das dann doch nicht will also bleib ich länger am Knopf, damit das
Programm die Aufforderung ignoriert?
Sowas schmeiss ich dir um die Ohren, wenn du mir sowas andrehen willst.
Was kommt als nächstes?
@ Don Panso (Gast)
>> Namen. Mit der 1 << Bitname Syntax arbeiten!>Du hast recht, das ist übersichtlicher, führt aber zuweilen zu ewig>langen Zeilen bzw. zu mehr Schreibarbeit. Da ich faul bin habe ich mir>das abgewöhnt,
Schlechte Entscheidung.
> dennoch werde ich das in der nächsten Fassung des>Programms beherzigen.
Gute Entscheidung!
>Meinst du z.B. eine Variable "int flowwert_zu_niedrig;", die man dann in>einem if-Statement beispielsweise zu '1' setzt, wenn der flowwert zu>niedrig wird?
Ja. Das nennt man allgemein Flags, also (binäre) Merker, welche
bestimmte Dinge anzeigen. Sie werden vom "Verursacher" gesetzt und von
der Auswertung wieder gelöscht. In deinem Fall heisßt dass, der Merker
wird in einer if() Abfrage gesetzt und in einer andern Abfrage der
entprellten Tasten gelöscht. Zwischendrin tutet es ununterbrochen ;-)
>> Den ADC liest man nicht nach einem _delay aus, sondern wenn der ADC>> 'fertig' meldet.>Ok wird auch gemacht. Habe ich mal irgendwo gesehen wie das geht.
Vielleicht hier?
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29>Mal gucken, ob ich das mit dem Tasten-Entprellen mache. Ist das wirklich>nötig?
Es ist deutlich besser. Und tut auch nicht weh.
>Auch ein guter Vorschlag. Wird villeicht umgesetzt. Muss zwar noch>herausfinden wie, aber das wird schon.
Siehe Entprellung.
>> Was hat>> das ganze den Bitte mit Programm"optimierung" zu tun?>Damit will ich sagen, dass das Programm zwar meistens das tut, was es>soll, jedoch nicht perfekt ist. Das will ich mit eurer Hilfe ändern.
Dann schreib das in den Betreff!
"Hilfe zur Programmverbesserung gesucht".
> Die Effizienz des Programms soll verbessert werden.
Du bist noch lange nicht in der Liga, in der man von Effizienz oder gar
deren Steigerung spricht. Du musst erstmal noch einige Grundlagen lernen
und umsetzen.
>stecke ich ein wenig mehr Gehirnschmalz in den Titel.
Verbindlichsten Dank. Und lies vorher was über Netiquette und
Bildformate, nur so als Vorwarnung.
MfG
Falk
Don Panso schrieb:> Damit will ich sagen, dass das Programm zwar meistens das tut, was es> soll.
Dann ist es fehlerhaft und es muß nichts optimiert werden, sondern der
Fehler beseitigt.
Optimieren bedeutet, daß Programm läuft fehlerfrei und man will z.B. den
Flash-Verbrauch oder den Stromverbrauch (CPU-Last) reduzieren.
Fehler beseitigen und Optimieren sind 2 völlig verschiedene Dinge.
Es kann sich aber manchmal erst beim Optimieren ein Fehler bemerkbar
machen, z.B. volatile-Fehler.
Peter
Falk Brunner schrieb:>>Damit will ich sagen, dass das Programm zwar meistens das tut, was es>>soll, jedoch nicht perfekt ist. Das will ich mit eurer Hilfe ändern.>> Dann schreib das in den Betreff!>> "Hilfe zur Programmverbesserung gesucht".
Noch besser wäre eigentlich den Prozessortyp noch zu nennen und
vieleicht irgenwie das Problem in den Vordergrund zu stellen (z.B.
Tastendruck wird nicht immer erkannt). Das jemand Hilfe sucht ist in
diesem FOrum meist sowieso anzunehmen ;)
Mir schwant da noch was.
Zeig doch mal die Funktion fail_sound()
Wenn die so aussieht, wie ich zur Zeit vermute, dann zieh ich den
Einwand mit der nicht notwendigen Entprellung wieder zurück.
Nicht weil die Entprellung unbedingt notwendig wäre (ich denke immer
noch, dass ein prellender Taster in diesem konreten Fall kein Problem
darstellt), sondern weil dir die PeDa Entprellung dafür sorgt, dass kein
Tastendruck verloren gehen wird.
Je länger ich mir das alles ansehe um so mehr komme ich zum Schluss:
Das Programm ist zwar aus Newbie-Sicht bzw. für eine
Desktop-Programmierer vernünftig aufgebaut.
Jemand der allerdings im Embedded Bereich arbeitet, schlägt die Hände
über dem Kopf zusammen. So arbeitet man nicht, wenn ein Programm mehrere
Dinge 'gleichzeitig' machen soll:
Piepton ausgeben
Taste überwachen
Messwerte überwachen
Im Embedded Bereich gilt als Faustregel (mit ein paar kleinen
Ausnahmen):
Sobald der erste _delay_ms auftaucht, ist das Programmdesign schon
falsch.
Hallo mal wieder!
Ok, das mit dem Thread-Titel tut mir leid. Das ist mein erster Thread
und ich dachte einfach das ist ein guter Titel, der aussagt, was ich
eigentlich will...dem scheint wohl nicht zu sein. Ich gelobe Besserung!
Falk Brunner schrieb:> Und lies vorher was über Netiquette
Auch wenn das mit dem Gehirnschmalz ein wenig frech klang, möchte ich
gerne an dieser Stelle anmerken, dass das nicht böse oder abwertend
gemeint war. Ich respektiere und finde es sehr freundlich von euch, das
ihr euch die Zeit nehmt, anderen Leuten zu helfen und mein Programm auf
ein professionelleres Niveau zu heben. Alles was ich hier schreibe bitte
nicht negativ sehen.
Karl heinz Buchegger schrieb:>>> idealerweise nutzt man das loslassen des tasters aus>>>> Auch ein guter Vorschlag.>> Kein guter Vorschlag.
Stimmt...es lohnt sich nicht, den Taster gedrückt zu halten, nur weil
man es sich anders überlegt hat und den Alarm doch anlassen will.
Ich hoffe, ihr nehmt es mir nicht übel, dass ich mich so hin und her
reissen lasse. Ich denke, dass zeugt einfach davon, dass ich noch nicht
so tief in der Materie drin bin.
Karl heinz Buchegger schrieb:> Für solche Sachen sollte das AVR-GCC-Tutorial deine erste Anlaufstelle> sein
Das erwähnte "irgendwo" schliesst das AVR-GCC-Tutorial mit ein. Dort
habe ich schon viele Lösungen für Probleme gefunden.
Karl heinz Buchegger schrieb:> Das weiß ich nicht, weil ich nicht weiß, ob auf dem STK externe Pullup> Widerstände verbaut sind oder nicht.
Das STK500 besitzt keine externen Pullup-Widerstände, aber wenn die
internen des µC auch ok sind, dann nehme ich die.
Karl heinz Buchegger schrieb:> flowwert_in_range = ( flowwert > FLOW_MINIMUM && flowwert < FLOW_MAXIMUM );
Ich hoffe, da ist kein copyright drauf ;-)
Falk Brunner schrieb:>>> Den ADC liest man nicht nach einem _delay aus, sondern wenn der ADC>>> 'fertig' meldet.>>>Ok wird auch gemacht. Habe ich mal irgendwo gesehen wie das geht.>> Vielleicht hier?
Jup, genau da! Danke trotzdem nochmal für den Link. :-)
Falk Brunner schrieb:>>Mal gucken, ob ich das mit dem Tasten-Entprellen mache. Ist das wirklich>>nötig?>> Es ist deutlich besser. Und tut auch nicht weh.
Oooookkkkkk. Wenns nicht weh tut, dann entprelle ich eben den Taster.
Ist ja auch im Tutorial gut beschrieben, wie das geht.
Karl heinz Buchegger schrieb:> Zeig doch mal die Funktion fail_sound()
Ich füge die Header-Datei "fail_jingle.h", in der die Funktion
"fail_sound()" definiert ist, in den Anhang ein. Funktioniert ganz gut
mit einem Lautsprecher...auf die Weise kann man sogar ein Klavier
programmieren, aber das ist eine andere Sache...
Karl heinz Buchegger schrieb:> So arbeitet man nicht, wenn ein Programm mehrere> Dinge 'gleichzeitig' machen soll
Ich weiss, dass das Programm sequentiell abläuft und das es z.B. nichts
bringt, während dem Alarmton oder der ADC-Wandlung, den Taster zu
drücken. Ich hab es jetzt nicht nachgerechnet, aber die maximale
Wartezeit, bis der Tastendruck registriert wird, ist durchaus
akzeptabel. Für professionelle Anwendungen ist das sicher nichts, aber
ich denke, für dieses Problem hier wird das schon reichen.
Danke für eure Geduld und Hilfsbereitschaft.
P.S.: und ich hoffe, das mit dem Thread-Titel is jetzt geklärt :-D
Don Panso schrieb:>> So arbeitet man nicht, wenn ein Programm mehrere>> Dinge 'gleichzeitig' machen soll>> Ich weiss, dass das Programm sequentiell abläuft und das es z.B. nichts> bringt, während dem Alarmton oder der ADC-Wandlung, den Taster zu> drücken.
Darum gehts in Wirklichkeit gar nicht.
Das mag jetzt in deiner Anwendung kein konkretes Problem sein, trotzdem
sollte man die Dinge gleich richtig lernen, sofern das vom Aufwand her
vertretbar ist.
Es geht darum, dass die nobelste Eigenschaft deines Programms darin
besteht 2 Eingangswerte zu überwachen.
Das ist die Hauptaufgabe des Programms.
OK Dein Programm macht jetzt nichts weiter mit den Werten, aber wenn die
Werte zb dazu benutzt werden würden, bei einer Überschreitung eine
Notabschaltung oder sonstige Korrekturmassnahmen einzuleiten, dann ist
es einfach nicht akzeptabel, wenn diese Überschreitung ein paar 100
Millisekunden zu spät festgestellt wird oder die Massnahmen ein paar 100
Millisekunden später beginnen, nur weil der µC damit beschäftigt ist,
vor sich hin zu tröten.
Vor allen Dingen ist das deshalb nicht akzeptabel, weil man das alles
durch den Einsatz eines Timers und Interrupts auch ganz einfach
'parallelisieren' kann. So wie eine Timer ISR eine LED blinken lassen
kann, so kann sie auch die Membran einer Tröte vor und zurück schnellen
lassen. Das verbraucht noch nicht einmal 1% Rechenzeit nebenher, von
denen das Hauptprogramm überhaupt nichts merkt.
In einem Programm mehrere Dinge quasi gleichzeitig zu machen, läuft
immer in irgendeiner Form auf einen Timer und eine ISR hinaus.
@ Don Panso (Gast)
>Ich füge die Header-Datei "fail_jingle.h", in der die Funktion>"fail_sound()" definiert ist, in den Anhang ein.
MööööP! Schon wieder falsch. In *.h Dateien gehört kein Programmcode,
sondern nur defines, Deklarationen und ggf. Makros.
Programmcode gehört immer in *.c Dateien.
> Funktioniert ganz gut>mit einem Lautsprecher...auf die Weise kann man sogar ein Klavier
Naja, für einen Anfänger ist das soweit OK. Aber das kann man einfacher
und besser, weil parallel zum normalen Programmablauf, mit einem Timer
und der Output Compare-Funktion machen.
Und allgemein was zum Thema "viele Sachen gleivhzeitig bearbeiten"
findest du im Artikel Multitasking.
>drücken. Ich hab es jetzt nicht nachgerechnet, aber die maximale>Wartezeit, bis der Tastendruck registriert wird, ist durchaus>akzeptabel.
~1s. Naja.
Schau mal in den Artikel Multitasking, denk drüber nach und
präsentier uns dann ein deutlich verbessertes, aufgeräumtes Programm. Du
schaffst das!
MFG
Falk
Mensch, ihr seid ja echt fix! Da komm ich gar nicht hinterher :-D
Ein wiederholtes Dankeschön fürs am Ball bleiben.
Karl heinz Buchegger schrieb:> weil man das alles> durch den Einsatz eines Timers und Interrupts auch ganz einfach> 'parallelisieren' kannFalk Brunner schrieb:> Und allgemein was zum Thema "viele Sachen gleivhzeitig bearbeiten"> findest du im Artikel Multitasking.
Ich habe mich schon immer mal gefragt, wie man gleichzeitig Sachen
bearbeiten kann, aber nie die Zeit gefunden mich ausgiebig damit zu
beschäftigen. Daher sind meine bisherigen Programme immer sequentiell
abgelaufen (bis auf einmal, wo ich einen Timer nebenher als Stoppuhr
laufen gelassen habe).
Das ist jetzt alles viel Stoff...wird wohl ein bisschen Zeit in Anspruch
nehmen, mich da einzulesen.
Falk Brunner schrieb:> Du> schaffst das!
Danke, die Motivation kann ich gebrauchen. :-D
Wenn ihr Lust habt könnt ihr hier demnächst (das kann ein Zeitraum von
mehreren Tagen sein; steht auch ein langes Wochenende vor der Tür, wo
ich endlich mal etwas Freizeit habe) das überarbeitete Programm
anschauen. Ich halte mich auf jeden Fall ran! Jetzt lerne ich erst mal
Multitasking!
Mfg,
D. Panso
P.S.:
Falk Brunner schrieb:>>Ich füge die Header-Datei "fail_jingle.h", in der die Funktion>>"fail_sound()" definiert ist, in den Anhang ein.>> MööööP! Schon wieder falsch.
Mist schon wieder steh ich im Fettnäpfchen!
Don Panso schrieb:> Ich habe mich schon immer mal gefragt, wie man gleichzeitig Sachen> bearbeiten kann, aber nie die Zeit gefunden mich ausgiebig damit zu> beschäftigen.
Wenn du einen Schweinsbraten im Rohr hast, bleibst du dann vor dem Herd
stehen und wartest bis der fertig ist?
Natürlich nicht.
Du hast einen Haufen Aufgaben zu erledigen.
zb Schweinsbraten kochen
Hausaufgaben kontrollieren
Geschirr abwaschen
Anstatt jetzt jede Aufgabe für sich zu erledigen und (eventuell)
abzuwarten bis sie fertig ist, wird bei jeder Aufgabe immer nur ein
kleiner Teil erledigt und dann gehts weiter zur nächsten
ins Rohr schauen ob Braten fertig
eine Rechnung der Hausaufgabe kontrollieren
ein Teller abwaschen
ins Rohr schauen ob Braten fertig
eine Rechnung kontrollieren
ein Teller abwaschen
ins Rohr Schauen ....
und so gehts reihum immer durch. In manchen Fällen muss man noch vorab
testen, ob es überhaupt etwas zu tun gibt und nur dann eine Aktion
machen, wenn das der Fall ist
while( 1 )
if Braten im Rohr fertig ?
aus dem Rohr nehmen
if Kind hat wieder eine Rechnung fertig
Rechnung kontrollieren
if Teller am schmutzigen Teller stapel
Teller abwaschen
aber das Prinzip ist nach wie vor das gleiche: Du bleibst nicht beim
Rohr stehen, du bleibst nicht bei Töchterchen/Sohn stehen, du bleibst
nicht an der Abwasch, sondern machst einen kleinen Teil der Aufgabe
(wenn er machbar ist) und gehst dann weiter zur nächsten Aufgabe.
Ob man das jetzt wie im Artikel über einzelne Funktionen macht, oder ob
zb ein Timer einen Takt vorgibt, in dem Dinge zu erledigen sind (zb eine
LED einschalten oder eine Membran in die andere Position zu verfahren),
ist ein Implementierungsdetail. Wenn man genau Zeiten einzuhalten hat
(wie zb bei der Erzeugung von Frequenzen) ist ein Timer die bessere
Wahl. Das ändert aber nichts am Prinzip.
@ Karl heinz Buchegger (kbuchegg) (Moderator)
>Wenn du einen Schweinsbraten im Rohr hast, bleibst du dann vor dem Herd>stehen und wartest bis der fertig ist?
Und wenn er Moslem is(s)t ? ;-)
Schönes Beispiel, wenn gleich die Erfahrung zeigt, dass besonders
MENSCHEN, eher schlecht im Multitasking sind.
Die sollten lieber NUR EINE Sache auf einmal machen, sonst steigen die
Reibungs(Umschalt)verlust mal fix auf 50% und mehr.
Ein Mikrocontroller hat das Problem nahezu nicht.
MFG
Falk
Falk Brunner schrieb:> @ Karl heinz Buchegger (kbuchegg) (Moderator)>>>Wenn du einen Schweinsbraten im Rohr hast, bleibst du dann vor dem Herd>>stehen und wartest bis der fertig ist?>> Und wenn er Moslem is(s)t ? ;-)>> Schönes Beispiel, wenn gleich die Erfahrung zeigt, dass besonders> MENSCHEN, eher schlecht im Multitasking sind.
Sag das mal den Frauen.
Die rühmen sich doch damit, dass sie von Natur aus Multitasking können.
Ich hab aber eher die Erfahrung gemacht:
Sie können zwar viele Dinge 'gleichzeitig', aber nichts richtig.
@ Karl heinz Buchegger (kbuchegg) (Moderator)
>Ich hab aber eher die Erfahrung gemacht:>Sie können zwar viele Dinge 'gleichzeitig', aber nichts richtig.
Das hast DU gesagt . . . ;-)
@Karl heinz Buchegger
Gutes, anschauliches Beispiel. Ich mach jetzt erst mal Feierabend und
villeicht schieb ich einen Braten in die Röhre (im kulinarischen Sinne).
Schönen Tag noch!
Ein wiederholtes hallo allerseits!
Ich habe meine Synapsen spielen lassen und nun folgendes am Programm
geändert:
-Zum einen ist jetzt eine ADC-Initialisierung vorhanden, die ein
Dummy-Readout vornimmt
-Sämtliche ADC-Routinen sind jetzt als Funktion vorhanden
-es gibt keine header-Datei für den Alarmton mehr
-ich habe mich an der Festkommaarithmetik versucht...der Speicherbedarf
ist tatsächlich runtergegangen
-die Abfrage des Tasters geschieht jetzt auch während der Alarmton
spielt
Die Spannungsmessung und die Anzeige der physikalischen Werte auf dem
Display aktualisiert sich bei Einhaltung der Grenzwerte alle 500ms. Eine
schnellere Aktualisierungsdauer ist nicht nötig.
Weichen Werte ab, so wird statt der 500ms-Pause der Alarmton abgespielt.
Dadurch verlängert sich zwar die Pause, in der keine Messung mehr
vorgenommen wird, auf die Dauer des Alarmtons (der weit mehr als 500ms
dauert), aaaaaaber das ist vertretbar. Um ein nahezu nahtloses rödeln
des Alarmtons zu verhindern habe ich die Variable "uint8_t ton_pause =
500;" eingebracht. Durch eine Abfrage des Wertes dieser Variable und
einer 1ms-Pause, falls die Variable den Wert nicht besitzt, verzögert
sich so das erneute Abspielen des Alarmtons.
Das Kapitel Multitasking habe ich durchgelesen, dennoch weiss ich nicht,
wie ich das in mein Programm einbauen kann. Was ist nämlich, wenn man
ganz bestimmte Frequenzen unbedingt einhalten will?
Was ich meine ist: in dem Beispiel im Artikel Multitasking gibt es eine
LED, die, wenn der Taster nicht gedrückt wird, mit einer Frequenz von
5Hz blinken soll.
Das "parallele" arbeiten wurde so erreicht, dass man die LED
einschaltet, dann 1ms wartet und schließlich testet, ob die UART etwas
zu empfangen hat und ob der Taster gedrückt wird. Hat die UART nix zu
empfangen, dauert es insgesamt also ca. 1ms, bis "der Prozess" wieder in
der Funktion mit der LED ist. Dort prüft man nun, ob eine Variable den
Wert 99 erreicht hat.
Ist dies der Fall, geht die LED aus und es dauert 100*1ms, bis die LED
wieder an geht (sofern die UART nichts zu empfangen hat). Was ist aber,
wenn die UART etwas zu empfangen hat? Dieses Empfangen braucht doch
Zeit...es würde also 100*(1ms + tUart) dauern, bis die LED wieder
umschaltet, was wiederrum die Frequenz verdirbt, oder verstehe ich da
was falsch? Bei einem Lautsprecher käme also ein anderer Ton raus...
Nun ja, jedenfalls habe ich das Programm geändert und ich bilde mir ein,
die meisten eurer Vorschläge mit einbezogen zu haben (bis auf
Tasten-Entprellung...da bin ich mir nicht sicher, ob das wirklich
notwendig ist). Ich habe noch keine Möglichkeit, das Ganze zu testen,
weil ich an das STK500 etc. erst am Montag wieder dran komme. Deswegen
sind villeicht noch ein paar Bugs drin. Kompillieren lässt es sich aber
schon mal, das heisst aber nicht, dass die Anwendung klappt..
Also, wenn ihr euch die Arbeit machen wollt, das Programm nochmal
durchzuschauen, hätte ich nichts dagegen ;-)
Einen schönen Tag noch!
Don Panso schrieb:> Das Kapitel Multitasking habe ich durchgelesen, dennoch weiss ich nicht,> wie ich das in mein Programm einbauen kann. Was ist nämlich, wenn man> ganz bestimmte Frequenzen unbedingt einhalten will?
Wenn man Timing einhalten muss, empfiehlt es sich immer auf einen Timer
zu setzen.
Einen Timer kann man so programmieren, dass er alle X Taktzyklen eine
Interrupt Service Routine aufruft und dabei den momentanten Ablauf im
Hauptprogramm (kurz!) unterbricht.
Mit einem Timer samt zugehöriger ISR ist es überhaupt kein Problem einen
Lautsprecher so anzusteuern, dass das Setzen einer Variablen in der
Hauptschliefe auf 1 ausreicht, so das der Lautsprecher zu quäken
anfängt. Setzt man die (globale) Variable wieder zurück auf 0, so hört
das Gequäke auf.
Denselben Timer kann man oft auch noch mitbenutzen um seinem Programm
einen Zeittakt zu verpassen, so dass auch noch andere Dinge in
bestimmten Zeitrastern erfolgen können.
Wenn du Timer links liegen lässt, schenkst du mindestens 70% des
Potentials deines µC von vorne herein her. Es lohnt sich also sich mit
dieser Baugruppe im µC zu beschäftigen.
Hi Karl!
Hmmm, dann lese ich mir nochmal durch wie das mit den Timern und
Interrupts funktioniert. Wird wieder ne Weile dauern...
Karl heinz Buchegger schrieb:> Das hier druckwertspannung = ((adcwert_druck*493)/102400);> funktioniert sicher nicht so wie du dir das vorstellst
ach das musste man dann so schreiben, oder?
druckwertspannung = ((adcwert_druck*493.0)/102400.0);
Womit das dann für diesen Teil mit der Festkommaarithmethik erledigt
wäre... :-)
@ Don Panso (Gast)
>Ich habe meine Synapsen spielen lassen und nun folgendes am Programm>geändert:
Es wird deutlich besser, ein paar Knackpunkte fehlen aber noch.
>-ich habe mich an der Festkommaarithmetik versucht...der Speicherbedarf>ist tatsächlich runtergegangen
Es sind aber noch double Variablen drin. Also immer noch viel unnötiger
Speicherbedarf.
>-die Abfrage des Tasters geschieht jetzt auch während der Alarmton>spielt
Schön, aber du hast immer noch große Wartezeiten drin, das geht besser.
>Die Spannungsmessung und die Anzeige der physikalischen Werte auf dem>Display aktualisiert sich bei Einhaltung der Grenzwerte alle 500ms. Eine>schnellere Aktualisierungsdauer ist nicht nötig.
Gute Idee, aber noch unzureichend umgesetzt.
>Weichen Werte ab, so wird statt der 500ms-Pause der Alarmton abgespielt.
Wenn du die 500ms Pause jetzt noch sinnvoll verkleinerst, bist du fast
am Ziel.
>500;" eingebracht. Durch eine Abfrage des Wertes dieser Variable und>einer 1ms-Pause, falls die Variable den Wert nicht besitzt, verzögert>sich so das erneute Abspielen des Alarmtons.>Das Kapitel Multitasking habe ich durchgelesen, dennoch weiss ich nicht,>wie ich das in mein Programm einbauen kann. Was ist nämlich, wenn man>ganz bestimmte Frequenzen unbedingt einhalten will?
Dann nimmt man einen Timer und die Output Compare Funktion.
>wenn die UART etwas zu empfangen hat? Dieses Empfangen braucht doch>Zeit...es würde also 100*(1ms + tUart) dauern, bis die LED wieder>umschaltet,
Nein, keinesfalls!
> was wiederrum die Frequenz verdirbt, oder verstehe ich da>was falsch?
Ja. Alle Prozesse sind pro Millisekunde! einmal dran. Das EMPFANGEN
eines Bytes per UART kostet keine Zeit, das macht der UART allein. Das
Verarbeiten dauert natürlich etwas Zeit, aber wenn man es richtig macht
nur sehr wenig, in der Größenordnung von 1ms.
> Bei einem Lautsprecher käme also ein anderer Ton raus...
Ja. Aber in deiner Anwendung kommt es nicht auf 100,0% Tonhöhe an, 99%
sind auch OK. Nur ausgehen darf der Ton nicht, logisch.
>Nun ja, jedenfalls habe ich das Programm geändert und ich bilde mir ein,>die meisten eurer Vorschläge mit einbezogen zu haben
Du hast den ersten Schritt getan, das ist gut. Es fehlen aber noch
einige.
> (bis auf>Tasten-Entprellung...da bin ich mir nicht sicher, ob das wirklich>notwendig ist).
Ist hier nicht nötig.
> Ich habe noch keine Möglichkeit, das Ganze zu testen,>weil ich an das STK500 etc. erst am Montag wieder dran komme. Deswegen>sind villeicht noch ein paar Bugs drin. Kompillieren lässt es sich aber>schon mal, das heisst aber nicht, dass die Anwendung klappt..
Richtig.
>Also, wenn ihr euch die Arbeit machen wollt, das Programm nochmal>durchzuschauen, hätte ich nichts dagegen ;-)
Done.
Ich hab mir mal die Arbeit gemacht, und dein Programm etwas gestrafft.
So sollte es am Ende aussehen, wenn man weiß was man tut. Ich hoffe du
erkennst dann, wie man das mit dem Multitasking real umsetzt und vor
allem auch WARUM!
Das Programm ist kompiliert vollständig, bei dir musst du jedoch die
drei defines unter //Workaround auskommentieren, da ich deine lcd.h
nicht hatte.
Njoy.
MFG
Falk
@ Don Panso (Gast)
>Hmmm, dann lese ich mir nochmal durch wie das mit den Timern und>Interrupts funktioniert. Wird wieder ne Weile dauern...
Das mach mal später. Vorerst brauchst du das nicht, es geht hier auch
gut ohne.
>Womit das dann für diesen Teil mit der Festkommaarithmethik erledigt>wäre... :-)
Woa, Falk!
Falk Brunner schrieb:> Ich hab mir mal die Arbeit gemacht, und dein Programm etwas gestrafft.
Mensch, dass hab ich nicht verlangt. Aber wenn es jetzt schon hier ist,
dann nutze ich das auch ;-)
Sei herzlichst bedankt!
Es ist natürlich immer besser sich etwas selbst zu erarbeiten, deswegen
nehme jetzt dein Programm und pflück das Zeile für Zeile auseinander, um
das auch zu verstehen und was für die Zukunft zu lernen. Das wird mir
sicherlich später noch weiter helfen.
Nochmals danke, auch an die Anderen, die hier gepostet haben! Danke,
dass ihr eure Zeit geopfert habt. Ich wusste, es lohnt sich hier im
Forum mal anzufragen.
So, heute wird das zwar nichts mehr...aber sobald ich Zeit habe setze
ich mich da dran und am Montag teste ich das mit allen Komponenten. Dann
lasse ich es euch auch wissen, wie gut das funktioniert (falls es euch
dann noch interessiert ;-) ).
Danke nochmal an alle!
Beste Grüße,
Don Panso
Don Panso schrieb:> ach das musste man dann so schreiben, oder?>> druckwertspannung = ((adcwert_druck*493.0)/102400.0);>> Womit das dann für diesen Teil mit der Festkommaarithmethik erledigt> wäre... :-)
Nicht unbedingt.
Wenn du endlich mal anfangen würdest, Formeln zusammenzufassen und
umzustellen ....
Hallooooooo, da bin ich wieder!
Falk, ich bin dein letztes Programm durchgegangen und habe mir erlaubt,
einige Änderungen vorzunehmen. Zum einen habe ich die lcd-Funktionen an
meine lcd.h angepasst (ich packe die mit dem Programm in den Anhang,
falls du das nochmal durchgucken möchtest; die lcd.h habe ich von
P.Fleury downgeloaded). Ausserdem habe ich:
-ADC-Einstellungen an meine Gegebenheiten angepasst (externes AREF vom
STK500 nutzen; Prescaler 16)
-in der Funktion "my_print_LCD()" das Überprüfen auf ein Minus-Zeichen
neutralisiert, da wir sowieso mit uint arbeiten und die Funktion bei
einem fehlenden Minus-Zeichen ein überflussiges Leerzeichen raushauen
würde
-die Parameter für die Funktion "my_print_LCD()" geändert. Der
Funktionsaufruf sieht jetzt so aus: "my_print_LCD(str_buffer, 7, 9,
1);". In den Variablen "uint32_t druck" und "uint32_t flow" kann maximal
eine dreistellige Zahl stehen (wenn 4.93V als Messsignal anliegen). Das
habe ich gemacht, da der Platz auf dem Display begrenzt ist und die
Funktion "my_print_LCD()" führende Nullen als ein Leerzeichen auf dem
Display ausgeben würde.
-der Alarm hört jetzt nicht nur auf Tastendruck auf, sondern auch, wenn
sich die Werte wieder innerhalb der Grenzen befinden
Ich hoffe du nimmst mir die Änderungen nicht übel und sofern diese nicht
totaler Blödsinn sind und mir jemand mit einem actionreifen Hechtsprung
zuvorkommt werde ich diese Version des Programmes morgen in der Praxis
mal ausprobieren.
So denn Leute, einen schönen Sonntag noch!
P.S.: Reine Verständnisfrage an Falk: die Aktualisierungsdauer von
AD-Wandlung und Anzeige hast du eingestellt, indem du die Variable
"uint8_t loop_cnt" unendlich lang hoch zählen lässt. Das Rückstellen auf
'0' geschieht ja quasi durch einen overflow, da eine 8-bit-Variable ab
dem Wert 256 zu wenig bits hat. Hat das nicht negative Folgen? In einer
weit zurückliegenden Vorlesung habe ich mal gehört, dass z.B. Strings
bei einem overflow nachfolgende Adressen verändern. Bei integern
passiert nichts?
@ Don Panso (Gast)
>Falk, ich bin dein letztes Programm durchgegangen und habe mir erlaubt,>einige Änderungen vorzunehmen.
Mach ur, es war ja schliesslich dein Programm ;-)
>-die Parameter für die Funktion "my_print_LCD()" geändert. Der
Naja, die Zahlen waren nur aus der Hüfte geschossen, sowas kann man bein
Testen leicht und schnell anpassen.
>-der Alarm hört jetzt nicht nur auf Tastendruck auf, sondern auch, wenn>sich die Werte wieder innerhalb der Grenzen befinden
Ob das so eine gute Idee ist?
>P.S.: Reine Verständnisfrage an Falk: die Aktualisierungsdauer von>weit zurückliegenden Vorlesung habe ich mal gehört, dass z.B. Strings>bei einem overflow nachfolgende Adressen verändern.
Das ist aber ein anderer Overflow. Wenn bei einem String das
Terminierungszeichen 0x0 üerschrieben wird, dann gibt es Ärger, wenn
andere Routinen darauf zugreifen, weils sie dann entweder einen riesigen
String ausgeben, weil sie endlos nach dem Ende suchen, oder wenn sie den
Strin und nachfolgenden Speicher überschreiben.
> Bei integern passiert nichts?
Erstmal nichts. Denn egal ob Üverflow oder nicht, es wird KEIN anderer
Speicher beeinflußt. Allerding können Arithmetische Rechnungen
fehlschlagen wegen eines Overflows, vor allem unbemerkt in
Zwischenergebnissen in Formeln. Hier ist das aber gänzlich unkritisch.
MfG
Falk
Moin, moin!
Falk Brunner schrieb:>>Falk, ich bin dein letztes Programm durchgegangen und habe mir erlaubt,>>einige Änderungen vorzunehmen.>> Mach ur, es war ja schliesslich dein Programm ;-)
Ja, es WAR mein Programm. Auf deine Änderungen wäre ich im Leben nicht
gekommen. Oder villeicht erst nach Stunden härtester Denkarbeit. Es ist
gut ein Programm zu sehen, dass von jemandem stammt, der sich auskennt.
Da lernt man was für die Zukunft und man gewinnt unwahrscheinlich an
Erfahrung dazu.
Falk Brunner schrieb:>>-der Alarm hört jetzt nicht nur auf Tastendruck auf, sondern auch, wenn>>sich die Werte wieder innerhalb der Grenzen befinden>> Ob das so eine gute Idee ist?
Warum? Das kannst du nicht wissen, aber es handelt sich um ein Prozess,
bei dem es keine nachhaltigen Folgen hat, wenn die Werte mal kurz
abweichen. Nehmen wir an, der Volumenstrom weicht für eine Sekunde ab.
Dann hört der Nutzer den Alarmton einmal und wird aufmerksam. Ich denke,
es ist nicht so toll, wenn er dann extra noch den Taster drücken muss,
weil der Wert mal kurz abgewichen ist, zumal der gleichzeitig noch
andere Dinge zu tun hat...aber, um ehrlich zu sein: geredet habe ich
darüber mit dem späteren Nutzer noch nicht. Das sollte ich villeicht mal
machen, um zu sehen wie seine Präferenzen diesbezüglich sind. Wie sind
deine Erfahrungen?
Nun denn, ich geh jetzt erst mal Kaffee trinken und dann wird getestet!
Grüße,
D. Panso
Don Panso schrieb:> darüber mit dem späteren Nutzer noch nicht. Das sollte ich villeicht mal> machen, um zu sehen wie seine Präferenzen diesbezüglich sind. Wie sind> deine Erfahrungen?
Das es davon abhängt mit wem du redest.
Wenn du mit dem Chef redest, dann ist der daran interessiert seine
'Maschinen' zu schonen: Jeder Alarm muss gemeldet werden und solange das
'Problem' nicht behoben ist, geht die Sirene auch nocht aus.
Wenn du mit dem Maschinenbediener redest: Wenn mir 5 Maschinen
gleichzeitig die hucke voll hupen, artet das in Stress aus. Am liebsten
wär mir ein optisches Signal mit der Möglichkeit manuell die Sirene
zuschalten zu können.
@ Karl heinz Buchegger (kbuchegg) (Moderator)
>Wenn du mit dem Maschinenbediener redest: Wenn mir 5 Maschinen>gleichzeitig die hucke voll hupen, artet das in Stress aus.
Sicher, aber wenn es was WICHTIGES ist, MUSS es auffallen und nerven.
Sinnvollerweise solle natürlich was Unwichtiges a) nicht dauernd
anschlagen und b) nicht so nerven.
@ Don Panso (Gast)
>gekommen. Oder villeicht erst nach Stunden härtester Denkarbeit. Es ist>gut ein Programm zu sehen, dass von jemandem stammt, der sich auskennt.>Da lernt man was für die Zukunft und man gewinnt unwahrscheinlich an>Erfahrung dazu.
Das ist der Sinn der Sache ;-)
>Warum? Das kannst du nicht wissen, aber es handelt sich um ein Prozess,>bei dem es keine nachhaltigen Folgen hat, wenn die Werte mal kurz>abweichen. Nehmen wir an, der Volumenstrom weicht für eine Sekunde ab.>Dann hört der Nutzer den Alarmton einmal und wird aufmerksam. Ich denke,>es ist nicht so toll, wenn er dann extra noch den Taster drücken muss,>weil der Wert mal kurz abgewichen ist, zumal der gleichzeitig noch>andere Dinge zu tun hat...
Dann sollte man noch sowas wie eine Entprellung einbauen. Sprich, das
Hupen geht erst los, wenn der Alarm für ein paar Sekunden aktiv ist. Das
Erspart die kurzen Hupsignale, wenns mal nur bisschen an der Grenze
zappelt.
>Nun denn, ich geh jetzt erst mal Kaffee trinken und dann wird getestet!
Wir sind gespannt.
MFg
Falk
Falk Brunner schrieb:> Dann sollte man noch sowas wie eine Entprellung einbauen. Sprich, das> Hupen geht erst los, wenn der Alarm für ein paar Sekunden aktiv ist. Das> Erspart die kurzen Hupsignale, wenns mal nur bisschen an der Grenze> zappelt.
Und dank vernünftiger Programmstruktur ist das jetzt noch nicht mal eine
Hexerei :-)
Aber erst mal soll er seinen nicht funktionierenden 'Alarm aus Knopf' in
Gang bringen.
Ok, ich hab mal getestet mit folgendem Ergebnis:
Karl heinz Buchegger schrieb:> Aber erst mal soll er seinen nicht funktionierenden 'Alarm aus Knopf' in> Gang bringen.
:-D du hast recht Karl. Das ist mir nicht aufgefallen. Momentan muss man
den Taster die ganze Zeit gedrückt halten, damit der Alarm einen nicht
permanent wegpustet. Da habe ich nicht aufgepasst...hätte ich mal früher
hier reingeschaut. Das wird geändert, aber erst mal Mittagessen ;-)
Bis auf die Sache mit dem Taster funktioniert aber ansonsten alles
einwandfrei.
Mahlzeit!
D. Panso
Don Panso schrieb:> Ok, ich hab mal getestet mit folgendem Ergebnis:>> Karl heinz Buchegger schrieb:>> Aber erst mal soll er seinen nicht funktionierenden 'Alarm aus Knopf' in>> Gang bringen.>> :-D du hast recht Karl. Das ist mir nicht aufgefallen. Momentan muss man> den Taster die ganze Zeit gedrückt halten, damit der Alarm einen nicht> permanent wegpustet. Da habe ich nicht aufgepasst...hätte ich mal früher> hier reingeschaut. Das wird geändert, aber erst mal Mittagessen ;-)> Bis auf die Sache mit dem Taster funktioniert aber ansonsten alles> einwandfrei.
Mach dir 2 Variablen
die eine zeigt an, ob eine Alarmsituation vorliegt
die andere ob der Alarm gemeldet werden soll
Zuviel 'Funktionalität' in eine Variable zu packen führt oft zu solchen
'Problemen'. Momentan ist deine 'alarm' Variable beides in
Personalunion.
Wenn du das Melden vom Auftreten des Alarms trennst, kannst du gleich
die 'alarm' Variable zu einem Zähler umfunktionieren, die mitzählt wie
oft die Alarmsituation in Folge vorlag und nur dann wenn, Hausnummer,
500 mal hintereinander eine Alarmsituation war, die Heulboje in Gang
bringen (die dann vom Benutzer mittels 'alarmAllowed' wieder abgewürgt
werden kann)
Ich habe diesen Thread mit Interesse verfolgt...
Ich komme aus einem Kraftwerk, wo wir diverse PLS-Systeme haben...
Aus Sicherheitstechnischer Sicht wäre es sinnvoll, wenn der Alarm beim
Überschreiten/Unterschreiten an geht, und erst wieder ausgeht, wenn der
Benutzer reagiert hat, Knopf gedrückt zum Bleistift. Außerdem wird der
Alarm angezeigt (Das Ausrufezeichen, was ich irgendwo oben gelesen habe)
Aber wenn nun der Werte um die Alarmgrenze rumschwankt, kommt man aus
dem Drücken nicht mehr raus. Interessant wäre hierzu eine Hysterese.
Wert darf sich innerhalb 20 und 30 befinden - Wert geht auf 30,2 - Alarm
geht an, Ausrufezeichen kommt - Knopf wird gedrückt, Hupe geht aus,
Ausrufezeichen bleibt - jedoch, erst wenn der Wert die 29 erreicht hat,
geht auch das Fragezeichen weg.
Auch, wenn der der Wert dann von 30,2 auf 29,5 (Fragezeichenist noch da)
und dann wieder auf 30,1 geht, kommt die hupe wieder.
Was passiert, wenn der erste wert schon im Alarm ist, und der zweite
Wert sollte nun einen Alarm bringen - kommt der dann auch???
Gruß Blackmore
So, Leute!
Es ist vollbracht. Nach einer weiteren Änderung funktioniert nun alles
so wie es soll. Dazu habe ich, wie Karl es vorgeschlagen hat, eine
zweite Variable "uint8_t alarm_allowed = 1" eingefügt, die auf den
Taster reagiert und bei Tastendruck zu '0' wird. Die Variable "uint8_t
alarm = 0" wird zu '1' gesetzt sollten die Messwerte von den Grenzen
abweichen. Der Alarm wird nur abgespielt, wenn beide Variablen gleich
'1' sind und rückgesetzt, wenn die Messwerte wieder innerhalb der
Grenzen sind.
Ich habe es mit dem späteren Nutzer abgesprochen und er meinte diese
Lösung sei gut. Sollte ein Wert nur kurz abweichen, ertönt auch der
Alarmton nur kurz, so dass man aufmerksam wird und weiter verfolgt, ob
sich villeicht mehr tut. Deswegen habe ich deine Idee, Karl, mit dem
Warten auf längere Abweichung der Werte nicht umgesetzt. Nimm mir das
bitte nicht übel.
Ansonsten folge ich mal der Netiquette (ja, ich habe es durchgelesen)
und mache einen Abschlussbericht.
Folgendes Projekt wurde erfolgreich umgesetzt:
-Messung zweier verschiedener Spannungen mit dem ADC eines ATmega16 auf
einem STK500
-Umrechnung der Werte in die dazugehörigen physikalischen Größen und
Anzeige dieser auf einem LC-Display
-bei Abweichen der Größen von festgelegten Grenzen ertönt ein Alarmton,
den man per Taster abstellen kann. Sind die Größen wieder innerhalb der
Grenzen, wird der Alarm ebenfalls wieder abgestellt.
-Speicherplatzbedarf wurde durch Festkommaarithmetik gesenkt und
Multitasking wurde angewendet
Ausserdem habe ich noch fix eingefügt (noch nicht getestet):
-Pause zwischen den Alarmtönen, so dass der nicht nahtlos vor sich
hindudelt
Ein herzliches Dankeschön an alle, die hier Vorschläge gemacht und dazu
beigetragen haben, das dieses Programm auf ein professionelleres Niveau
gehoben wird und es nun auch wirklich das tut, was es soll. Speziell
auch ein Dankeschön an Falk, der sich die Mühe gemacht hat, das Programm
selbst zu bearbeiten und deutlich zu verbessern. Ich schmücke mich
ungern mit fremden Lorbeeren, aber wenn mir die schon coolant angeboten
werden... ;-)
Ich möchte an der Stelle anmerken, dass ich das Programm nicht einfach
blind übernommen habe, sondern ich bilde mir ein, Falks sehr gute
Herangehensweise Verstanden zu haben, so dass ich schließlich sogar
selbst Veränderungen durchführen konnte. Sicherlich werden mir die
neugewonnenen Erfahrungen in Zukunft nochmal helfen.
Sollten später nochmal bei anderen Dingen Probleme auftreten, werde ich
mich wieder an die hilfreichen Leute in diesem Forum wenden, aber
diesmal mit einem durchdachteren Thread-Titel ;-)
So genug mit dem Kitsch :-) Ich stelle die vorerst endgültige Fassung
des Programms in den Anhang, für den Fall, dass das nochmal jemand
betrachten möchte. Diesem Thread werde ich noch ein Weilchen folgen.
Weitere Vorschläge werden also registriert. Kann ja auch sein, dass ich
doch totalen Mist gebaut habe und mich jemand warnen will.
Ach und Blackmore: herzlichen Dank auch für dein Interesse. Das Programm
funktioniert jetzt wie gewünscht, deswegen belasse ich das vorerst so.
Ich werde deine Vorschläge aber, wenn die Zeit es zulässt, in einer
späteren Version berücksichtigen.
Danke nochmal an alle. Und frohes Schaffen noch!
Beste Grüße,
Don Panso
Don Panso schrieb:> sich villeicht mehr tut. Deswegen habe ich deine Idee, Karl, mit dem> Warten auf längere Abweichung der Werte nicht umgesetzt. Nimm mir das> bitte nicht übel.
Sowieso nicht.
Dein (hoffentlich zahlender) Kunde hat das letzte Wort.
Was du aus dem Projekt mitnehmen solltest, ist der grundsätzliche
Programmaufbau:
* keine oder wenn, dann nur sehr kurze delays
* immer nur ein kleines Stückchen Arbeit machen lassen
* das dafür reihum wieder und immer wieder
* 1000 mal 1 Millisekunde gewartet ergibt in Summe auch wieder
1 Sekunde Wartezeit
Das ist der prinzipielle Programmaufbau, mit dem du wahrscheinlich mehr
als 95% aller µC typischen Problemstellungen bewältigen kannst. Selbst
dann, wenn es anfänglich so aussieht als ob kein 'Multitasking'
notwendig ist, lohnt sich dieser Aufbau trotzdem: Er macht nicht viel
Ärger, ist einfach und für den Fall der Fälle birgt er
Entwicklungspotential.
Das andere, was du mitnehmen sollst:
Floating Point braucht man eher selten, Formeln ruhig am Papier
zusammenfassen, ausrechnen und umstellen, dann kann man vieles mit
Ganzzahlarithmetik erschlagen, auch wenn es am Anfang nicht so aussieht.
@ Don Panso (Gast)
>Es ist vollbracht.
Wenn das mal nicht vorschnell ist . . .
>so wie es soll. Dazu habe ich, wie Karl es vorgeschlagen hat,
Nöö, du hast Kuddelmuddel programmiert. Karl hat was von einem ZÄHLER
erzählt.
Ausserdem hast du dein Grenzwerte für den Druck verändert. Absicht oder
Fehler?
Ich dachte negativer Druck ist sowieso nicht praxisrelevant.
>abweichen. Der Alarm wird nur abgespielt, wenn beide Variablen gleich>'1' sind und rückgesetzt, wenn die Messwerte wieder innerhalb der>Grenzen sind.>Ich habe es mit dem späteren Nutzer abgesprochen und er meinte diese>Lösung sei gut. Sollte ein Wert nur kurz abweichen, ertönt auch der>Alarmton nur kurz, so dass man aufmerksam wird und weiter verfolgt, ob>sich villeicht mehr tut.
Schön, aber dazu braucht man keine zweite Variable, diese Funktion war
vorher auch schon da.
>-bei Abweichen der Größen von festgelegten Grenzen ertönt ein Alarmton,>den man per Taster abstellen kann. Sind die Größen wieder innerhalb der>Grenzen, wird der Alarm ebenfalls wieder abgestellt.
Hast du das mal WIRKLICH KOMPLETT getestet?
Denn was bei dir nämlich passiert ist, dass wenn deine Werte ausserhalb
der zulässigen Grenzen sind, dein Bediener genervt den Knopf drückt,
dabei den Alarm abschaltet, aber solange die Wert immer noch ausserhalb
des Sollbereichs sind KEIN Alarm mehr ertönt!! D.h. deine Anlage läuft
OHNE Alarm dauerhaft ausserhalb der Parameter! Der wird erst wieder
scharf geschaltet, wenn die Werte im Normalbereich sind. Ich kann mir
nicht vorstellen, dass das gewünscht oder akzeptabel ist. Und das hat
auch nichts mit Entprellung zu tun!
>-Speicherplatzbedarf wurde durch Festkommaarithmetik gesenkt
Wieviel? Wieviel braucht dein erstes Programm, wieviel das Neune?
> und Multitasking wurde angewendet
;-)
>Ausserdem habe ich noch fix eingefügt (noch nicht getestet):>-Pause zwischen den Alarmtönen, so dass der nicht nahtlos vor sich>hindudelt
Hört auf mit so einem Gemurkse! Man postet keinen Code, der nicht
getestet ist! Das ist Müll!!!
>So genug mit dem Kitsch :-) Ich stelle die vorerst endgültige Fassung>des Programms in den Anhang, für den Fall, dass das nochmal jemand>betrachten möchte.
Done.
MfG
Falk
Hallo, kurze Meldung nochmal!
Karl heinz Buchegger schrieb:> Dein (hoffentlich zahlender) Kunde hat das letzte Wort.
Dafür kriege ich kein Geld. Das ist alles Teil eines Bachelorprojekts
:-)
Don Panso schrieb:> Ausserdem habe ich noch fix eingefügt (noch nicht getestet):> -Pause zwischen den Alarmtönen, so dass der nicht nahtlos vor sich> hindudelt
Da war ich Dämel zu vorschnell. Das klappt so natürlich nicht! Das wird
geändert.
Karl heinz Buchegger schrieb:> Was du aus dem Projekt mitnehmen solltest, ist der grundsätzliche> Programmaufbau...Karl heinz Buchegger schrieb:> Das andere, was du mitnehmen sollst:> Floating Point braucht man eher selten, Formeln ruhig am Papier> zusammenfassen...
Ist gebongt ;-)
Später stell ich hier villeicht noch eine perfekte, einwandfrei
funktionierende Version des Programms rein.
So denn, Adieu!
Es gibt kein perfektes Programm, irgendwer hat immer noch irgendwas
auszusetzen...
Aber ein Listing eines Programmes, was die geforderten Dinge tut wäre
schon interessant...
Wenns dich noch interessiert: Noch eine kleine 'Manöverkritik' zum Thema
"Do's und Don't do's in C"
* Gib Pins die eine spezielle Bedeutung haben, einen Namen.
Das erleichtert das Verständnis dessen, was im Code vor sich geht,
macht so manchen Kommentar überflüssig (und das sind die allerbesten
Kommentare: die die keiner braucht und die daher rausfliegen)
und erleichtert auch Hardware-Umbauten.
Beispiel:
1
voidfail_sound(void){
2
3
staticuint16_thilf=200;
4
5
if(hilf>100&&hilf<=200){
6
/* Frequenz ca. 391Hz */
7
PORTC|=(1<<PC6);
8
_delay_ms(1.28);
9
PORTC&=~(1<<PC6);
10
_delay_ms(1.28);
11
}elseif(hilf>0&&hilf<=100){
12
/* Frequenz ca. 132Hz */
13
PORTC|=(1<<PC6);
14
_delay_ms(3.8);
15
PORTC&=~(1<<PC6);
16
_delay_ms(3.8);
17
}elsehilf=500;
18
hilf--;
19
}
Da mitten drinn ist die Hardwarebeschaltung versteckt. Aus dem
Zusammenhang wird zwar irgendwann ersichtlich, dass am Pin PC6 wohl ein
Lautsprecher hängen wird, aber warum nicht Nägel mit Köpfen machen
1
#define SUMMER_PORT PORTC
2
#define SUMMER_DDR DDRC
3
#define SUMMER_PIN PC6
4
5
...
6
7
voidfail_sound(void){
8
9
staticuint16_thilf=200;
10
11
if(hilf>100&&hilf<=200){
12
/* Frequenz ca. 391Hz */
13
SUMMER_PORT|=(1<<SUMMER_PIN);
14
_delay_ms(1.28);
15
SUMMER_PORT&=~(1<<SUMMER_PIN);
16
_delay_ms(1.28);
17
}
18
elseif(hilf>0&&hilf<=100){
19
/* Frequenz ca. 132Hz */
20
SUMMER_PORT|=(1<<SUMMER_PIN);
21
_delay_ms(3.8);
22
SUMMER_PORT&=~(1<<SUMMER_PIN);
23
_delay_ms(3.8);
24
}
25
else
26
hilf=500;
27
28
hilf--;
29
}
30
31
....
32
33
intmain()
34
{
35
....
36
37
SUMMER_DDR|=(1<<SUMMER_PIN);// war: DDRC = 0xFF;
38
39
....
40
41
}
jetzt hast du die komplette 'Konfiguration' für den Summer an einer
Stelle beisammen. Gibt es Änderungen, musst du nur an die #define ran
und dort die korrekten Werte eintragen. Der Rest des Programms passt
sich von alleine an.
Port, DDR und Pin für den Taster wären die nächsten Kandidaten.
Grundsätzlich: Wenn du im Code die Bezeichnungen PORTx, PINx etc.
benutzen musst, dann solltest du darüber nachdenken, dir da spezielle
#define dafür zu machen.
* keine magischen Konstanten mitten im Code
1
if((druck>3)||
2
(druck<0)||
3
(flow>105)||
4
(flow<95)){
Wenn dein Kunde andere Grenzwerte will, musst du den kompletten Code
durchforsten, wo diese Grenzwerte eingetragen sind. Ganz schlimm wird es
dann, wenn dieselbe magische Konstante (in derselben Bedeutung) an
mehreren Stellen vorkommt. Aber selbst dann, wenn nicht, lohnt sich auch
hier ein #define
1
#define DRUCK_MIN_WERT 0
2
#define DRUCK_MAX_WERT 3
3
#define FLOW_MIN_WERT 95
4
#define FLOW_MAX_WERT 105
5
6
...
7
8
if(druck<DRUCK_MIN_WERT||druck>DRUCK_MAX_WERT||
9
flow<FLOW_MIN_WERT||flow>FLOW_MAX_WERT)
das gibt dir dann auch einen guten Platz, an dem du dokumentiern kannst,
wie sich die Werte eigentlich berechnen. Denn ein Flow Wert von 95 sagt
dir in einem halben Jahr gar nichts mehr.
Ideal ist es, wenn du die Werte aus für den Benutzer interessierenden
Werten automatisch berechnen lassen kannst. Dann brauchst du bei einer
Änderung nicht lange nachdenken, sondern setzt den Wert einfach so ein,
wie ihn dir dein Kunde mitteilt und der Compiler rechnet diesen Wert aus
dem Benutzersystem in dein internes Zahlensystem um. Dann hast du das
Beste aus 2 Welten: zum einen dokumentierst du die Umrechnung, zum
anderen hast du bei einer Änderung wenig Arbeit.
* vermeide Variablennamen wie temp, hilf oder anderen nichtssagenden
Begriffen. Der Zähler in fail_sound hat eine spezielle Bedeutung. Der
hat sich schon einen besseren Namen als 'hilf' verdient. Genauso das
'flag' in my_print_LCD. Flag ist ein Gattungsbegriff für eine bestimmte
Funktionalität die eine Variable haben kann. In diesem Fall zeigt sie
an, ob eine 0 eine führende 0 sein kann. Warum nennst du die dann nicht
einfach 'trailingZero' oder so ähnlich. Dann brauchst du den Kommentar
nicht mehr (und wie bereits gesagt: Ein Kommentar der wegfällt ist ein
guter Kommentar)
Karl heinz Buchegger schrieb:> * keine magischen Konstanten mitten im Code> if( (druck > 3) ||> (druck < 0) ||> (flow > 105) ||> (flow < 95) ) {>> Wenn dein Kunde andere Grenzwerte will, musst du den kompletten Code> durchforsten, wo diese Grenzwerte eingetragen sind. Ganz schlimm wird es> dann, wenn dieselbe magische Konstante (in derselben Bedeutung) an> mehreren Stellen vorkommt. Aber selbst dann, wenn nicht, lohnt sich auch> hier ein #define> #define DRUCK_MIN_WERT 0> #define DRUCK_MAX_WERT 3> #define FLOW_MIN_WERT 95> #define FLOW_MAX_WERT 105
Nicht nur das... später hinaus willst Du vielleicht die Grenzwerte vom
Kunden selbst via Menü bestimmen lassen, und dann müsstest DU im
gesamten Programmcode, ähm...
So musst Du nur gucken, steht im EPROM ein selbst bestimmter Wert, also
überschreibe ich den Standartwert mit dem neuen, und schon gibt es neue
Grenzwerte...
Gruß Blacky
Falk Brunner schrieb:>>Es ist vollbracht.>> Wenn das mal nicht vorschnell ist . . .
Leider wahr :-(
Falk Brunner schrieb:> Nöö, du hast Kuddelmuddel programmiert. Karl hat was von einem ZÄHLER> erzählt.
Dazu sage ich:
Don Panso schrieb:> Deswegen habe ich deine Idee, Karl, mit dem> Warten auf längere Abweichung der Werte nicht umgesetzt. Nimm mir das> bitte nicht übel.Falk Brunner schrieb:> Ausserdem hast du dein Grenzwerte für den Druck verändert. Absicht oder> Fehler?
Gut aufgepasst! Das war Absicht. Da ich die Vorrichtung, die den
Differenzdruck erzeugt noch nicht habe, misst der Differenzdruckmesser
erstmal nichts. Um negative Werte zu verhindern habe ich noch ein wenig
an der Formel für die Umrechnung in den physikalischen Wert gedreht. Das
wird natürlich später wieder geändert.
Falk Brunner schrieb:> Hast du das mal WIRKLICH KOMPLETT getestet?> Denn was bei dir nämlich passiert ist, dass wenn deine Werte ausserhalb> der zulässigen Grenzen sind...
Ja, dass war auch so angedacht wie du es beschreibst.
Falk Brunner schrieb:> Wieviel? Wieviel braucht dein erstes Programm, wieviel das Neune?
Poste ich später...
Falk Brunner schrieb:> Hört auf mit so einem Gemurkse! Man postet keinen Code, der nicht> getestet ist! Das ist Müll!!!
Sorry, Lektion gelernt.
Blackmore schrieb:> Es gibt kein perfektes Programm...
War auch nicht ganz ernst gemeint...
Blackmore schrieb:> Aber ein Listing eines Programmes, was die geforderten Dinge tut wäre> schon interessant...
Kommt auch noch :-)
Karl heinz Buchegger schrieb:> Noch eine kleine 'Manöverkritik'
Kritik dankbar angenommen.
Uff, so jetzt wieder frisch an die Arbeit...
Don Panso schrieb:> Blackmore schrieb:>> Es gibt kein perfektes Programm...>> War auch nicht ganz ernst gemeint...
War auch nicht böse gemeint...
Aber ich sehe es bei mir... PHP programmiert, alles perfekt, dann kommt
der Auftraggeber und will noch irgendeinen sh***... und ich armer Tropf
darf jetzt den gesamten Code durchforsten, nur weil der irgendwo ein
Punkt grundsätzlich haben waill...
Aber ich muss eigentlich ruhig sein, hab seit einer Woche mein
Atmel-Zeug hier und nicht mal den µC aufs Steckboard draufgesteckt,
geschweige denn mal Strom drauf gegeben...
Aber um nochmal auf mein Posting oben zurück zu kommen - Usereingabe von
Grenzwerten...
Ein kommendes Projekt von mir sieht auch eine Steuerung eines Lüfters
vor, mit Luftfeuchte und Temperatur. Der Nutzer, der es nutzen will,
kann mir keine Grenzwerte sagen - muss man im laufenden Betrieb sehen,
wie sich das ganze verhält... Aber jedesmal 80km fahren, nur um die
Grenzwerte zu ändern... bäh... also dann lieber 5 Taster mehr
anstöpseln, und die Einstellung den User machen lassen - da siegt meine
eigene Faulheit...
Gruß Blacky
Hey Blacky!
Blackmore schrieb:> Usereingabe von Grenzwerten...
Ich verstehe deinen Einwand. Sicherlich wäre das eine ganz nette
Funktion. Dennoch ist sie in meiner Anwendung nicht notwendig, denn sind
die Grenzwerte einmal festgelegt, dann bleiben die auch. Was ich mache,
ist ein sogenanntes SMPS aufzubauen. Mit dem misst man die
Partikelanzahlkonzentration in der Luft in Abhängigkeit von der Größe
der Partikel. Für das Messprinzip ist es absolut notwendig, dass die
Luftvolumenströme, einer mit Hilfe des Volumenstromsensors und der
andere mit Hilfe des Differenzdrucks über ein Bauteil im Luftstrom
gemessen, durch das Gerät konstant bleiben. Das habe ich bereits
erreicht.
Diese Sache hier mit der Überwachung der Werte mit Hilfe des
Mikrocontrollers ist eigentlich reine Spielerei und für das Messprinzip
nicht relevant. Wir müssen jetzt nur noch schauen, wie der
Differenzdruck über einem Bauteil beim erwünschten Volumenstrom ist,
dann stehen auch dort die Grenzwerte absolut fest. Wenn alles gut geht
dürfte sich in der Richtung auch nichts ändern.
Klar ist das mit der Usereingabe auch ein nettes Feature, aber hier
nicht wirklich notwendig...Sorry, aber da siegt meine Faulheit ;-)
Viel Erfolg noch mit deinem Projekt. Das was in diesem Thread vor sich
geht ist sicherlich hilfreich für dich. Ich beeile mich und korrigiere
das Programm so gut es von meiner Seite aus geht...
Grüße,
Don Panso
Don Panso schrieb:> Ich verstehe deinen Einwand. Sicherlich wäre das eine ganz nette> Funktion. Dennoch ist sie in meiner Anwendung nicht notwendig, denn sind> die Grenzwerte einmal festgelegt, dann bleiben die auch.
Du musst noch viel lernen, ehe du in die betriebliche Praxis entlassen
werden darfst :-)
Eines der ehernen Gesetze in der kundenorientierten Programmierung
lautet:
Betrachte alle dir vom Kunden genannten Konstanten als variabel. Denn
genau das sind sie auch. :-)
(Das zweitwichtigste lautet:
Sagt dir dein Kunde 'Das brauchen wir nicht, das kommt bei uns nicht
vor!', dann spitz die Ohren. Genau das sind dann die Fälle, auf denen
bei der Abnahme herumgeritten wird.
:-D @Karl & Blacky: ihr zwei habt da offensichtlich Erfahrung. Da kann
ich natürlich nichts gegen sagen. Wie aber bereits erwähnt mache ich
hier mein Bachelorprojekt...da ist alles halb so wild. Die drücken auch
mal ein Auge zu und ich bin immer noch der Meinung, dass sich die
Grenzwerte nicht ändern werden :-P
Ich werde eure Erfahrungsberichte dennoch im Hinterkopf behalten für den
Fall eines zukünftigen Kundenkontaktes.
Ich habe mich mal daran verucht, dass Programm noch ein wenig mehr zu
verändern...mit nicht ganz erwünschten Folgen. Ich weiss schon wodran es
liegt. Es braucht aber Zeit, das Problem zu lösen. Testen kann ich das
erst morgen und solange werde ich es nicht posten, um mir erneute
Schelte zu ersparen :'-(
Also dann, schönen Feierabend Jungs!
Vielen Dank für das Vertrauen, welches Du in mich setzt...
Jedoch muss ich zu meiner Entschuldigung sagen: Freitag hab ich meinen
ERSTEN Atmel Mikroprozessor in den Händen gehalten, nicht mal
programmiert hab ich die Dinger...
Asche auf mein Haupt...
Hallo Leute!
Ich melde mich hier aus dem verregneten Westen des Landes. Ich habe nun
eine Version des Programms getestet, die alles tut, was ich will
(muahahahaha) :-| . Diese Stelle ich nun in den Anhang. Ich denke, diese
Version werde ich nun endgueltig benutzen. Der "Abschlussbericht" steht
ja oben.
@ Karl
Um passendere Variablennamen habe ich mir jetzt noch keinen Kopf
gemacht. Zu einem späteren Zeitpunkt werde ich das noch ändern.
Falk Brunner schrieb:>>-Speicherplatzbedarf wurde durch Festkommaarithmetik gesenkt>> Wieviel? Wieviel braucht dein erstes Programm, wieviel das Neune?
Altes Programm (siehe erster Post):
Größe, der hex-file: 10,4KB
Neuste Version:
Größe, der hex-file: 4,22KB
Schon ein ziemlicher Unterschied...
Blackmore schrieb:> Vielen Dank für das Vertrauen, welches Du in mich setzt...
Ach, jeder fängt mal klein an. Sieh mich an. Ich kann dir nur den Rat
geben, das Tutorium auf dieser Seite mal anzuschauen und ein paar
Beispiele auszuprobieren. Zum Testen vom Mikrocontrollern eignet sich
das STK500 recht gut. Ich habe damit nur positive Erfahrungen gemacht.
Einfach in den Sockel stecken und programmieren. Ist mit ca. 75Euronen
auch noch knapp erschwinglich. Des weiteren helfen die Datenblätter der
ATmegas auch sehr gut. Dort gibt es dann auch Beispiele, wie man z.B.
eine Messung mit dem ADC durchführt usw.
Und wenn nichts mehr hilft, dann guck mal in diesem Forum nach, ob nicht
jemand das selbe Problem hat wie du. Wenn du nichts findest, eröffne
selbst ein Thread und es wird dir schon jemand helfen (schau dir diesen
Thread an). Und das wichtigste: nicht ohnmächtig werden ;-) (bin
zufällig auf ein Kommentar von dir in einem anderen Thread gestossen).
So denn, falls ihr hier noch folgt...wenn es noch Kritik gibt: ich stehe
zur Verfügung. Danke für eure Geduld!
Bis dann!
Don Panso
Jetzt hab ich mir auch mal Deinen Code durchgelesen, und verstanden habe
ich nichts -kommt aber eher davon, das ich gar kein C kann...
Aber, jetzt habe ich noch Fragen, an alle, die hier mitlesen:
1
int main(void) {
2
3
uint32_t druckspannung;
4
uint32_t druck;
5
uint32_t flowspannung;
6
uint32_t flow;
7
uint8_t alarm_allowed = 1;
8
uint8_t alarm = 0;
9
char str_buffer[12];
10
uint8_t i;
11
uint8_t loop_cnt=0;
12
13
/* IOs konfigurieren */
14
15
TASTER_DDR = 0x00;
16
TASTER_PORT |= (1<<TASTER_PIN); // Pull Up für Taster
17
LAUTSPRECHER_DDR = 0xFF;
18
19
/*Display-Initialisierung*/
20
21
lcd_init(LCD_DISP_ON);
22
lcd_clrscr();
23
lcd_command(_BV(LCD_CGRAM)); /* set CG RAM start address 0;*/
24
25
/* Zeichen #0 mit Delta-Symbol neu definieren */
26
for(i=0; i<8; i++) {
27
lcd_data(pgm_read_byte(&deltaChar[i]));
28
}
29
30
lcd_home();
31
/* Statischen Text schreiben, 0 ist das selbstdefinerte Delta-Symbol*/
32
lcd_putc(0);
33
lcd_puts("p: mbar");
34
lcd_gotoxy(0,1);
35
lcd_puts("Flow: l/min");
36
37
/* ADC konfigurieren */
38
ADC_Init();
39
40
/* endlose Hauptschleife */
das uint32_t druckspannung; und Co deklariert mir verschiedene
Variablen???
Sollte ich wirklich die Hardware nach den Variablen initialisieren?
und das auch noch in der main?
Wie gesagt, ich habe noch keinen Plan von dem Ganzen, deswegen frage
ich...
Gruß Blacky
Hey Blacky...
Öhm, ich weiss nicht, ob das eine spezielle Regel für C ist, aber in
allen Programmen, die ich bisher gesehen habe, werden die Variablen am
Anfang der main deklariert...
War das deine Frage, oder habe ich etwas falsch verstanden?
He,
diese Variablen sind lokal definiert und deshalb auch nur in der Main
verwendbar, werden sie außerhalb des Mains (und etwaigen Funktionen)
deklariert sind es globale Variablen.
Ich hoffe ich habe deine Frage beantwortet (sofern ich sie richtig
verstanden hab)
mfg
Ber
Wie gesagt, ich kenne C nicht...
ich würde vielleicht am Anfang der main() einen Sprung zu einer
init-sequenz schreiben, in der init-sequenz werden mir alle inits
eingebastelt, die ich brauche, evtl. als include???
dadurch bekomme ich diese statischen dinge, die ich nur einmal machen
muss, und mir im Programm eigentlich nur unübersichtlichkeit bringe
weg...
Es sei denn, ich mach nen Denkfehler, und sowas DARF man gar nicht
machen...
@ Ber
ok, Erklärung verstanden... jetzt nur noch die Reihenfolge: macht es
Sinn, zuerst die Software und dann die Hardware zu deklarieren???
also zuerst die Variablen, und dann die Ports und LCD und und udn???
@ Blackmore (Gast)
>das uint32_t druckspannung; und Co deklariert mir verschiedene>Variablen???
Ja.
>Sollte ich wirklich die Hardware nach den Variablen initialisieren?
Warum nicht?
>und das auch noch in der main?
Das ist der Normalfall.
MFG
Falk
Blackmore schrieb:> ok, Erklärung verstanden... jetzt nur noch die Reihenfolge: macht es> Sinn, zuerst die Software und dann die Hardware zu deklarieren???> also zuerst die Variablen, und dann die Ports und LCD und und udn???
Du schmeisst da ein wenig die Dinge durcheinander.
Das hier
1
intmain(void){
2
3
uint32_tdruckspannung;
4
uint32_tdruck;
sagt lediglich aus:
* Es gibt eine Variable namens 'druckspannung' und die soll ein
uint32_t sein.
Damit ist an sich noch nichts weiter vereinbart, als das diese Variable
jetzt 'zur Welt kommt'. Mehr nicht.
Die Hardware selbst wird nicht deklariert. Die ist schon da.
Aber sie wird am Programmanfang konfiguriert und in einen verwendbaren
Zustand gebracht.
Mit ein wenig Augenzwinkern kann man es so sehen:
Am Anfang wird die Umgebung in der sich das Programm bewegt festgelegt.
Diese Umgebung besteht aus Hardware und Variablen. Die Hardware gibt es
bereits, die ist von Anbeginn der Zeit vorhanden und fix. Die Variablen
gibt es noch nicht. Wenn main() zu laufen beginnt, erzeugt es seine
Variablen die es benötigt und erst damit ist dann seine Umgebung
vollständig.
Und nachdem dann die Umgebung vollständig ist, gehts los indem die
Hardware konfiguriert wird.
He,
im Prinzip ist es ganz egal was du zuerst deklarierst, aber die meisten
Programmierer setzen zuerst ihre Variablen auf und beschreiben erst dann
die Hardware.
Deklarieren einer Variablen bedeuted im Prinzip nur dass eine Variable
mit dem vergegebenm Namen und dem Typ "geboren" wird, sonst geschieht
nichts weiter, somit ist auch die Reihenfolge egal was zuerst gemacht
wird.
mfg
Ber
Ok,
danke für die Erklärung...
Ich stand halt auf dem Standpunkt, die Hardware ist schon vorhanden, nur
noch nicht vollständig eingestellt...
An der Software bastel ich noch, es ändern sich dadurch auch meine
Variablen...
Deswegen wollte ich die Hardware vollständig einrichten, Ports richtig
rum definieren, etc, und dann die Software mit ihren ganzen Variablen,
etc pp machen...
Da es letztlich egal scheint, wierum man das macht, denke ich, werde ich
für mich persönlich erst die Hardware aufbauen, in der Software richtig
einstellen, und dann alles, was rein Software ist machen...
So habe ich, für mich persönlich eine feste Richtung:
Hardware planen, aufbauen, einstellen in Software, Software ienstellen
(Variablen, etc), Software aufbauen d.h. programmieren...
Mal sehen, ob ich das dann einhalten kann, ich hoffe doch, das ich nicht
schon bei der zweiten Zeile Code alles anders mache...
Danke Euch... man liest sich bestimmt wieder...
Gruß Blackmore
Im Anfange schuf Gott Ports, Timer, ADC und Speicher. Und der Speicher
ward ohne Form und leer. Und Finsternis lag auf der Fläche der
SRAM-Bytes.
Und Gott sprach: "Es werde Memory Management"
Und es ward Memory Management!
Nun schwanden vor dem einsetzen Stackpointer, des schwarzen Dunkels
greuliche Unordnung. Der erste uint32_t enstand!
Und Gott sah den uint32_t und er sah das es gut war.
Und Gott sprach: Es initialisiere sich der Port, als das er als Eingang
benutzt werden kann. Auch initialisiere sich ein anderer Port um als
Ausgabefenster für das LCD zu dienen. (An dieser Stelle stutzte Gott ein
wenig, denn er hatte das LCD noch nicht erfunden, aber das machte
nichts, es war einfach da.)
Und die Ports initialisierten sich. Und Gott sah, dass es gut war.
@ Don Panso (Gast)
> * final_program_endgueltig.c (6,1 KB, 8 Downloads) | Codeansicht
Du solltest mit dem Wort "endgültig" etwas sparsamer sein.
Sinnvollerweise nutzt man Versionsnummern, zwei oder dreistellig.
>Version werde ich nun endgueltig benutzen. Der "Abschlussbericht" steht>ja oben.
Warum hast du das wieder mit den Pausen zwischen den Alarmtönen
geändert? Ging wohl nicht auf Anhieb? Was nicht verwunderlich ist, hilf
ist eine 8-Bit Variable, die kann man nicht auf 500 setzen ;-)
>Altes Programm (siehe erster Post):>Größe, der hex-file: 10,4KB>Neuste Version:>Größe, der hex-file: 4,22KB
Naja, Faktor 2,5, nicht schlecht, oder? Wobei das Hex-File nciht exakt
die Größe angiebt, die kann man aber sehr leicht im AVR-Studio ablesen,
in der Ausgabe beim Compilieren. Pi mal Daumen sind das knapp 2kB Flash.
MfG
Falk
Falk Brunner schrieb:>> * final_program_endgueltig.c (6,1 KB, 8 Downloads) | Codeansicht>> Du solltest mit dem Wort "endgültig" etwas sparsamer sein.> Sinnvollerweise nutzt man Versionsnummern, zwei oder dreistellig.
Jup stimmt. Beim nächsten mal wird das beachtet.
Falk Brunner schrieb:> Warum hast du das wieder mit den Pausen zwischen den Alarmtönen> geändert? Ging wohl nicht auf Anhieb? Was nicht verwunderlich ist, hilf> ist eine 8-Bit Variable, die kann man nicht auf 500 setzen ;-)
Joa, aber wenn du nochmal in der alten Version von
"final_program_endgueltig.c" genauer hinschaust, erkennst du, das die
Variable 16-bit hatte ;-)
Das mit dem pausieren des Alarmtons habe ich erst mal aufgegeben. Da
setze ich mich villeicht später noch mal ran...ich hab zwar auch schon
eine Idee, wie ich das realisieren kann, aber wie gesagt: später.
Das das mit der Pause einfügen, wie ich es in der Alten Version versucht
habe, nicht funktioniert, hatte ich ja drei Posts später zugegeben...
Don Panso schrieb:>> Ausserdem habe ich noch fix eingefügt (noch nicht getestet):>> -Pause zwischen den Alarmtönen, so dass der nicht nahtlos vor sich>> hindudelt>> Da war ich Dämel zu vorschnell. Das klappt so natürlich nicht! Das wird> geändert.
(Da hatte ich deinen Post direkt danach noch nicht gelesen). Das was ich
da fabriziert hatte war wirklicher Murks und funktionierte natürlich gar
nicht. Das hatte ich erst beim testen gemerkt, was ich, wie du schon
sagtest, vor dem posten hätte machen sollen.
Gestern Abend sah die Funktion "fail_sound()" noch so aus (hab ich nicht
gepostet):
void fail_sound(void){
static uint16_t hilf = 200;
if (hilf > 100 && hilf <= 200) {
/* Frequenz ca. 391Hz */
LAUTSPRECHER_PORT |= (1 << LAUTSPRECHER_PIN);
_delay_ms(1.28);
LAUTSPRECHER_PORT &= ~(1 << LAUTSPRECHER_PIN);
_delay_ms(1.28);
} else if (hilf > 0 && hilf <= 100) {
/* Frequenz ca. 132Hz */
LAUTSPRECHER_PORT |= (1 << LAUTSPRECHER_PIN);
_delay_ms(3.8);
LAUTSPRECHER_PORT &= ~(1 << LAUTSPRECHER_PIN);
_delay_ms(3.8);
} else if (hilf > 200 && hilf <= 400) {
_delay_ms(5);
}
else hilf=400;
hilf--;
}
So in der Art sah das aus (weiss ich um ehrlich zu sein nicht mehr
genau). Ein Test ergab, das die gewünschte Pause vorhanden war. Das
Problem:
Der AD-Wandler wird während des Tons angeschmissen. Der braucht länger
als vorgesehen ist, womit während dem Ton eine Art tocken erzeugt wird.
Sprich: was ich haben will:
Dödöööö pause Dödöööö pause Dödöööö
Was ich mit dem hier in diesem Post kopierten Code hatte:
Dödötocköö pause Dötockdöööö pause tockDödöööö
Was ich jetzt momentan habe:
DödööööDödööööDödöööö
(Ich hoffe die Lautmalerei ist verständlich :-D)
Mit dem jetzigen Code wird die Messung der Spannungswerte und das
Anzeigen auf dem Display zwar auch während dem Ton vollzogen, dennoch
ist das tocken komischerweise nicht so auffällig...
Ich habe das schon eine Idee, wie ich das Problem lösen kann, dennoch
lasse ich mir noch ein bisschen Zeit...mal gucken ob ich mich heute noch
dransetze.
Falk Brunner schrieb:> Naja, Faktor 2,5, nicht schlecht, oder? Wobei das Hex-File nciht exakt> die Größe angiebt, die kann man aber sehr leicht im AVR-Studio ablesen,> in der Ausgabe beim Compilieren.
Wirklich ordentlich runter gegangen.
Ich kompiliere mit WinAvr und überspiele das Programm mit
AVR-Studio...ich halte mal ein Auge offen, wo ich den tatsächlichen
Speicherbedarf finden kann :-)
Grützi,
Panso
@Don Panso (Gast)
>Der AD-Wandler wird während des Tons angeschmissen. Der braucht länger>als vorgesehen ist, womit während dem Ton eine Art tocken erzeugt wird.
Das hat mit dem AD-Wandler und der Dauer der Messung gar nichts zu tun,
sondern mit deiner immern noch nicht vorhandenen Entprellung des
Alarmsignals. Aber du bist ja immer schlauer. Wenn dein Alarm nämlich
entprellt ist, wird er zwischendurch nicht kurz abgeschaltet. Das
erzeugt nämlich das Stottern des Alarms.
Und was lernen wir daraus? Eine Entprellung ist nicht nur für
Tasten, sondern auch für Messergebnisse oft sinnvoll und notwenig.
MfG
Falk
Karl heinz Buchegger schrieb:> OK. Gefragt war nur nach dem weißen Hintergrund.> [C]> int main()> {> uint8_t i;>> while( 1 ) {> for( i = 0; i < 32; ++i )> PORTB = 0xFF;> }> }>> versus> [code]> int main()> {> uint8_t i;>> while( 1 ) {> for( i = 0; i < 32; ++i )> PORTB = 0xFF;> }> }
Siehst Du...
aber gut zu wissen, das nur mit C Syntaxhighlighting vorhanden ist, DAS
wusste ich nicht...
Gruß Blackmore
Falk Brunner schrieb:> Aber du bist ja immer schlauer.
Pffff, das habe ich nicht behauptet. Ich habe mir lediglich nur meine
eigenen Gedanken zu einem bestehenden Problem gemacht. Anders konnte ich
mir das nämlich nicht erklären...
Meinst du das hier mit Entprellung???
Falk Brunner schrieb:> Dann sollte man noch sowas wie eine Entprellung einbauen. Sprich, das> Hupen geht erst los, wenn der Alarm für ein paar Sekunden aktiv ist. Das> Erspart die kurzen Hupsignale, wenns mal nur bisschen an der Grenze> zappelt
??? Selbst wenn die Werte permanent ausserhalb der Grenzen sind und
nicht an der Grenze zappeln, tockt der Alarm...
Meinst du mit "wenn der Alarm für ein paar Sekunden aktiv ist", dass man
den Ausgang des Mikrocontrollers erst ein paar mal an und aus gehen
lässt und dann erst den Lautsprecher dazu schaltet oder wie?
Kannst du mir das bitte genauer erklären? Ich verstehe das irgendwie
nicht :-(
Tatsache ist auch, dass in dem allerallerersten Programm, dass ich
gepostet habe der Alarm auch ohne Entprellung nicht getockt hat. Bei dem
Programm war noch nichts mit Multitasking...kann das villeicht auch
daran liegen?
@ Don Panso (Gast)
>Meinst du das hier mit Entprellung???
Ja.
>??? Selbst wenn die Werte permanent ausserhalb der Grenzen sind und>nicht an der Grenze zappeln, tockt der Alarm...
hast du das SICHER geprüft? Einfach mal die IF-Abfrage auskommentieren
und alarm dauerhaft auf 1 setzen?
>Meinst du mit "wenn der Alarm für ein paar Sekunden aktiv ist", dass man>den Ausgang des Mikrocontrollers erst ein paar mal an und aus gehen>lässt und dann erst den Lautsprecher dazu schaltet oder wie?
Nein!
>Kannst du mir das bitte genauer erklären? Ich verstehe das irgendwie>nicht :-(
So wie es Karl Heinz erklärt hat. Die Variable alarm wird erst auf 1
gesetzt, nachdem ein Zähler einen bestimmten Wert erreicht hat. Und der
wird nur dann hochgezählt, wenn die Messwerte abweichen. Siehe unten
1
/* Messgrößen auf Grenzwerte prüfen und bei Abweichung Alarm aktivieren, mit Entprellung */
>Tatsache ist auch, dass in dem allerallerersten Programm, dass ich>gepostet habe der Alarm auch ohne Entprellung nicht getockt hat.> Bei dem Programm war noch nichts mit Multitasking...kann das villeicht> auch daran liegen?
Ja, kann es. Das Auslesen des ADC geht eher schnell, aber die Berechnung
dauert etwas. Wenn auch nur Millisekunden, das hört man. Hmmm. Dann
müsste man halt wohl oder übel wieder auf das alte System umstellen.
Oder einen Schritt weiter gehen, und den Timer sowie die Output Compare
Funktion nutzen, dann sollte es auch stotterfrei laufen.
Ok, es gibt einen Zwischenschritt. Nur Output Compare. Siehe Anhang.
MfG
Falk
P S Und stell deinen Editor auf Soft Tabs, sprich Leerzeichen statt
echtem Tabulatorzeichen. Sonst wird deine Formatierung immer zerfressen
angezeigt, weil es keinen einheitlichen Tabulatorabstand gibt.
Falk Brunner schrieb:> hast du das SICHER geprüft? Einfach mal die IF-Abfrage auskommentieren> und alarm dauerhaft auf 1 setzen?
Da brauch ich nichts in der Software ändern. Ich puste einfach anhaltend
in den Differenzdruckmesser oder Stelle mittels des Lüfters den
Volumenstrom ab.
Falk Brunner schrieb:> Das Auslesen des ADC geht eher schnell, aber die Berechnung> dauert etwas.
Auch wenn ich nicht "AD-Wandler etc." geschrieben habe, ist es das, was
ich gemeint habe. Nach der AD-Wandlung kommt zwangsweise Berechnung und
diverse Display-Routinen. Deswegen auch das anfängliche Zögern mit dem
Multitasking und dem Beispiel mit der LED...
Aber DAS hört sich jetzt vorschlau an. Ich habe mich zuvor mit diversen
Fettnäpfchen nicht gerade mit Ruhm bekleckert, also komm ich mal wieder
ein bisschen runter.
Ein erneutes Dankeschön, für deine Mühen uns eine Überarbeitung des
Programms zur Verfügung zu Stellen. Ich schaue es mir mal an und
versuche es zu verstehen ;-)
Falk Brunner schrieb:> Und stell deinen Editor auf Soft Tabs
Hmm, ich habe mal einen Vortrag über den C-Styleguide gehalten...seitdem
mache ich das eigentlich mit 4 Leerzeichen etc. Weiss nicht, was da
schief läuft. Mal gucken, ob sich was ändern lässt.
Schönen Abend noch!
Don Panso
Ok ich seh schon, da muss ich mich noch ein bisschen mit dem Timer des
ATmega16 auseinandersetzen. Dann wühl ich mal im Datenblatt. Das dauert
etwas...dann teste ich auch morgen mal...
@Falk:
Hey, warum hast du den Lautsprecherpin geändert? ;-)
Don Panso schrieb:> Hey, warum hast du den Lautsprecherpin geändert?
Achso, dass hat wohl mit dem Timer zu tun?
Wie gesagt, muss mich da erst mal einlesen...
Don Panso schrieb:>> Hey, warum hast du den Lautsprecherpin geändert?>> Achso, dass hat wohl mit dem Timer zu tun?
Ok, es hat mit dem Timer zu tun. Das Problem: auf PORTD befinden sich
bereits alle Anschlüsse für das LCD. Hmmm, ich könnte das in der lcd.h
ändern und sämtliche Verbindungen umstecken...aber ich habe noch im
Laufe des Nachmittags eine vermeintliche Lösung erarbeitet, die ich
morgen erst testen möchte, bevor ich die wieder mit übertriebenem Tamtam
poste.
Ich melde mich dann morgen noch mal...
So, Freunde der Nacht
Ich habe das Programm gestern umgeschrieben. Sorry Falk, aber deine
Version mit dem Timer habe ich noch nicht getestet...wegen der Sache mit
dem LCD etc...
Jedenfalls habe ich es heute getestet und es funktioniert, sogar mit
einer kleinen Pause zwischen den Alarmtönen und das tocken ist
verschwunden...
Schaut mal rein, wenn ihr noch Lust habt :-)
Grüße,
Don Panso
@ Don Panso (Gast)
>Sorry, hab nicht so viel Zeit, die Änderungen zu Erklären...muss jetzt>weg bis heute Abend...
Herzlichen Glühstrumpf, du hast auf möglichst komplizierte Weise die
alte, erste Version wieder hergestellt. :-0
Wie gesagt, in diesem speziellen Fall kann man das machen, das Programm
ist ausreichend schnell unf funktionsfähig. Aber mit dieser
Programmierweise wirst du später nicht weit kommen, deshalb der Schwenk
auf Multitasking.
MfG
Falk
So, wieder zurück in den heimischen Gefilden.
Falk Brunner schrieb:> Herzlichen Glühstrumpf, du hast auf möglichst komplizierte Weise die> alte, erste Version wieder hergestellt. :-0Falk Brunner schrieb:> Aber mit dieser> Programmierweise wirst du später nicht weit kommen, deshalb der Schwenk> auf Multitasking.
Danke für die Glühstrümpfe. Inwiefern fehlt hier denn das Multitasking?
Der Ton ist in kleine Stücke zerlegt worden, in denen zwischendurch der
Taster abgefragt wird. Die Pause danach ist ebenfalls in kleine Stücke
zerlegt worden, zwischen denen der Taster abgefragt wird. Lediglig das
Wandeln, Umrechnen und Anzeigen auf dem Display geschieht, während der
Ton gerade nicht spielt, um das tocken zu vermeiden.
Die Pause, die zwischen zwei Wandlungs-Umrechnungs-Anzeige-Zyklen
besteht, wenn alle Messwerte innerhalb der Grenzen sind (256 * 5ms =
1,28s) ist in etwa genau so lang, wie der Alarmton und Tonpause zusammen
(100*2*1,28ms + 100*2*3,8ms + 56*5ms = 1,296s), besser angleichbar über
das delay in der Funktion "fail_sound()".
Die maximale Reaktionszeit, um den Taster zu erkennen ist DEUTLICHST
reduziert worden gegenüber der von dir angesprochenen alten, ersten
Version. Die Aktualisierungsdauer von Wandlung etc. ist akzeptabel.
Inwiefern ist also die alte, erste Version also wieder hergestellt
worden?
Hmmm, ok, im Prinzip war das eigenltich Sinn dieses Threads.
Das was die alte, erste Version tun sollte ist immer noch vorhanden,
jedoch ist die Schnelligkeit und Speicherbelastung ist im positiven Sinn
verändert worden.
Falk Brunner schrieb:> Wie gesagt, in diesem speziellen Fall kann man das machen>. . .>Aber mit dieser Programmierweise wirst du später nicht weit kommen,
Wir werden sehen, was die Zukunft bringt. Tatsache ist, dass
Multitasking kompliziert ist und sich nicht immer leicht auf gegebene
Probleme anwenden lässt.
Tatsache ist auch, dass das Programm JETZT ENDLICH tut, was ich will.
Sogar durch Tests bestätigt.
Also, zum dritten Male melde ich nun Erfolg. Abschlussbericht siehe oben
etc. etc.
Danke für eure Geduld und Entschuldigung für die ständigen
Erfolgsmeldungen, die dann doch auf ihre Art und Weise nur heisse Luft
waren. Drücken wir die Daumen, dass dem diesmal nicht so ist.
Konstruktive Kritik ist immer noch willkommen.
Mit freundlichen Grüßen,
Don Panso
@ Don Panso (Gast)
>Danke für die Glühstrümpfe. Inwiefern fehlt hier denn das Multitasking?
OK, Kommando zurück, es ist doch nicht wie Version 1.0. Da war ich wohl
etwas vorschnell mit meinem Urteil.
Nein, diese Version ist ziemlich gut, denn der Ton wird mit dem Alarm
synchronisiert. Das erklärt das Fehlen des Stotterns.
>Die maximale Reaktionszeit, um den Taster zu erkennen ist DEUTLICHST>reduziert worden gegenüber der von dir angesprochenen alten, ersten>Version.
Ja. ;-)
>Wir werden sehen, was die Zukunft bringt. Tatsache ist, dass>Multitasking kompliziert ist
Ein wenig.
> und sich nicht immer leicht auf gegebene>Probleme anwenden lässt.
Eine Frage der Erfahrung.
>Tatsache ist auch, dass das Programm JETZT ENDLICH tut, was ich will.>Sogar durch Tests bestätigt.
Schön ;-)
>Also, zum dritten Male melde ich nun Erfolg.
Der Kaiser wäre stolz auf dich . . . ;-)
MfG
Falk
Falk Brunner schrieb:> OK, Kommando zurück,
Uff, Gott sei Dank...
Falk Brunner schrieb:> denn der Ton wird mit dem Alarm synchronisiert
Das war die Idee dahinter ;-)
Falk Brunner schrieb:> diese Version ist ziemlich gut
Danke. Es war ein langer weg bis hierhin. Mich graut es immer noch, wenn
ich den ganzen Thread von oben nach unten runterscrolle...
Letzte Woche war das Programm noch ein häufchen Elend. Schaut euch an,
wo wir heute stehen. All das war nur wegen eurer Hilfe möglich. Danke an
euch!
Falk Brunner schrieb:>> Tatsache ist, dass>>Multitasking kompliziert ist>> Ein wenig.
Schon ein bisschen.
Falk Brunner schrieb:> Eine Frage der Erfahrung.
Ganz genau. Die kommt dann noch mit möglichen folgenden Projekten.
Falk Brunner schrieb:>>Also, zum dritten Male melde ich nun Erfolg.>> Der Kaiser wäre stolz auf dich . . . ;-)
:-D
So, Leute. Ich behaupte es ist alles gesagt. Das Ergebnis dieses Threads
kann sich sehen lassen. Es hat sich definitiv gelohnt hier zu posten.
Danke zum x-ten Mal an alle für die Unterstützung ohne die das Programm
heute noch vor sich hin lahmen würde.
Sollten aber noch Vorschläge, Anregungen, Kritik etc. bestehen: ich
schau hier ab und zu noch mal rein. Nachfolgendes wird also,
wahrscheinlich nicht nur von mir, beachtet.
Machtet jut, schwingt de Hut.
Don Panso