Hallo!
Ich wollte mich wieder zu dem leidigen Thema Taster melden. Und zwar
wäre es mein Endziel meine Feuchtemesserschaltung mit einem Taster in
den Power-Down Modus zu befördern. Ich habe jetzt aber erst mal ein
kleines Programm für mich etwas "angepasst". Ich habe versucht möglichst
viele Kommentare einzubringen, damit man meinen Gedankengang sieht. Ich
bin ja wie hier schon paar Mal erwähnt totaler Anfänger bei der
C-Programmierung. Als Controller verwende ich den ATTINY24V.
Um die ganze Sache zu entprellen habe ich mit Delay gearbeitet. Ich
könnte mir vorstellen, dass ich das Unterprogramm taster_abfrage genauso
auch in mein eigentliches Programm übernehmen kann. Unterschiede werden
wohl nur im Main auftauchen, da ich ja keine Lämpchen ausschalten will
sondern den ATTINY. Die ISR wird sich dann ja wohl nach dem Main
wiederfinden. Jetzt aber erst mal zu diesem einfacheren Programm.
Nach meiner Theorie hätte ich ja am Anfang insgesamt 4 mal eine
if-Abfrage machen können (müssen) damit die Schaltung entprellt ist:
1. wenn Taster gedrückt
2. Wartezeit 40 - 80 ms dass der Zustand stabil ist (Diesen Tip habe ich
von einem Studienkollegen bekommen mit den 40 ms. Damit spare ich mir
angeblich eine Entprellung. Zusätzlich könnte ich auch 100nF parallel zu
meinem Taster schalten wurde mir gesagt)
3. Abfragen ob Taster immer noch gedrückt ist nach der Wartezeit
4. Abfragen ob Taster ausgelassen ist (Die Reaktion soll ja erst nach
dem Auslassen erfolgen. Sprich solange einer seinen Finger da drauf hat
passiert gar nichts)
5. wieder eine Wartezeit zur Stabilisierung
6. Abfragen ob Taster immer noch ausgelassen ist
Soetwas mit 4 if-Abfragen scheint mir aber doch zu kompliziert zu sein.
Keine Ahnung ob mir die while Schleife da weiterhilft, damit es
einfacher wird!
Dieses Programm funktioniert auch. Wobei der SMD-Taster nicht auf jede
Aktion reagiert. Da ist die Frage ob das rein mechanisch bedingt ist,
oder ob das mit meinem Programm und z.B. dem Delay zusammenhängt.
Würde mich über euren Support freuen!
Gruß
Thomas
Danke! Ja das schaut schon mal viel besser aus. Hältst du den
Kondensator parallel zum Taster für sinnvoll? Eigentlich sieht mir ja
die Gesamtstruktur des ganzen relativ kompliziert aus mit den
if-Abfragen.
Gruß
Thomas
Bastler schrieb:
> Danke! Ja das schaut schon mal viel besser aus. Hältst du den> Kondensator parallel zum Taster für sinnvoll?
Nein.
> Eigentlich sieht mir ja> die Gesamtstruktur des ganzen relativ kompliziert aus mit den> if-Abfragen.
Wenn du das kompliziert nennst, dann warte mal ab, bis du anfängst
richtige Programme zu schreiben. :-)
Und arbeite an deiner Code-Formatierung.
Die hat einen Zweck und sollte daher immer und überall gleich sein.
Es ist nicht akzeptabel, wenn du die öffnende { eines Blocks einmal um 2
Zeichen einrückst und ein ander mal nicht. Wobei du dich fagen solltest,
welchen Zweck es hat, die { einzurücken um dann gleich nocheinmal den
Teil der innerhalb des Blockes steht ebenfalls um 2 Zeichen einzurücken.
Auch die Einrückung hat einen Zweck, wenn du das nicht konsequent
durchziehst, führst du den Zweck ad absurdum. Zweck einer Einrückung ist
es anzuzeigen, dass ein Codeteil zb in einer Abhängigkeit zu einem
anderen Codeteil steht. D.h. Wenn zb bei einem if der then Teil nur aus
einer Anweisung besteht und du daher keine {} drumherum machst, dann
wird diese eine Anweisung eingerückt!
1
unsignedchartaster_abfrage(void)
2
{
3
staticunsignedcharzustand=0;
4
unsignedcharret=2;// ret auf definierten "undefinierten" Zustand
5
6
if(!(PINB&(1<<PINB2)))// wenn Taster gedr�ckt
7
{
8
_delay_ms(80);// Wartezeit 80ms
9
if(!(PINB&(1<<PINB2)))// wenn Taster immer noch gedr�ckt
Über jeder } muss es in der gleichen Codespalte eine { geben. Die {
steht in derselben Spalte, in der auch die Anweisung beginnt, die den
Block erzwingt (bei dir das 'i' von 'if'). Nach einer { wird der
abhängige Codeteil um 2 Zeichen eingerückt. Die schliessende } wird
wieder um 2 Zeichen ausgerückt und die nächsten Codeteile beginnen dann
ebenfalls in dieser Spalte.
Wenn sich mit konsequenter Anwendung dieser Regel die schliessende } der
Funktion nicht in Spalte 1 befindet, dann ist in der Funktion in der { }
Hierarchie irgendetwas durcheinander gekommen.
Ich glaube dieses Durcheinander kommt daher weil ich von einem Textfile
in das AVR Studio eingefügt habe. Ich habe es bis jetzt immer mit Tab
gemacht. Die zwei Leerzeichen kommen irgendwie durch das *.c oder
*.txt-File.
Trotzdem nochmal herzlichen Dank für die Erklärung. Ja wie gesagt für
mich als Anfänger ist das extrem schwer da plötzlich wie ein Profi alles
zu machen. Daher sieht das kompliziert aus für mich. Würdest du sagen
ich entprelle die Taste mit dem Delay? Ich habe ja jetzt immer ein
Warning seit dem ich das mit dem Delay mache:
"F_CPU not defined for <util/delay.h>"
Alternativ würde das ja wohl mit for gehen wo ich ja immer eine
bestimmte Zeit abwarte. Da könnte ich dann ja wohl den CPU-Takt
heranziehen dafür. Alternativ wäre ja auch ein Timerinterrupt möglich
vermute ich. Nur dann wird es wieder sehr kompliziert für mich da ich ja
ohnehin einen Interrupt benötige um dieses Ding wieder aufzuwecken.
Evt. werde ich nochmal Hilfe in Anspruch nehmen wenn ich das mit dem
Power-Down umsetzen will. Hatte da schon einmal Probleme weil er nicht
eingeschlafen ist. Möchte da aber zunächst selber rumprobieren.
Gibt es eigentlich nur beim aufwachen den Interrupt?? Also wird die
Interruptserviceroutine nur dann aufgerufen wenn ich meinen Externen
Interrupt durch den Taster erzeuge? Einschlafen wird er wohl rein durch
den Power-Down Befehl wobei ich nicht vergessen darf die Interrupts zu
enablen und keine Flankenänderung da es ja keinen Takt mehr gibt. Das
dürfte wohl so richtig sein?!
Gruß
Th.
Bastler schrieb:
> Warning seit dem ich das mit dem Delay mache:>> "F_CPU not defined for <util/delay.h>"
Die delay Funktionen arbeiten nach dem Prinzip in einer Schleife solange
Instruktionen abzuarbeiten, bis die Zeit vergangen ist.
Um die Zeit berechnen zu können, müssen sie daher auch wissen, wie
schnell dein µC getaktet ist. Denn klarerweise werden 100 Instruktionen
bei doppelter Taktfrequenz doppelt so schnell abgearbeitet.
das F_CPU Makro macht genau das. Es instruiert die delay Funktionen (und
andere) darüber wie schnell dein µC getaktet wird.
einfach ganz am Anfang, noch bevor all den Includes
#define F_CPU 4000000 // 4 Mhz
oder welche Taktfrequenz du auch immer hast.
Hallo
Also das mit dem #define F_CPU 1000000 hab ich gemacht. Mein
Controller soll ja mit 1 MHz laufen. Allerdings habe ich genau diese
Zeile wieder entfernt da der Takt durch die Fuses ja ohnehin auf 1 MHz
festgelegt ist. Er bringt jetzt auch drei Warnings:
1. F_CPU not defined for <util/delay.h>
2. F_CPU redefined
3. this is the location of the previous definition
Wo liegt hier der Fehler?
Gruß
Thomas
Bastler schrieb:
> Hallo>> Also das mit dem #define F_CPU 1000000 hab ich gemacht. Mein> Controller soll ja mit 1 MHz laufen. Allerdings habe ich genau diese> Zeile wieder entfernt da der Takt durch die Fuses ja ohnehin auf 1 MHz> festgelegt ist.
Falsch.
Das F_CPU stellt nichts an der Hardware ein.
Aber woher soll denn der Compiler wissen, wie schnell dein µC getaktet
ist? Der kann ja nicht hellsehen.
#define F_CPU 1000000
ist die Information für alle die es wissen wollen, welche Taktfrequenz
der µC hat.
Er bringt jetzt auch drei Warnings:
>> 1. F_CPU not defined for <util/delay.h>> 2. F_CPU redefined> 3. this is the location of the previous definition>> Wo liegt hier der Fehler?
Reihenfolge!
delay.h will wissen, wie hoch die Taktfrequenz ist. Daher muss die F_CPU
vor dem delay.h vereinbart werden
Ok. Danke. Es funktioniert jetzt auch ohne Warnings.
Kann ich jetzt aus der Tasterabfrage relativ leicht auch eine Power-Down
Routine entwerfen?
Ich hätte jetzt gesagt dass man dem switch weiter kommen müßte. Nur dass
man hald bei case Lampe aus irgendwie was reinbringen muss mit:
sei() //ISR aktivieren
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
Geht das so in die Richtung?
Gruß
Thomas
Bastler schrieb:
> Geht das so in die Richtung?
In den sleep schicken ist nicht das grosse Problem. So wie du das hast
müsste das schon gehen. Die Frage ist eher: Wodurch wird der µC wieder
aufgeweckt?
Wenn ich das bis jetzt so richtig mitbekommen habe erfolgt das Aufwecken
des Controllers durch eine ISR. Mein Problem ist jetzt nur wie die
Anordnung ist.
Die ISR ist ja quasi eine eigene Unterfunktion. Nur wie das mit dem case
gehen soll ist mir noch schleierhaft. Ich versuche jetzt mal was
zusammenzuschreiben. Habe noch nie eine ISR geschrieben geschweige denn
den Controller in Power Down geschickt.
Vermute aber mal dass wenn mans einfach macht auch hier nur wenige
Zeilen fällig sind.
Gruß
Thomas
Der Taster muss an einem Pin des MC hängen, mit dem man einen externen
Interrupt auslösen kann (z.B. INT0 oder INT1). Die Interruptroutine
definierst du einfach in deinem Programm, im Prozedur-Body muss nichts
drin stehen.
In deinem entsprechenden Case-Zweig schaltest du Interrupt ein,
definierst und gehst in den entsprechenden Sleep-Modus. Genau da bleibt
das Programm stehen. Mit dem "Ein-Taster" (am Interrupt-Pin) wird wieder
aus dem Sleep-Modus gegangen und genau an dieser Programmstelle
weitergemacht. Wenn du Ein/Aus mit dem gleichen Taster machen möchtest
musst du noch etwas Logik schreiben, dass der MC nicht gleich wieder
nach dem Aufwecken einschläft...
Grüße Uwe
Also hardwaremäßig hängt ein Taster am Pin 5 meines ATTINY 24V. Das
sollte der INT0-Pin sein. Kann eine LED damit ein und ausschalten. Das
funktioniert.
Habe ich die Möglichkeit nach dem Aufwachen automatisch einen Reset
auszulösen? Geht das? Im Moment produziere ich irgendwie nur Fehler. Ich
habe
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
eingebaut aber da meckert er ja auch schon. Außerdem einen Interrupt bei
pegelwechsel da ja kein Takt im Power-Down Modus. Kann mir da jemand
helfen wie die Struktur da aussieht?
Gruß
Thomas
Ich habe jetzt versucht einen Code zusammenzustellen für den Power Down.
Ich habe keine Fehlermeldungen aber ich bezweifle dass dieser Code
wirklich das tut was er soll. LED geht nach wie vor an und aus. Nur
glaube ich nicht dass der Controller einschläft und wieder aufwacht.
Könntet ihr mir Tips geben was ich verändern muss.
Danke!
Gruß
Thomas
Habe ich mir zunächst angeschaut. Allerdings muss ich sagen dass ich
hier nicht alles verstehe. Ja ich weiss man soll power-down nicht
verwenden! Darum habe ich ja erst mit dem sleep_cpu gearbeitet. Die
Frage ist ja auch ob das innerhalb von dem case funktioniert. Das
einschalten müßte dann ja irgendwie auf die ISR verweisen. Keine Ahnung
wie das dann nur von der groben Form dann aussehen könnte. Habe hald
versucht hier alles logisch zusammenzufassen. Ich weiss auch nicht so
genau was alles in der ISR stehen muss. Das soll ja möglichst kurz sein.
Bastler schrieb:
> Ich weiss auch nicht so> genau was alles in der ISR stehen muss. Das soll ja möglichst kurz sein.
Dann mache das doch. Im Extremfall steht einfach nix in der ISR.
Geschickter ist es in der ISR nach dem Aufwecken den Wecker abzustellen,
damit irgendwelche im Wachzustand einlaufenden Interrupts keine
Peozessorzeit fressen. Also heisst das den Weckinterrupt zu disablen,
bis er das nächste mal gebraucht wird. Das nächste Mal ist in dem Fall
die Stelle vor dem Schlafenlegen und dann wird der Weckinterrupt wieder
enabled.
Das habe ich ja glaube ich gemacht:
ISR ( INT0_vect ) // externer Interrupt 0
{
GIMSK &= ~(1 << INT0); // externer Interrupt deaktiviert
cli();
}
Zunächst der externe Interrupt deaktiviert dann noch die restlichen.
Müßte mein LED eigentlich erlöschen wenn mein Controller in Power-Down
ist? Ich denke mal nicht da die LED bei 0 aktiv ist und das ja wohl der
default-Wert sein dürfte. Also werde ich den Power-Down Zustand nur am
Stromverbrauch erkennen. Kann mir auch nicht so ganz vorstellen dass es
so funktioniert. Ich habe jetzt zwar wohl alles in meinem Programm drin
was man brauchen könnte aber ob die Reihenfolge so wirklich stimmt sei
dahingestellt!
Gruß
Th.
Das ist tatsächlich so lange dahingestellt, wie du nur Codefetzen
zeigst.
1. Stromverbrauch messen geht, wenn der Rest der unbekannten Schaltung
das zulässt. Einen Tropfen Wasser in einem Eimer Wasser zu messen ist
schwer.
Aber es ist trivial eine Debug-LED zu toggeln, wenn ein Ereignis
auftritt z.B. Schlafmodus oder Wecken. Eine LED muss auch nicht
Active-Low betrieben werden. Im Sinn deines stromsparenden Gerätes sind
Active-Low angeschlossene LEDs eher kontraproduktiv.
2. Das cli() in der ISR ist mindestens überflüssig und u.U. fehlerhaft.
Es fehlt:
3. Wie und wo wird der INT0 eingestellt? Flanke oder Level? Welcher
Level? Wird eine eventuell noch anstehende INT0 Bedingung gelöscht
(GIFR)?
4. Ist im Programm ein sei() enthalten und wo?
5. Wie ist die Hardware am INT0-Pin angeschlossen? Was hält den HIGH
Pegel (nicht aufwachen)? Der interne Pullup dieses Pins? Wo wird der
geschaltet/initialisiert?
Hallo!
Ok dann zeige ich hier nochmal meinen Code. Mir ist klar dass die Sache
so nicht funktionieren kann. Alleine schon die Reihenfolge geht wohl
nicht. Ich habe meine LED auf Active-High umgebaut. Es ist also im
Moment nur der Controller mit dementsprechender 3 V Spannungsversorgung,
Schnittstelle und eine LED angeschlossen. Ja ok natürlich noch der
zukünftige Power-Down Taster. Der Taster ist an Pin3 gegen GND
angeschlossen (also INT0).
Ich hoffe diese Infos sind ausreichend.
Gruß
Thomas
Die Manipulation von zustand in main() ist unschön. Deine Idee zustand
in taster_abfrage() zu kapseln ist schöner. Man könnte beides erreichen,
wenn man die globale Variable wieder durch die statische ersetzt und
taster_abfrage() etwas ergänzt...
Zunächst mal Danke für diese Hilfe. Ich habe wieder meinen Code
angehängt. Ich hoffe dass ich alles so weit richtig übernommen habe.
Leider funktioniert die Sache immer noch nicht. Ich weiss ehrlich gesagt
nicht wo das Problem liegt. Es hat schon funktioniert. Man spürt den
Power-Down ja nur durchs Amperemeter. Im Power-Down Zustand war der
Stromverbrauch aber immer noch bei 1mA!!!!! Das ist enorm viel wenn das
denn stimmt!
Gruß
Thomas
taster_abfrage(EIN);// Synchronisieren auf Wecktaster
77
break;
78
default:
79
break;
80
}
81
}
82
return0;
83
}
Gut dass du noch eingefügt hast:
> MCUCR &= ~((1 << ISC01)|(1 << ISC00)); // low level interrupt
Das hatte ich fälschlicherweise zuviel rausgeworfen, als ich die Makros
reingebracht hatte. Es funktioniert zwar ohne die Zeile (Bits sind per
default gelöscht), schöner ist es mit der Zeile.
Ok!
Diese Zeile kann man ja wohl weglassen:
//MCUCR |= (1<<SM1); // Wahl des Power-down Modes (SM2 = 0)
Das wird ja von
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
übernommen oder?
Ich habe nur das Problem dass er mir nicht immer aufwacht. Beim ersten
schlafen gehen geht das. Dann nicht mehr. Könnte aber auch an der
Entprellung liegen. Im Power-Down zieht er jetzt noch 10 µA Strom. Das
scheint mir eigentlich so weit in Ordnung zu sein oder?
Ich habe den Code auch nochmals verfälscht. Ohne das sei() wo er nach
dem Aufwachen hinspringen soll ging auch nichts. Aber das macht
eigentlich wenig Sinn finde ich!
Kann man eigentlich zum Aufwachen einen Reset auslösen automatisch?
Gruß
Thomas
Das klingt dann doch verdächtig nach den Problemen, die Peter Dannegger
in seinem Beitrag "AVR-GCC Power-Down Tutorial" anspricht
und auch Lösungen dafür anbietet.
>Kann man eigentlich zum Aufwachen einen Reset auslösen automatisch?
Ach was!
"Ich suche dringend einen Controller, der folgendes kann. Beim Aufwachen
soll automatisch ein Reset ausgelöst werden, wobei der Controller
selbsttätig seine Taktfrequenz verdoppeln und einige Bytes seines
eigenen Programmspeichers ändern soll. Außerdem soll er während des
Resets den Tx- mit dem Rx-Pin vom UART hardwaremäßig vertauschen sowie
an einen zweiten Controller, der sich nur um die Abfrage eines einzigen
Tasters kümmert, ein Signal schicken. Das Ganze soll unbedingt mehr als
1000 mal pro Sekunde möglich sein."
So lautet eine richtige Anfängerfrage! ;-)
@ Thomas
Ich bin vom Schreibtischtäter zum Stromer mutiert. D.h. ich habe gerade
die Source oben auf mein Pollin-Funk-AVR-Board mit dem Attiny2313
portiert und an dessen LED und Taster angepasst.
Mit den Hinweisen von Peter funktioniert das Schlafen/Wecken mehrmals
hintereinander. Ohne ATOMIC_BLOCK(ATOMIC_FORCEON){ } geht es aber auch.
Wenn das bei deinem Aufbau nicht funktioniert, schreibe mal was zum
Anschluss des Wecktasters - wo bekommt der im inaktiven Zustand (nicht
gedrückt) den HIGH-Pegel her? Ich habe dafür bei der Initialisierung am
INT0-Pin den internen Pullup gesetzt (Attiny2313: PORTD |= (1 << PD2);)
Hallo!!
Also das scheint zu funktionieren. Konnte es jetzt 5 Mal hintereinander
ein und ausschalten. Danach hat es zwar gestockt aber vielleicht liegt
das ja an den SMD Tastern. Mich würde jetzt nur noch interessieren was
dieses Atomic macht. Das habe ich ja auch nicht kappiert wo ichs mir
angesehen habe.
Der Wecktaster ist an PB2 (INT0) angeschlossen. Ich habe keine Ahnung wo
der im inaktiven Zustand den HIGH Pegel herbekommt. Ich stelle mir hald
vor dass der Pull-Up am Eingang für den externen Interrupt aktiv ist.
Und durchs VCC bekommt der Pin dann High. Wissen tu ich es nicht. Habe
mit Microcontroller fast nie was zu tun gehabt. Achso lese gerade
weiter. Du wolltest darauf raus. Also der Pullup ist bei mir aktiviert
und Pin ist auf Eingang. Dadurch erklärt sich das wohl. Könntest du mir
nochmals mit paar Kommentaren helfen damit ich das ganze Programm
nachvollziehen kann.
Der schwierige Teil kommt ohnehin noch. Das war ja jetzt nur ein
Beispiel um das mal zu testen. Meine eigentliche Schaltung ist ein
Betauungsmesser den man ein und ausschalten kann. In diese Software muss
ich das jetzt irgendwie implementieren. Also das mit LED aus und ein
kann man da ja rauslassen. Da meine LEDs jetzt highactiv sind wird ihnen
die defaultmäßige 0 nichts mehr anhaben. Also sprich ich brauche meine
LEDs beim ausschalten nicht extra ausschalten. Da werde ich sicher noch
Hilfe brauchen!
Gruß
Thomas
Bastler schrieb:
> Mich würde jetzt nur noch interessieren was> dieses Atomic macht. Das habe ich ja auch nicht kappiert wo ichs mir> angesehen habe.
Es sorgt dafür, dass die Anweisungen innerhalb der {} Klammer nicht
durch Interrupts unterbrochen werden. Das ist wichtig, wenn Register in
mehreren Einzelschritten manipuliert werden. Beispiel 16-Bit-Register
oder Register lesen, Bits manipulieren und Register zurückschreiben.
Ohne den Schutz künnten bei einer Unterbrechung falsche Daten in ein
Register gelangen und/oder andere unerwünschte Sachen passieren.
Beispiel:
Interrupts seien aktiviert (sei). Der INT0 wird enabled aber das Sleep
noch nicht. Jetzt tritt ein zufälliger INT0 auf. Die ISR wurde den INT0
disablen. Dann käme das Sleep... und prompt würde der AVR nicht mehr
aufwachen, weil der INT0 disabled ist. Möglicherweise ist genau das beim
2. Durchlauf in
Beitrag "Re: Tasterabfrage"
passiert.
Also darf der Code zwischen dem INT0 enable und dem Sleep nicht
unterbrochen werden! Das stellt die Atomic-Klammer sicher.
> Könntest du mir> nochmals mit paar Kommentaren helfen damit ich das ganze Programm> nachvollziehen kann.
Frag konkreter. Im Tutorialschreiben bin ich nicht gut.
> Der schwierige Teil kommt ohnehin noch. Das war ja jetzt nur ein> Beispiel um das mal zu testen.
So verläuft i.A. Entwicklung. Splitten in Teilaufgaben. Lösen der
Teilaufgaben und dann Zusammenführen zum Gesamtprojekt.
Guten Morgen!
Also das mit Atomic scheint mir schon geholfen zu haben. Ich habe jetzt
mal versucht mein Programm mit der Tasterabfrage in mein eigentliches
Programm zur Feuchtemessung einzufügen. Außerdem habe ich das Programm
umgeändert damit die LEDs nicht mehr lowactive sind.
Ich habe jetzt folgende Fehlermeldungen.
stray '\356' in program
und viele Warnings.
Für mein Programm wäre es ja besser wenn das Einschalten einen Reset
auslösen würde. Das dürfte sogar zwingend notwendig sein, weil alle
andere Funktionen wohl sonst nicht mehr funktionieren dürften.
Auch die Funktion mit dem Blinken der LEDs funktioniert nicht mehr so
wie es mal war...
Ob man die while(1) Schleife von Schalter onoff benötigt weiss ich
ehrlich gesagt auch nicht. Es würde da ja nie mehr wieder rauskommen.
Nur ohne Schleife weiss ich auch nicht ob das dementsprechend abgedeckt
wird alles
Gruß
Thomas
Stop. Fehler gefunden. Ich habe
return zustand;
vergessen. Allerdings macht er jetzt irgendwie gar nichts mehr!!"g" Alle
LEDs leuchten. Kein Power-Down. Ein Fehler dürfte wohl sein, dass diese
while(1) Schleife fehlt die im anderen ist.
Die Abfrage if((trigger % 61)==0) würde ich an deiner Stelle auch
überdenken.
Mit der Abfrage würde die EIN/AUS-Taste nur in knapp 2% der Umläufe von
trigger ausgeführt (Bedingung ist 5 mal wahr bei 256 Schritten). Das
wäre mir für eine interaktive Eingabe deutlich zu wenig.
Also in einem ersten Test würde ich dieses if rauswerfen und die Zeilen
sei();
unsigned char schalter;
vor das while(1) ziehen.
Logisch betrachtet würde ich die Messaktionen in den case EIN: Fall des
switch stecken. Dort ist ja die Aktion bei eingeschaltetem Gerät...
Guten Morgen!
Danke für deine neuen Tips. Du hast wohl recht dass man die Sache mit
on/off öfter abfragen sollte. Seitdem ich aber das mit dem on/off in
meinem Code habe funktioniert die Feuchtemessung nicht mehr so ganz. Die
gelbe LED leuchtet da nur noch ganz schwach.
Ich habe jetzt auch den Aufruf feuchtemessung() in Main unter case EIN
geschrieben. Das müßte wohl so funktionieren. Ein- und Ausschalten ist
leider in dieser Schaltung immer noch nicht möglich. Ich mußte ja die
while(1)-Schleife die ursprünglich auch für mein on/off eingebaut war
weglassen da ja auch für die feuchtemessung und das mit der Batterie
eine while(1) Schleife vorgesehen ist. Ebenso wäre es doch auch sinnvoll
dass mit dem Einschalten ein Reset ausgelöst wird oder? Dann würde er
alles wieder neu übernehmen.
Bin im Moment in der geringen Zeit die mir fürs Programmieren zur
Verfügung steht dazu übergegangen zu testen ob nicht auch ein
kapazitiver Feuchtesensor einzufügen ist. Man kann über die Ladezeit ja
die Kapazität bestimmen. Da brauche ich ja normal keinen PWM oder so.
Komparator wird wohl schon reichen. Die Frage ist nur ob das mit meinen
3V Batteriespannung so einfach geht. Hast du hierbei Erfahrung? Gibt
auch einen tollen Beitrag hier im Forum zum Thema Kapazitätsbestimmung.
Da ist auch eine Schaltung dabei. Schwierig dürfte hald sein 0,3 pF pro
% rel. Feuchte zu messen befürchte ich. Wobei das bei mir ja nicht so
genau sein muss da ich ja eh nur eine grüne, gelbe und rote LED habe.
Wichtig wäre aber jetzt erstmal dass die Schaltung mit dem
Betauungssensor funktioniert.
Danke!
Gruß
Thomas
Bastler schrieb:
> Seitdem ich aber das mit dem on/off in> meinem Code habe funktioniert die Feuchtemessung nicht mehr so ganz. Die> gelbe LED leuchtet da nur noch ganz schwach.> Ich habe jetzt auch den Aufruf feuchtemessung() in Main unter case EIN> geschrieben. Das müßte wohl so funktionieren.
Weil du jetzt die feuchtemessung() zu oft aufrufst - jetzt jedesmal
statt alle 16tes Mal. Dadurch toggelt die LED zu häufig und du siehst
insgesamt eine dunklere LED.
1
// ### FRÜHER jedes 16.tes Mal ###
2
// z.B. jedes 16. Mal // wenn Trigger ist 16, 32, 48 usw.
3
//if((trigger % 16) == 0)
4
// feuchtemessung();
5
6
schalter=taster_abfrage(UNDEF);
7
switch(schalter)
8
{
9
caseEIN:
10
feuchtemessung();// ### JETZT JEDESMAL! ###
11
//LED_EIN();
12
break;
Ändere es mal versuchsweise in (hier ist der Block batterieüberwachung()
auch in den Wachzustand gezogen worden)
1
schalter=taster_abfrage(UNDEF);
2
switch(schalter)
3
{
4
caseEIN:
5
if(trigger==0)// jedes 256.te Mal
6
batterieueberwachung();
7
if((trigger%16)==0)// jedes 16.te Mal
8
feuchtemessung();
9
break;
> Ein- und Ausschalten ist> leider in dieser Schaltung immer noch nicht möglich. Ich mußte ja die> while(1)-Schleife die ursprünglich auch für mein on/off eingebaut war> weglassen da ja auch für die feuchtemessung und das mit der Batterie> eine while(1) Schleife vorgesehen ist.
Weil die Feuchtemessung() ausserdem auf das ADC Ergebnis wartet, erwarte
ich eine gewisse Trägheit bei der Reaktion auf den ein/aus Taster, wenn
wie in deinem Code jedesmal die Funktion aufgerufen wird. Das sollte
sich mit obigem Vorschlag mit seltenerem Aufruf deutlich verbessern.
Die jetzt vorhandene while(1) Schleife ist die Hauptarbeitsschleife und
die kann (und sollte) alle Aufgaben übernehmen: feuchtemessung,
batteriemessung, ein/aus Abfrage, schlafen/aufwachen und trigger zählen.
trigger zählen kann man später sinnvoll durch einen Timer ersetzen
(Batteriemessung alle x Stunden, Feuchtemessung alle x Minuten,
dazwischen pennen und Strom sparen). Wie oft die Feuchte gemessen werden
muss/soll hängt von deiner Anwendung ab. Wozu verwendest du das
Messgerät eigentlich?
> Ebenso wäre es doch auch sinnvoll> dass mit dem Einschalten ein Reset ausgelöst wird oder? Dann würde er> alles wieder neu übernehmen.
Das ist ja trivial zu lösen: Den Einschalter legst du auf den Resetpin.
Es gibt Anwendungen bei denen man die Initialisierung auf den
Grundzustand nicht haben will. Beispiele: Es läuft eine Uhr mit und die
Uhrzeit soll nicht verloren gehen. Es läuft eine
Mittelwertbildung/Messwertglättung und die soll nicht vorloren gehen...
> Bin im Moment in der geringen Zeit die mir fürs Programmieren zur> Verfügung steht dazu übergegangen zu testen ob nicht auch ein> kapazitiver Feuchtesensor einzufügen ist. Man kann über die Ladezeit ja> die Kapazität bestimmen. Da brauche ich ja normal keinen PWM oder so.> Komparator wird wohl schon reichen. Die Frage ist nur ob das mit meinen> 3V Batteriespannung so einfach geht. Hast du hierbei Erfahrung? Gibt> auch einen tollen Beitrag hier im Forum zum Thema Kapazitätsbestimmung.> Da ist auch eine Schaltung dabei. Schwierig dürfte hald sein 0,3 pF pro> % rel. Feuchte zu messen befürchte ich. Wobei das bei mir ja nicht so> genau sein muss da ich ja eh nur eine grüne, gelbe und rote LED habe.> Wichtig wäre aber jetzt erstmal dass die Schaltung mit dem> Betauungssensor funktioniert.
Sorry habe ich keine Erfahrung. Wenn es die Sensoren bei Conrad gibt,
schreib mal die Artikelnummern dazu. Ich würde mir mindestens die
Datenblätter mal ansehen. Und wenn du einen Link zu dem Beitrag hast,
gib den bitte auch an.
Ja der Tip das alles mit in case Ein einzubauen ist schon mal gut. Das
mit dem Reset nach dem Einschalten dachte ich hald nur weil ich nicht
weiss ob du ganzen Werte vor der while(1) Schleife erhalten bleiben.
Keine Ahnung ob das bei mir nötig ist.
Die Schaltung funktioniert leider immer noch nicht. Speziell die gelbe
LED ist sehr dunkel. Kann ja auch nicht hardwaremäßig zusammenhängen
weil es ohne Power Down ja auch ging. Power Down geht leider immer noch
nicht wieder. Keine Ahnung an welcher Stelle noch etwas falsch ist.
Der kapazitive Sensor ist von der Firma Hygrosens Instruments und heißt
und heißt KFS140-MSMD (Conrad Art.-Nr.: 156508 - 62). Der Link zu der
Seite auf der das mit dem kapazitivem Sensor beschrieben ist lautet:
http://elm-chan.org/works/cmc/report.html
Gruß
Th.
Bastler schrieb:
> Ja der Tip das alles mit in case Ein einzubauen ist schon mal gut. Das> mit dem Reset nach dem Einschalten dachte ich hald nur weil ich nicht> weiss ob du ganzen Werte vor der while(1) Schleife erhalten bleiben.> Keine Ahnung ob das bei mir nötig ist.
Da bleibt nix erhalten. Durch einen RESET fängt das Programm ganz von
vorne an, d.h. alle globalen Variablen werden auf 0 initialisiert und
die Ports sind im Zustand nach dem RESET (Eingang, Tristate).
> Die Schaltung funktioniert leider immer noch nicht. Speziell die gelbe> LED ist sehr dunkel. Kann ja auch nicht hardwaremäßig zusammenhängen> weil es ohne Power Down ja auch ging. Power Down geht leider immer noch> nicht wieder. Keine Ahnung an welcher Stelle noch etwas falsch ist.
Ich kenne deine Schaltung nur teilweise. Es wäre hilfreich, wenn du ein
Schaltbild zeichnest und in den Anhang steckst. Handskizze reicht, muss
nichts fein ausgetüfteltes sein.
Bei dem Aufbau der Tastersoftware wurde ja die Portinitialisierung
geändert. Man muss jetzt nachsehen, ob das nach dem Einfügen der
eigentlichen Messroutinen aus der Messsoftware in das Gesamtprogramm
Taster+Messsoftware noch passt.
> Der kapazitive Sensor ist von der Firma Hygrosens Instruments und heißt> und heißt KFS140-MSMD (Conrad Art.-Nr.: 156508 - 62).
Den hast du zur Zeit aber nicht in die Schaltung eingebaut oder? Ich
glaube es war mal von einem resistiven Betauungssensor die Rede.
Mich würde beim KFS140-MSMD dieser Satz aus dem Datenblatt (und der
Preis von 26€/Stk.) abschrecken:
"Der Sensor ist nicht für manuelles löten geeignet, da der Sensor mit
hoher Sicherheit überhitzt und beschädigt wird."
> Der Link zu der> Seite auf der das mit dem kapazitivem Sensor beschrieben ist lautet:> http://elm-chan.org/works/cmc/report.html
Das sieht gut aus. Der Messbereich ist für deinen Zweck geeignet.
nicht
PORTA &= ~(1<<PA3);
heissen?
(Jetzt rein aus Symetriegründen und ohne das Programm analysiert zu
haben)
Du kannst dich vor solchen Kinkerlitzchenfehlern ein wenig besser
schützen, wenn du dir ein paar #define dafür machst
1
#define LED_ROT (1<<PA1)
2
#define LED_GELB (1<<PA2)
3
#define LED_GRUEN (1<<PA3)
dann steht da (und an anderer Stelle ebenso)
1
elseif((messwert>0x32)&&(messwert<0x70))//96
2
{
3
PORTA|=LED_GELB;
4
PORTA&=~LED_ROT;
5
PORTA&=~LED_GRUEN;
6
}
womit die Kommentare überflüssig sind und man leichter sieht, welche
Funktion die Port-Umschaltung hat bzw. auch was da eigentlich passiert
und ob man sich beim Copy&Paste vertan hat.
Ja genau. Das war ein Fehler. Jetzt funktioniert die Messung wieder ganz
einwandfrei. Jetzt ist nur noch die Frage warum das ein- und ausschalten
noch nicht so funktioniert. Ich dachte mir jetzt dass ich die LEDs kurz
vor dem einschlafen nochmal separat deaktivieren muss. Habe euch das im
Code mitgeschickt. Das hat einmal funktioniert. Dann nicht mehr. Kann
natürlich auch mechanisch bedingt sein. Ich verwende so SMD Taster. Evt
hat sich der inzwischen ja schon so abgenutzt?! Oder meine
Entprellroutine ist nicht so perfekt.
Ebenso ist ja auch die Frage bei den blinkenden LEDs. Ich habe das auch
mit delay gemacht. Ist sicher nicht so sauber. Gibt es da Störungen
untereinander?
Stefan:
Das mit dem löten wäre gar kein Problem weil bei mir andere Technologien
zum Einsatz kommen. Es wird nur im Probeaufbau gelötet dann nicht mehr.
Du müßtest mir nur noch ausdeutschen warum der in seiner Schaltung 4
Pins des Controllers benötigt bei diesem Link. Der Sensor ist bei
Reichelt um ca. 12 Euro erhältlich. Keine Ahnung woher der große
Unterschied kommt. Im Moment ist der resistive Betauungssensor eingebaut
und ich bin froh wenn das alles so funktioniert. Die Zugabe wäre die
Schaltung mit kapazitivem Sensor. In meiner Arbeit ist fürs
programmieren keine Zeit vorgesehen da es um Technologiethemen geht.
Daher ist es auch ein Zeitproblem. 3 V meiner Batterie wären also
ausreichend. Auch der Stromverbrauch würde wohl durch das dauernde laden
nicht größer sein als mit dem Spannungsteiler bei mir vermute ich mal.
Stromlaufplan im Anhang. Kleiner Fehler dass LED4 an PA7 statt an PB1
hängt.
Gruß
Thomas
Hier noch der aktualisierte Code. Ich habe beim einschalfen noch die
LEDs deaktiviert. Müßte aber wohl vor dem endgültigen einschlafen sein
denke ich.
Gruß
Th.
Bastler schrieb:
> Hier noch der aktualisierte Code. Ich habe beim einschalfen noch die> LEDs deaktiviert.
Nein, hast du nicht.
Du hast die LEDs deaktiviert, wenn die CPU wieder aufwacht :-)
Die CPU schläft ein, wenn du sleep_cpu() aufrufst. Wenn dieser Aufruf
zurückkommt, ist die CPU aus dem Schlafen schon wieder aufgewacht.
Bastler schrieb:
> Hier noch der aktualisierte Code. Ich habe beim einschlafen noch die> LEDs deaktiviert. Müßte aber wohl vor dem endgültigen einschlafen sein> denke ich.
taster_abfrage(EIN);//Synchronisieren auf Wecktaster
27
}
28
break;
Obacht mit LED_BAT!
Im Code von batterieueberwachung() hast du die Batterie-LED noch an
PORTB hängen und in deiner Ausschaltroutine manipulierst du PORTA.
Kontrolliere das in batterieueberwachung(). Und die DDRA Initialisierung
auch!
Hallo!
Ja das sieht jetzt schon besser aus irgendwie. Allerdings habe ich
unsigned char gerettetes_porta;
aus der while(1) Schleife rausgezogen. So funktioniert es ja auch. Sinn
ist also die Bits von PORTA so wie sie gerade sind in der Variable zu
sichern. Nur wenn ich sie dann lösche im nächsten Schritt steht dann in
der Variable nicht 0x00?? Ich habe ja alles auf 0 gesetzt.
Gerät läßt sich jetzt aussschalten.
Kann mir jemand diese Schaltung erklären die oben zur Auswertung des
kapazitiven Sensors im Anhang ist. Ich brauche da wohl nur bisschen
umdimensionieren weil ich ja nur 3V Vcc habe oder? Welche Portpins
brauche ich da von meinem ATTINY24V dafür. Passt ja nicht analog.
Gruß
Thomas
Bastler schrieb:
> Hallo!>> Ja das sieht jetzt schon besser aus irgendwie. Allerdings habe ich>> unsigned char gerettetes_porta;>> aus der while(1) Schleife rausgezogen. So funktioniert es ja auch. Sinn> ist also die Bits von PORTA so wie sie gerade sind in der Variable zu> sichern. Nur wenn ich sie dann lösche im nächsten Schritt steht dann in> der Variable nicht 0x00?? Ich habe ja alles auf 0 gesetzt.
Nö. Der alte Zustand von PORTA steht in gerettetes_porta und der neue
Zustand (LEDs aus) wird neu nach PORTA geschrieben. gerettetes_porta ist
eine eigene Speicherstelle im RAM und wird nicht durch die Zuweisung an
eine andere Speicherstelle (PORTA) beeinflusst - gerettetes_porta ist ja
kein Zeiger o.ä.
> Gerät läßt sich jetzt aussschalten.> Kann mir jemand diese Schaltung erklären die oben zur Auswertung des> kapazitiven Sensors im Anhang ist. Ich brauche da wohl nur bisschen> umdimensionieren weil ich ja nur 3V Vcc habe oder? Welche Portpins> brauche ich da von meinem ATTINY24V dafür. Passt ja nicht analog.
Du meinst http://elm-chan.org/works/cmc/report.html ?
Elm Chan erklärt das doch sehr gut.
Er verwendet AIN0 und AIN1 um Vc mit der halben Versorgungsspannung (0,5
* 5V) zu vergleichen und dabei wird die Zeit gemessen, bis das von 0
ansteigende Vc und halbe Versorgungsspannung gleich sind. Die gemessene
Zeit geht dann in die Formel zur Berechnung von C ein.
Für den Vergleich wird der Analog Comparator des µC benutzt. Auch der
Attiny24V hat den. Vc geht auf AIN0 (PA1) und die halbe
Versorgungsspannung auf AIN1 (PA2). Leider hast du da schon LEDs
geplant. Die LEDs müsstest du an andere Pins hängen, weil du den Analog
Comparator für die C-Messung brauchst!
Um die Messung genauer zu machen macht Elm Chan zwei Messungen mit
Vc/Vcc = 0,5 und 0,17. Er stellt über PB2 ein, welche Spannung an AIN1
reinkommen soll (0,17 * Vcc bzw. 0,5 * Vcc) je nachdem wie PB2
geschaltet wird: PB2 Tristate Input AIN0 ist 0,5Vcc und PB2 LOW Output
(=GND) AIN1 ist 0,17Vcc.
Zu der geringeren Vcc bei deinem System fällt mir spontan wenig ein. Die
Formeln bzw. das Messprinzip sollte auch bei geringerem Vcc
funktionieren, weil es auf das Verhältnis Vc/Vcc ankommt und weil das
exakt auf 0,5 bzw. 0,17 eingestellt wird.
Elm Chan benutzt auch noch den Transistor Q1 und sich weiss nicht wie
sich der mit seinem Basiswiderstand bei Vcc = 3V verhält. Soweit ich
sehe ist der Q1 aber nur dazu da, um den unbekannten Kondensator ggf.
mit mehr Saft zu laden, d.h. er spielt eine Rolle bei grossen C, wenn
das Laden mit R5 zu lange dauern würde. Bei deinem sehr kleinen C im
hundert pF Bereich kann dieser Schaltungsteil wohl wegfallen.
Das wäre ja relativ einfach zu realisieren. Habe nochmals versucht die
Schaltung aufzuzeichnen wie sie bei mir ungefähr aussehen müßte. Durch
das Durchschalten des Transistors Q1 in der Ursprungsschaltung wird ja
praktisch nur der Widerstand verkleinert. Dadurch fließt wohl mehr Strom
in Cx. Folge: Die Ladezeit wird geringer wie du auch schon gesagt hast.
PA1 und PA2 könnte ich relativ Problemlos freimachen. Den Kontakt zum
Umschalten kann ich ja dann ganz einfach z.B. auf PA3 legen. PA3 ist
dann ein Eingang. Wenn ich dann 0 anlege verändert sich der
Spannungsteiler und ich habe für das Spannungsverhältnis 0.169... also
0,17. Was ist das aber dann für ein Zustand wenn ich das
Spannungsverhältnis 0,5 benötige? Da müßte der 10k in der Luft hängen.
Welche Möglichkeiten siehst du noch den Stromverbrauch zu reduzieren.
Ich würde meine Widerstände gerne viel größer machen. Also R7, R8 und
R9. Habe ja nur eine Batterie (CR2032) mit einer Kapazität von 200mAh
und der Spannungsteiler zieht ja dauernd Strom egal ob ich im Power Down
Modus bin oder nicht. Habe mal so bisschen gerechnet. Bei Vcc/2 fließen
um die 38µA. Da ist aber der Controller noch gar nicht dabei. Das Teil
würde dann ja maximal ein halbes Jahr oder so intakt sein. Ist das aber
wohl der Preis den ich dafür zahle dass ich nur so eine "kleine"
Batterie verwende? Was ist für eine Lebensdauer normal für so Lithium
Batterien wenn ich irgendein anderes Gerät habe? Es könnte nämlich
passieren dass die Technologie dazu zwingt dass ein Batterietausch nicht
mehr möglich ist.
Tut mir leid dass ich mich in diesen Bereichen doch etwas dumm anstelle.
Gruß
Thomas
Bastler schrieb:
> Was ist das aber dann für ein Zustand wenn ich das> Spannungsverhältnis 0,5 benötige? Da müßte der 10k in der Luft hängen.
Genau, das müsste er. Geht. Den Pin als Eingang schalten und den
internen Pullup-Widerstand ausgeschaltet lassen. Dann ist der Pin
Tristate
([[http://www.mikrocontroller.net/articles/Ausgangsstufen_Logik-ICs#Tristate]])
- so hochohmig, dass man meint der 10k bambelt in der Luft.
> Welche Möglichkeiten siehst du noch den Stromverbrauch zu reduzieren.
Ich würde zweistufig vorgehen. Zunächst die Schaltung so wie sie ist
aufbauen und testen bzw. die Software entwickeln. Dann optimieren und
zwar in Hardware und in Software.
> Ich würde meine Widerstände gerne viel größer machen. Also R7, R8 und> R9. Habe ja nur eine Batterie (CR2032) mit einer Kapazität von 200mAh> und der Spannungsteiler zieht ja dauernd Strom egal ob ich im Power Down> Modus bin oder nicht.
Vielleicht kann man auch in Hardware den Spannungsteiler und die
Versorgung des Sensors von einem Outputpin aus betreiben statt von Vcc
aus. Diesen Versorgungspin kann man vorm Schlafengehen Tristate oder LOW
schalten, um den Dauerstrom im externen Schaltungsteil im Schlafzustand
zu minimieren.
Bei den Anzeige-LEDs forschen, ob es Methoden gibt, die mit weniger als
deinen 1,5mA zu betreiben, z.B. gepulst statt kontinuierlich
(http://members.misty.com/don/ledlocu.html#ckt bei deinem System dann
pulsen per Software).
In Software kommt es enorm darauf an, wie oft die Messungen gemacht
werden sollen. Nur pro Usereingabe oder auch regelmäßig alle x
Sekunden/Minuten/Stunden/Tage... Das alles geht in die Energiebilanz
rein.
Hinweise zum Energiesparen sind ja im Datenblatt angegeben. Abschalten
was geht... Vielleicht kannst du auch noch in der Taktrate runter gehen.
Habe auch nicht nachgesehen - ist der attiny24v bereits ein besonders
energiesparender µC von Atmel oder gibt es geeignetere?
> Habe mal so bisschen gerechnet. Bei Vcc/2 fließen> um die 38µA. Da ist aber der Controller noch gar nicht dabei. Das Teil> würde dann ja maximal ein halbes Jahr oder so intakt sein. Ist das aber> wohl der Preis den ich dafür zahle dass ich nur so eine "kleine"> Batterie verwende? Was ist für eine Lebensdauer normal für so Lithium> Batterien wenn ich irgendein anderes Gerät habe?
1-2x im Jahr Batteriewechsel wäre für mich als Anwender OK. Ich habe
aber auch Uhren u.ä. Geräte, deren vergleichbare Batterie deutlich
länger als 1 Jahr hält.
> Es könnte nämlich> passieren dass die Technologie dazu zwingt dass ein Batterietausch nicht> mehr möglich ist.
Wurde schon überlegt, alternative Energiequellen anzuzapfen? Vielleicht
geht was mit Solarzelle, Thermolelement? Oder kann ein Akku eingebaut
werden, der vom Anwender regelmäßig aufgeladen wird? Ist das zumutbar?
Guten Morgen!
Jetzt habe ich zunächst mal nochmal mit meinem Code ein Problem. Das mit
der Batterieüberwachung funktioniert jetzt plötzlich nicht mehr. Hat
aber schon mal funktioniert. Kann mir nur vorstellen dass es irgendwie
nicht mehr angewählt wird aber keine Ahnung warum. Habe auch mal das
ganze Blinken auskommentiert. Reicht aber immer noch nicht. Ich wollte
ja dass wenn die Batterie schwach ist alle 4 Sekunden so ein kurzes
Flashen zu sehen ist. Habe nur irgendwie das Gefühl dass sich die beiden
Delays der roten Led und der Bat LED stören. Wo es noch funktioniert hat
war plötzlich die Geschwindigkeit eine andere. Kann das sein?
Ok. Das mit dem Tristate ist mir jetzt klar.
Ich habe die Bauteile aus meiner aufgezeichneten Schaltung soeben
bestellt. Allerdings hat mein Attiny nicht mehr genug Pins frei. Naja
obwohl wenn ich den resistiven Sensor abhänge dann würde es schono
funktionieren. Dann habe ich genau drei Pins. Wenn ich allerdings einen
Pin suche an den ich den Spannungsteiler hinhänge wirds schwer. Da
könnte man aber glaube ich jederzeit einien Pin der ISP Schnittstelle
verwenden glaube ich.
Bei den LEDs sehe ich keine andere Möglichkeit. Ich verwende bereits
Low-Power SMD LEDs. 2mA. Da werde ich glaube ich kaum noch günstiger
fahren. Allerdings dürte das kein Problem sein. Sie leuchten eh nur beim
einschalten. Die rote blinkt recht schnell und die Bat-LED blinkt nur
alle 4 Sekunden kurz.
Ich denke meine Taktrate ist mit 1Mhz eh schon relativ gering. Habe da
wenig Erfahrung muss ich sagen.
Ok also ich denke mit der Batterie die 200mAh Stunden Kapazität besitzt
sollte das dann doch so weit funktionieren. Weiss jetzt auswendig nicht
was der Attiny an Strom zieht aber grob überschlagen müßte das für ein
halbes Jahr reichen. Man kann ja auch noch einen richtigen Onoff
Schalter einbauen bei Bedarf.
Ein Controllerwechsel wäre aus Zeitgründen völlig unmöglich. Auch an
sowas hätte ich gedacht. Klappt aber wohl nicht mehr.
Alternative Quellen kommen wohl nicht in Frage. Es soll ja alles winzig
klein sein. Diese Batterie scheint mir eine der kleinsten Energiequellen
zu sein die verfügbar sind.
Dann werde ich mich jetzt mal schlau machen wie man mit dem Comparator
umgeht. Habe ich auch noch nie gemacht geschweige denn gezählt wie lange
es dauert bis er die andere Spannung erreicht hat. Sind also zwei
Messungen. Laden bis 0,17 der VCC erreicht und laden bis 0,5 VCC
erreicht oder? Wird das Ding dann wieder entladen eigentlich?
Gruß
Thomas
Bastler schrieb:
> Ich habe die Bauteile aus meiner aufgezeichneten Schaltung soeben> bestellt. Allerdings hat mein Attiny nicht mehr genug Pins frei.
???
Du hast 4 LEDs, 2 Taster, ein Sensor, macht 7 Pins.
Dann sind von den 12 IOs also noch 5 übrig.
Peter
Bastler schrieb:
> Jetzt habe ich zunächst mal nochmal mit meinem Code ein Problem. Das mit> der Batterieüberwachung funktioniert jetzt plötzlich nicht mehr. Hat> aber schon mal funktioniert. Kann mir nur vorstellen dass es irgendwie> nicht mehr angewählt wird aber keine Ahnung warum.
Ich hatte schon geschrieben, dass die Batterie-LED am falschen Port
hängt. Schaltplan und Code passen nicht zusammen.
Was anderes zu der Batteriegeschichte... Die LEDs haben bestimmte
Durchflussspannungen und zwar unterschiedliche je nach Farbe
(Halbleitermaterial). Wenn deine Batteriespannung mit der Zeit sinkt,
ist irgendwann kein Betrieb der LEDs mehr möglich; sie leuchten einfach
nicht mehr, weil die Durchflussspannung unterschritten ist bzw. der
Strom nicht mehr ausreicht (Remember (I_led =
(U_batt-U_led)/Vorwiderstand). Vielleicht hast du Glück und die CR2032
hat eine flache Entladungskurve so dass (Ubatt-Uled) lange annähernd
konstant ist...
> Habe auch mal das> ganze Blinken auskommentiert. Reicht aber immer noch nicht. Ich wollte> ja dass wenn die Batterie schwach ist alle 4 Sekunden so ein kurzes> Flashen zu sehen ist. Habe nur irgendwie das Gefühl dass sich die beiden> Delays der roten Led und der Bat LED stören. Wo es noch funktioniert hat> war plötzlich die Geschwindigkeit eine andere. Kann das sein?
Definitiv kann das sein. So ein exaktes Blinken würde man mit einem
Timer implementieren und nicht mit einer Softwareverzögerung, die nicht
mehr stimmt sobald man neue Funktionen (Tastenabfrage, ggf. anderes
Messprinzip) implementiert oder den Code refaktoriert (umstrickt).
> Allerdings hat mein Attiny nicht mehr genug Pins frei.LEDs kann man multiplexen. Mit drei Pins kann man sechs LEDs betreiben
(http://en.wikipedia.org/wiki/Charlieplexing). Deine active-high
angeschlossene LEDs kann man auch problemlos an den Pins betreiben, die
für ISP benutzt werden; sie flackern dann beim ISP-Programmieren. Zum
Betrieb mit angeschlossenem ISP-Programmer:
http://www.mikrocontroller.net/articles/AVR_In_System_Programmer#ISP-Pins_am_AVR_auch_f.C3.BCr_andere_Zwecke_nutzen> Bei den LEDs sehe ich keine andere Möglichkeit. Ich verwende bereits> Low-Power SMD LEDs. 2mA. Da werde ich glaube ich kaum noch günstiger> fahren.
Die Idee in dem Link oben ist: Die LEDs müssen nicht dauernd leuchten,
um was zu sehen. Wenn die LED 1s leuchten soll, reicht vielleicht auch
1/10tel der Zeit oder 10x 1/100tel der Zeit...
> Ich denke meine Taktrate ist mit 1Mhz eh schon relativ gering. Habe da> wenig Erfahrung muss ich sagen.
Ausprobieren. Man kann durch eine Fuse die internen 1 MHz noch mal durch
8 teilen.
> Dann werde ich mich jetzt mal schlau machen wie man mit dem Comparator> umgeht. Habe ich auch noch nie gemacht geschweige denn gezählt wie lange> es dauert bis er die andere Spannung erreicht hat.
Kannst du ausrechnen anhand der Formel, die Elm Chan angegeben hat. Das
Laden wird bei dem angegebenen Widerstandswert 3M3 ca. 0,1 bis 0,4ms
dauern. so gesehen ist es wahrscheinlich kontraproduktiv den Takt unter
1 MHz zu senken, weil das an der erreichbaren Auflösung knabbert. Ist
aber nur ein Bauchgefühl ohne grosse Fehlerrechnung.
> Sind also zwei> Messungen. Laden bis 0,17 der VCC erreicht und laden bis 0,5 VCC> erreicht oder?
Habe mir den Quellcode von Elm Chan noch nicht angesehen. Aus der
Beschreibung lese ich, dass dazwischen der C wieder entladen wird. Es
werden zwei Zeiten gemessen t(0,17V laden) und t(0,5V laden)
> Wird das Ding dann wieder entladen eigentlich?
Selbstverständlich wird der C wieder entladen und zwar über R7 zur
Strombegrenzung und über PB0 = Output LOW.
Habe mir nochmal die Datenblätter der 4 verwendeten LEDs durchgelesen.
Bei allen ist forward voltage typisch 1,8 (min. 1,7V und max 2,2V). Bei
einem Strom von 2mA. Das ist bei allen gleich. Ich habe ja auch schon
die Spannung bis auf 2.3 V runtergeregelt damit ich sehe ob meine
Batterieled leuchtet. Da arbeitet alles einwandfrei. Erst bei 2 - 2,1 V
wirds kritisch mit dem Leuchten. Ich habe ja als Vorwiderstand jeweils
680 Ohm gewählt. Das heißt bei gewünschten 2mA fällt dort 1,36V ab. Im
Idealfall habe ich 3V Batteriespannung. Ok stimmt. Das heißt für die LED
bleiben eigentlich nur noch 1,64V. Das bedeutet meine Rs müssen kleiner
werden. Hatte hald mit den 680ern bis jetzt keine Probleme. Evt. versuch
ichs ja mal mit den 620ern. Wobei das ja auch noch zu groß ist. Wenn
maximal 2,2 V an den LEDs ok sind dann kann ich sogar irgendwas mit 500
Ohm verwenden.
Ok das heißt es würde wieder kompliziert werden weil ich ja dann einen
Timer brauche fürs Blinken. Schade. Hatte gehofft ich kann das ganz
einfach mit den delays machen. Brauche ja für de kapazitiven Sensor auch
einen Timer.
Das mit dem Multiplexen scheint ja auch nicht so schwer zu sein.
Direkt programmieren brauche ich da ja nichts. muss nur sagen welche
Leitung auf Ausgang und High oder welche auf Ausgang und low gezogen
wird.
Naja meinen Takt hätte ich jetzt schon auf 1MHz belassen. Das mit dem
Entladen ist mir jetzt auch klar. Werde morgen die Schaltung mal
aufbauen.
Also von meiner ISP Schnittstelle könnte ich Miso Mosi und SCL auch noch
für LEDs benutzen. Sprich wenn ich auf meinen Betauungssensor verzichte
habe ich erst mal 3 Pins nur für den kap. Sensor und dann könnte ich auf
6 LEDs erweitern für die Anzeige.
Naja ich werde mir wohl jetzt erst mal überlegen wie ich das mit dem
Blinken hinbekomme. Das gleichmäßige Blinken der roten LED dürfte ja ok
sein. Da taucht kein delay auf. Störend ist ja wohl eher das delay beim
Bat LED. Da wollte ich ja dieses kurze flaschen alle 4 s.
Gruß
Th.
Bastler schrieb:
> Also von meiner ISP Schnittstelle könnte ich Miso Mosi und SCL auch noch> für LEDs benutzen.
Besser nur MISO, die anderen könnten durch die LEDs zu stark belastet
werden. Hängt von Deinem Programmer ab, was der treiben kann.
Aber Du könntest sie für Tasten nehmen.
Wenn Du alle 12 IO nehmen willst, kannst Du nen Bootloader reinbrennen,
der braucht dann nur einen Pin (z.B. ein Tasterpin).
Wenn Du es elegant machen willst, steuere die LEDs spannungsabhängig per
Software-PWM. Dann brauchen sie nicht zuviel Strom bei voller Batterie
und sind noch hell genug bei schwacher Batterie.
Ich würde die LEDs eh nicht übers ganze Programm verteilt schalten, da
verliert man schnell den Überblick.
Ich würde ne Statemaschine machen und am Ende des Main werden dann die
LEDs entsprechend dem aktuellen Zustand geschaltet.
Dann siehts Du auch sofort logische Fehler in Deinem Programmablauf,
d.h. wenn verschiedee States gegeneinander kämpfen (Es gewinnt immer der
letzte).
Wenn aber direkt eine Funktion ne LED einschaltet und eine andere aus,
siehts Du das nicht.
Die Task zum Batterietest muß erstmal 16 Dummy-Wandlungen wegschmeißen,
da die Bandgap sehr hochohmig ist:
http://wap.taur.dk/bandgap.pnghttp://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=80458&start=all&postdays=0&postorder=asc
Peter
Bastler schrieb:
Mal sehen, ob es im Netz eine Entladekurve einer CR2032 gibt.
Interessiert mich jetzt doch, wieviel Energie bei welcher
"Abschaltspannung" noch nicht rausgesuckelt ist. Da gibt es sicher auch
gute/schlechte Hersteller. Kann mir nicht vorstellen, dass die
Billigsortimenter und Qualitätshersteller identische Batterien haben.
> Ok das heißt es würde wieder kompliziert werden weil ich ja dann einen> Timer brauche fürs Blinken. Schade. Hatte gehofft ich kann das ganz> einfach mit den delays machen.
Richtig gemacht wird es mit Timer sogar deutlich eleganter.
Du hast dann eine Variable und dort steht drin welche LEDs an/aus sind
und der Timer-Interrupt lässt die automatisch blinken! Im Programm
fütterst du bloss die Variable mit dem aktuellen Zustand.
Und du hast eine Uhr laufen und kannst z.B. X Sekunden nach der
Usereingabe den AVR automatisch schlafen legen und so Energie sparen,
wenn der User "vergisst" das Gerät auszuschalten.
Der Vorschlag von Peter mit der state machine ist sehr gut. Den würde
ich sofort umsetzen. Passt super in obiges Konzept!
> Brauche ja für de kapazitiven Sensor auch> einen Timer.
Für die C-Messung benutzt du eine andere Art Timer. Der /Analog
Comparator/ kann so konfiguriert werden, dass die Input Capture
Function in Timer/Counter1 getriggert wird. Das gibt dir einen
Zeitstempel für den Zeitpunkt, an dem 0,17V bzw. 0,5V erreicht werden.
Die Differenz zum Start-Zeitstempel ist dann die jeweils verstrichene
Ladezeit.
Soweit ich das oberflächlich im Datenblatt sehe, müsste beides (Timer
als Uhr und Timer als Zeitstempler) sogar zusammen auf dem Hardware
Timer1/Counter1 gehen. Alternativ Timer0 für die 1s-Uhr nehmen und
Timer1 für die C-Messung.
Hallo!
Zunächst mal wieder herzlichen Dank für eure Unterstützung. Ich habe
jetzt mal versucht einen Stromlaufplan mit meinem Sensor zu zeichnen.
Habe auch die VCC Versorgung für die Sensorschaltung auf einen Portpin
gelegt. Ist das so weit korrekt? Wenn ich aber jetzt nur noch MISO
benutzen darf dann kann ich auf die konventionelle Art nur 3 LEDs + das
Bat LED anschließen. Meint ihr wirklich dass ich an MOSi, SCK nichts
mehr ranhängen darf? Alle Lampen werden ja nie auf einmal leuchten. Ich
glaube mein Controller kann 20 mA. Die LEDs funktionieren mit 2mA.
Also das mit der Statemachine betrache ich für mich speziell als viel zu
komplex. Ich habe das einmal gehört habe aber keinen blassen Schimmer
was dahintersteckt. Und natürlich wieder das alte Problem. Ursprünglich
war diese Arbeit eine reine Technologiearbeit. Dann sollten irgendwann
mal die Lämpchen blinken und dann habe ich mich schweren Herzens dazu
entschlossen mit dem programmieren zu beginnen. HAbe programmieren immer
gehasst und bin dem ausgewichen wo es nur geht. Ich weiss jetzt durch
eure Hilfe inzwischen sehr viel nur kann ich mich hald gar nicht so
reinlesen und reinarbeiten weil einfach keine Zeit dafür da ist. Darum
stelle ich ja auch oft Fragen die für jemanden der es kann sehr trivial
sind! Es hieß damals eine halbe Seite Code... Jetzt sind wir bei
ungefähr 4-5 Seiten!!! Das mit dem Timer würde ich mir noch zutrauen.
Das mit dem Comparator auch noch für den kapazitiven Sensor. Nur auch
hier ist es ja jetzt wieder so dass ich zunächst mal keine Ahnung habe.
Ich weiss hald jetzt viel besser was man mit den ganzen Registern usw
macht.
Das mit dem Bootloader habe ich nicht verstanden... Das mit dem PWM
glaube ich da brauche ich nicht anzufangen... Würde zu lange dauern. Das
einzige wäre jetzt noch das mit dem Timer mit dem Blinken und dass mein
Spannungsteiler an nem Portpin liegt um im Power Down Strom zu sparen.
Stefan: Der Timer über den du bei der C-Messung sprichst der ist aber
auf meinem ATTINY 24 schon drauf oder? Wäre eigentlich für die Sache mit
dem kap. Sensor ein digitaler Komparator nicht besser? Der Ausgang des
analogen Komparators endet ja quasi irgendwo intern im Controller. Also
ich muss den softwaremäßig verschalten dass bei einem dementsprechenden
Ausgang was auch immer passiert.
Also meine Batterie hält jetzt wirklcih schon sehr lange. ICh glaube
200mAh sind wirklich eine ganze Menge und voll und ganz ausreichend.
Kann ja auch den Strom im Betrieb messen und den Strom im Power Down.
Dann kann man ja ne ungefähre Abschätzung machen wie lang das Ding hält.
Kommt natürlich auch immer drauf an wie lange es eingeschaltet bleibt.
Bei 2,4 V Batteriespannung ist ja auch noch nicht aller Tage Abend. Dann
leuchtet mein BatterieLED und man weiss dann Achtung es wird ungenau!
Gruß
Thomas
Bastler schrieb:
'n Abend ;-)
> Habe auch die VCC Versorgung für die Sensorschaltung auf einen Portpin> gelegt. Ist das so weit korrekt?
Sieht für mich OK aus. Kannst ja im Prototypen einen Jumper vorsehen, so
dass du entweder auf Vcc oder auf PA0 gehen kannst.
> Wenn ich aber jetzt nur noch MISO> benutzen darf dann kann ich auf die konventionelle Art nur 3 LEDs + das> Bat LED anschließen. Meint ihr wirklich dass ich an MOSi, SCK nichts> mehr ranhängen darf? Alle Lampen werden ja nie auf einmal leuchten. Ich> glaube mein Controller kann 20 mA. Die LEDs funktionieren mit 2mA.
Hängt wie Peter geschrieben hat vom ISP-Programmer ab; genauer, was der
"treiben" kann, also wie viel Strom der liefern kann. Wenn an den
Programmierleitungen deine LEDs hängen, fliesst dort ein Teil des
Programmierstroms ab.
Typische 74HC/HCT244 (http://www.nxp.com/pip/74HC_HCT244_3.html) wie im
Atmel-ISP STK200 können 6mA (HCT) bis 7,8mA (HC) treiben. Bei
Nicht-Low-Current LEDs mit ILed typ. 10-20 mA gäbe es schon Probleme.
Mit deinen Low-Current-LEDs mit ILed <2mA würde ich es im Prototypen
riskieren. ggf. beim Prototypen die Leitung zwischen LED und
Vorwiderstand mit Jumper trennbar machen oder bei dem Serienmodel die
Vorwiderstände nach dem ISP-Programmieren einlöten.
Mit anderen ISP-Programmeradaptern kann das ganz anders aussehen. Z.B.
wenn statt dem Buffer 74HC/HCT244 ein AVR Dienst schiebt, kann der ja
deutlich mehr treiben!
> Also das mit der Statemachine betrache ich für mich speziell als viel zu> komplex. Ich habe das einmal gehört habe aber keinen blassen Schimmer> was dahintersteckt. Und natürlich wieder das alte Problem. Ursprünglich> war diese Arbeit eine reine Technologiearbeit. Dann sollten irgendwann> mal die Lämpchen blinken und dann habe ich mich schweren Herzens dazu> entschlossen mit dem programmieren zu beginnen. HAbe programmieren immer> gehasst und bin dem ausgewichen wo es nur geht. Ich weiss jetzt durch> eure Hilfe inzwischen sehr viel nur kann ich mich hald gar nicht so> reinlesen und reinarbeiten weil einfach keine Zeit dafür da ist. Darum> stelle ich ja auch oft Fragen die für jemanden der es kann sehr trivial> sind! Es hieß damals eine halbe Seite Code... Jetzt sind wir bei> ungefähr 4-5 Seiten!!! Das mit dem Timer würde ich mir noch zutrauen.> Das mit dem Comparator auch noch für den kapazitiven Sensor. Nur auch> hier ist es ja jetzt wieder so dass ich zunächst mal keine Ahnung habe.> Ich weiss hald jetzt viel besser was man mit den ganzen Registern usw> macht.
Die Gefahr sich zu verzetteln besteht immer; man nennt das Featuritis.
dagegen hilft bei Projektbeginn genau zu beschreiben, was man bis wohin
haben will. Z.B. deine erste Version mit dem Betauungssensor.
Klar ist es schöner, wenn man mehrere Messpunkte haben kann, so wie es
mit dem kap. Sensor möglich ist. ABER man öffnet leicht eine Büchse der
Pandora., weil neue Voraussetzungen und nötiges Wissen dazu kommen.
Ich weiss nicht, ob ich dir erzählen darf, dass du noch an die
Kalibrierung des kap. Sensors denken musst. Also wie hängt die gemessene
Kapazität mit dem Messwert rel. Feuchte zusammen. Man kann das mit dem
bekannten Wasserdampfgehalt über bestimmten Salzlösungen machen. Die
Kurve im Datenblatt sind ja nur typ. Werte und der aktuelle Aufbau muss
kalibriert werden. Genaugenommen muss vielleicht jedes gebaute Gerät 1x
"im Werk" kalibriert werden. Bei einer grossen Serie kommt dann
natürlich die Frage auf, wie macht man das schnell und wo speichert man
dauerhaft den individuellen Kalibrierwert für die Umrechnung Kapazität
nach rel. Feuchte... ROM, d.h. im Programm? Würde bedeuten pro Gerät 1
Kompilerlauf... Oder im EEPROM? Da ist der nächste Wissensbaustein: Wie
geht man mit EEPROM um?
> Das mit dem Bootloader habe ich nicht verstanden... Das mit dem PWM> glaube ich da brauche ich nicht anzufangen... Würde zu lange dauern.
Bootloader ist IMHO ein Feature... Software-PWM auch, aber ein nicht so
schwer zu lösendes (s.u.)
> Das> einzige wäre jetzt noch das mit dem Timer mit dem Blinken und dass mein> Spannungsteiler an nem Portpin liegt um im Power Down Strom zu sparen.> Stefan: Der Timer über den du bei der C-Messung sprichst der ist aber> auf meinem ATTINY 24 schon drauf oder?
Ja im AVR sind mehrere Timer drin. Die wahrscheinlich einfachste Lösung
ist folgende:
Timer0 ist als allg. durchlaufende Uhr geschaltet. Die Interruptroutine
kontrolliert die Zustandsvariablen für die LEDs und übernimmt die
Aufgabe, die LEDs AN/AUS/Blinkend zu schalten.
Die Zustandvariablen für die LEDs werden im Userprogramm gesetzt. Ist
der Wert 0, ist die betreffende LED aus. Hat sie einen Wert, toggelt der
Timer0 die LED mit XOR, d.h. die LED blinkt. Die Zahl der Blinkaktionen
wird um eins vermindert und der Timer0 wartet auf den nächsten
Interrupt. Wenn die Interrupts im 1s Abstand kommen, hast du ein 1Hz
Blinken.
Für die bessere Energiebilanz kann man per Software in der Timer-ISR
auch leicht einrichten, dass ein 1 Hz Blinken gemacht wird, bei dem die
LED nur z.B. 10% leuchtet und 90& dunkel ist statt 50:50 wie üblich. Ist
aber ein Feature...
Umgekehrt geht natürlich auch - Batterie ist voll => 10:90,
Batteriespannung sinkt dann Verhältnis steigern bis wegen mir 90:10 -
das ist die Software-PWM, die Peter meint. Durch die unterschiedliche
Leuchtdauer bleibt der Helligkeitseindruck trotz sinkender
Batteriespannung gleich. Ist aber ein Feature...
Durch die Zahl kannst du mehr Infos aus dem AVR rausschaffen. Bsp. 1
Blinken für je 10 rel. Feuchte (oder je gemessene 10pF). Oder eine
Kombination von 2 LEDs für die Ausgabe eines Binärwertes oder
Zehner+Einer Stellen oder Zehner+Fünfer-Stellen. Ist aber ein Feature...
Timer1 wäre nur für Input Capture zuständig. Hier werden die Ladezeiten
gemessen.
> Wäre eigentlich für die Sache mit> dem kap. Sensor ein digitaler Komparator nicht besser? Der Ausgang des> analogen Komparators endet ja quasi irgendwo intern im Controller. Also> ich muss den softwaremäßig verschalten dass bei einem dementsprechenden> Ausgang was auch immer passiert.
Im Prinzip hast du einen digitalen Komparator mit Aussage Vkap < Vref
oder Vkap >= Vref. Der Zeitpunkt des Wechsels (Flankentyp ist
konfigurierbar) wird über den Input Capture gemessen. Komplett in
AVR-interner Hardware! Du musst "nur" den AC und Timer1 des AVRs intern
passend konfigurieren, die Messung starten (Strom per Outputpin ins
Messsystem geben) und wirst per Interrupt benachrichtigt, wenn das
Ereignis eingetreten ist. Dann den Zeitwert abholen.
> Also meine Batterie hält jetzt wirklcih schon sehr lange. ICh glaube> 200mAh sind wirklich eine ganze Menge und voll und ganz ausreichend.> Kann ja auch den Strom im Betrieb messen und den Strom im Power Down.> Dann kann man ja ne ungefähre Abschätzung machen wie lang das Ding hält.> Kommt natürlich auch immer drauf an wie lange es eingeschaltet bleibt.
Genau hier kann der Timer0 oben auch helfen. Z.B. wenn der x Sekunden
gelaufen ist (Ausprobieren was praktikabel ist), schickt der den AVR in
den Power Down, indem er eine Anweisung taster_abfrage(AUS); macht, die
beim nächsten Durchlauf von while(1) zum Schlafen führt. Ist aber ein
Feature...
> Bei 2,4 V Batteriespannung ist ja auch noch nicht aller Tage Abend. Dann> leuchtet mein BatterieLED und man weiss dann Achtung es wird ungenau!
Kann man mit leben. Baue den Prototypen. Einen funktionierenden. Und die
weiteren Features stellst du dann als Erweiterungen vor. Den Zeitaufwand
dafür kannst du abschätzen und - jetzt das coole - es ist keine
Hardwareänderung mehr nötig: Die Erweiterungen sind reine
Firmwareupdates!
Und da käme wieder der Bootloader wieder ins Spiel ;-) Wenn der
Endanwender die Updates machen soll, kann er keinen ISP-Adapter
benutzen, das ist aus verschiedenen Gründen unpraktikabel. ABER einen
einfachen Adapter (serielle Übertragung mit Sende-LED auf PC-Seite und
Empfangs-Fotodiode auf µC-Seite) um den Bootloader zu füttern, das habe
ich bei verschiedenen Konsumergeräten bereits gesehen. Ist aber ein
Feature...
Bastler schrieb:
> Also das mit der Statemachine betrache ich für mich speziell als viel zu> komplex. Ich habe das einmal gehört habe aber keinen blassen Schimmer> was dahintersteckt.
Ist eigentlich eine einfache Methode, um Klarheit in den Programmablauf
zu bekommen, d.h. den Überblick zu behalten.
Jeder Zustand entspricht einer Nummer (0...n). Und zu jedem Zustand gibt
es eine Routine (case), die etwas macht. Diese Routine beinhaltet dann
auch die Abfragen, um in einen anderen Zustand zu wechseln.
Das ganze bedingt natürlich, daß man sich erstmal einen
Programmablaufplan macht, d.h. welche Zustände gibt es und wie sind die
Beziehungen zueinander.
> Ursprünglich> war diese Arbeit eine reine Technologiearbeit. Dann sollten irgendwann> mal die Lämpchen blinken und dann habe ich mich schweren Herzens dazu> entschlossen mit dem programmieren zu beginnen.
Wie ist denn überhaupt so Dein Zeitplan?
Ich will Dir ja Deinen Optimismus nicht nehmen, aber die
Kapazitätsmessung halte ich für einen Anfänger als sehr kompliziert.
Ich würde dann erstmal eine SW-UART vorsehen, um Debugausgaben
darstellen zu können, d.h. Zahlenwerte in einem Terminalprogramm auf dem
PC.
Die Meßwerte lassen sich schlecht nur mit LEDs darstellen, Du mußt aber
irgendwie feststellen, welche Werte Deine Kapazitätsmessung liefert, ob
die eingermaßen linear und stabil sind.
Peter
Ok. Also ich habe meinen Prototypen aufgebaut. Auch ein Jumper habe ich
vorgesehen damit man zwischen VCC und Portpin wechseln kann. Habe diesen
Pin jetzt mal auf PA0 gelegt. Ich vermute ja mal dass dafür die ISP-Pins
von Haus aus ausscheiden. Ich gehe auch davon aus dass ich meinen Kap
Sensor (über 3,3M) und meinen "Referenzspannungsteiler" an das Gleiche
Potential anschließen muss weil es sonst ungenau ist. Dann vermute ich
muss dieser Pin als Ausgang konfiguriert werden wie bei den LEDs und auf
High gelegt werden. Damit liegt ungefähr VCC an diesem ausgewählten
Portpin an und ich kann ihn vorm einschlafen deaktivieren. Das wird
analog auch bei meinem Betauungssensor funktionieren nur kann ich dann
nicht als Referenz VCC angeben sondern muss irgendwie sagen dass des
über den Port rauskommt. Ist das so richtig?
Also ich habe als ISP Programmer den AVRISP MKII. Habe mir auch schon
das Manual durchgelesen allerdings stoße ich nirgends auf etwas was den
zu treibenden Strom betrifft. Kann mich auch erinnern dass ich irgendwo
schon mal was gelesen habe dass man die ISP Pins mitbenutzen kann.
Ausgeschlossen ist wohl VCC GND und Reset vermute ich. Warum kann man
gerade den MISO mitnutzen? Peter meinte ja auch für Taster geht das
eher. Ich könnte also meinen Power Down Taster z.B. auf MOSI legen. Muss
den Pin hald als Eingang konfigurieren und Pull Up setzen. Dann hätte
ich mir ja wieder einen der anderen Pins gespart.
Also das mit der Statemachine würde ich mal nach dieser Arbeit privat
versuchen wenn ich einfach auch die Zeit zum rumprobieren habe. Davon
würde ich also schon gerne Abstand nehmen.
Das mit dem kalibrieren hört sich natürlich schon etwas an wie
Alptraum!! Mir war es aber schon klar weil ichs ja auch gelesen habe.
Ich denke mal ich werde 0 und 100 % rel Feuchte kalibrieren und alles
andere ist dann in gleichen Abständen dazwischen. Das ist natürlich eine
gigantische Arbeit. Würde aber dann wohl die Werte vom Prototypen auf
die anderen Teile übernehmen.
Ich kann diesen Timer0 also auch mehrfach verwenden oder? Also nehmen
wir an das Bat-Led flasht alle 4 Sekunden auf. Dann bleibt das Programm
ja nicht da drin "hängen". Kann ich dann gleichzeitig sagen so jetzt
blinke mit der roten LED wenn es gerade so nass ist? Oder muss ich da
dann wieder einen anderen Timer vorsehen? Genauso ist das ja auch bei
meiner Tastenentprellung. Auch da habe ich ja delay verwendet. Also im
ungünstigsten Fall könnten drei Ereignisse gleichzeitig auftreten wo ich
einen Timer benötige. Also Batterie schwach, so nass dass rot blinkt und
ich möchte das Gerät ausschalten.
Also das mit dem Timer 1 betrifft dann meinen kap. Feuchtesensor. Der
macht also genau das richtige und ist irgendwie mit meinem Comparator
"getriggert".
Es gibt bereits jeweis nen Prototyp. Also eine Europlatine mit dem
Betauungssensor und eine mit dem kap. Sensor. Das gute ist dass jede
Schaltung auch einen ISP Stecker hat. Sprich ich kann im Nachhinein auch
noch die Software abändern. Auch meine mit der anderen Technologie
aufgebauten Schaltungen werden diesen Stecker beinhalten da es ja schwer
ist die SMD Attinys auf einer anderen Platine zu programmieren.
Ich sehe schon irgendwie stelle mich ziemlich dumm da meine Beiträge in
diesem Forum immer die längsten werden!!!"gg" Dabei sind die Probleme
die ich habe ja wohl die einfachsten die es nur geben kann.
Gruß
Th.
Zu Peters Beitrag:
Mein Zeitplan besagt eigentlich dass keine Zeit mehr fürs programmieren
ist. Ich suche mir immer wieder freie Minuten wo ich damit ein wenig
arbeiten kann. Bei meinem Betauungssensor sieht es ja eigentlich ned so
schlecht aus. Das einzige wäre noch das mit dem Timer dass des mit dem
Blinken und der Tasterentprellung noch sicherer funktioniert. Das mit
dem Kondensator ist eine reine Zugabe. Wenn ich das schaffe ist es gut.
Wenn nicht dann ist es auch gut. Mir ist schon klar dass der
hardwaremäßige Aufbau noch das geringste Problem ist. Die software ist
ja mein Hauptproblem weil ich davon ja praktisch keine Ahnung hab. Ich
muss mir ja auch erst mal über die Abläufe im klaren sein. Dass ein
Timer Zeit zählt ist mir schon klar. Nur wie man das natürlich
verarbeitet und was dann der Timerinterrupt macht und so das weiss ich
nicht. Da werde ich mir erst nochmal das Tutorial durchlesen und dann
nach ähnlichen Beispielen in diesem Forum suchen. Vielleicht ist es auch
erstmal gut wenn ich einfach mal so probiere eine LED zum blinken zu
bringen mit Timer. Ohne Sensor, Taster und was auch immer.
Gruß
Th.
Bastler schrieb:
> Ok. Also ich habe meinen Prototypen aufgebaut. Auch ein Jumper habe ich> vorgesehen damit man zwischen VCC und Portpin wechseln kann. Habe diesen> Pin jetzt mal auf PA0 gelegt. Ich vermute ja mal dass dafür die ISP-Pins> von Haus aus ausscheiden. Ich gehe auch davon aus dass ich meinen Kap> Sensor (über 3,3M) und meinen "Referenzspannungsteiler" an das Gleiche> Potential anschließen muss weil es sonst ungenau ist. Dann vermute ich> muss dieser Pin als Ausgang konfiguriert werden wie bei den LEDs und auf> High gelegt werden. Damit liegt ungefähr VCC an diesem ausgewählten> Portpin an und ich kann ihn vorm einschlafen deaktivieren. Das wird> analog auch bei meinem Betauungssensor funktionieren nur kann ich dann> nicht als Referenz VCC angeben sondern muss irgendwie sagen dass des> über den Port rauskommt. Ist das so richtig?
Weiss ich nicht aus dem Stegreif. Dazu müsste ich mir erst den Sinn
dieser Zeile wieder heraussuchen:
messwert = adcmessung((0<<REFS1)|(0<<REFS0)|(0<<MUX5)|(0<<MUX0));
Und überlegen, wo/wie der Betauungssensor angeschlossen war. In dem
aktuellen Schaltbild ist der ja nicht eingezeichnet. Tipp: Kommentare im
Programm schaden nicht. Schreib rein, was wichtig ist, wie z.B. der
passenede Hardwareanschluss zum aktuellen Code!
Die Zeile bedeutet, dass als Vref Vcc benutzt wird und PA0 als Eingang
für den ADC benutzt wird. Das beisst dich mit dem Schaltplan für das
Gerät mit dem kap. Sensor, wenn dort PA0 als Ausgang für die
Messspannungen (Sensor und Vergleich) benutzt wird.
> Also ich habe als ISP Programmer den AVRISP MKII. Habe mir auch schon> das Manual durchgelesen allerdings stoße ich nirgends auf etwas was den> zu treibenden Strom betrifft.
Im Userguide des AVRISP MKII steht, dass Pull-Ups an den
Programmierleitungen not stronger than 820 Ohm sein sollen. stronger
heisst hier kleinere Widerstandswerte. Das wären bei 5V 6mA - passt zu
den obigen Überlegungen mit den HC/HCT ICs.
> Kann mich auch erinnern dass ich irgendwo> schon mal was gelesen habe dass man die ISP Pins mitbenutzen kann.
Es gibt eine Appnote von Atmel Hardware Considerations in der was zu ISp
und SPI-Bus steht. Vielleicht meinst du die?
> Ausgeschlossen ist wohl VCC GND und Reset vermute ich. Warum kann man> gerade den MISO mitnutzen? Peter meinte ja auch für Taster geht das> eher.
MISO wird von zum programmierenden AVR betrieben. Dessen Pin kann mehr
Saft liefern. Mehr als die Logikbausteine/Levelkonverter/Buffer in den
ISP-Programmieradaptern.
> Ich könnte also meinen Power Down Taster z.B. auf MOSI legen. Muss> den Pin hald als Eingang konfigurieren und Pull Up setzen. Dann hätte> ich mir ja wieder einen der anderen Pins gespart.
Du brauchst eigentlich nur einen Taster max. zwei.
Wichtig zum Aufwecken ist, dass ein Taster an dem Pin mit INT0 hängt.
Den darfst du nicht wo anders hin legen. Die Ausnahme ist nur die
Variante mit dem Rausschmeissen aus dem Schlaf per RESET. Ein
RESET-Taster als Eingabetaster zu verwenden ist aber sehr unpraktisch.
PS: Usereingaben kann man auch über die Zahl der Tastendrücke, Dauer der
Tastendrücke ("lang", "kurz") und Kombinatioen (alias "Morsen")
machen...
> Also das mit der Statemachine würde ich mal nach dieser Arbeit privat> versuchen wenn ich einfach auch die Zeit zum rumprobieren habe. Davon> würde ich also schon gerne Abstand nehmen.> Das mit dem kalibrieren hört sich natürlich schon etwas an wie> Alptraum!! Mir war es aber schon klar weil ichs ja auch gelesen habe.> Ich denke mal ich werde 0 und 100 % rel Feuchte kalibrieren und alles> andere ist dann in gleichen Abständen dazwischen. Das ist natürlich eine> gigantische Arbeit. Würde aber dann wohl die Werte vom Prototypen auf> die anderen Teile übernehmen.
Hängt von der Fertigung der Sensoren ab. Bei guter Reproduzierbarkeit
könnte das gehen. Wenn du Pech hast, kommen die Sensoren aus
unterschiedlichen Chargen und sind zu stark unterschiedlich, um mit
einer "Kennlinie" behandelt zu werden.
> Ich kann diesen Timer0 also auch mehrfach verwenden oder? Also nehmen> wir an das Bat-Led flasht alle 4 Sekunden auf. Dann bleibt das Programm> ja nicht da drin "hängen". Kann ich dann gleichzeitig sagen so jetzt> blinke mit der roten LED wenn es gerade so nass ist? Oder muss ich da> dann wieder einen anderen Timer vorsehen? Genauso ist das ja auch bei> meiner Tastenentprellung. Auch da habe ich ja delay verwendet. Also im> ungünstigsten Fall könnten drei Ereignisse gleichzeitig auftreten wo ich> einen Timer benötige. Also Batterie schwach, so nass dass rot blinkt und> ich möchte das Gerät ausschalten.
Ja ein Timer würde per Interrupt alle LEDs bedienen. Stell dir den als
"Hintergrundprogramm" vor, der parallel zu deinem Userprogramm läuft.
> Es gibt bereits jeweis nen Prototyp. Also eine Europlatine mit dem> Betauungssensor und eine mit dem kap. Sensor. Das gute ist dass jede> Schaltung auch einen ISP Stecker hat. Sprich ich kann im Nachhinein auch> noch die Software abändern. Auch meine mit der anderen Technologie> aufgebauten Schaltungen werden diesen Stecker beinhalten da es ja schwer> ist die SMD Attinys auf einer anderen Platine zu programmieren.
Bei SMD AVRs muss es nicht unbedingt der fette ISP Stecker sein. Es gibt
hier im Forum Diskussionen, wo Leute nach alternativen
Kontaktmöglichkeiten gefragt haben und z.B. Pads am Platinenende genannt
wurden, die mit temporären Clips oder Federpins kontaktiert wurden. Man
kann auch direkt an die Pins gehen... Meine Überlegungen von damals
(Beitrag "Re: Challenger-Clip Miniatur(SMD)-Klemmprüfspitzen?") sind inzwischen im
Kauf geendet ;-)
> Ich sehe schon irgendwie stelle mich ziemlich dumm da meine Beiträge in> diesem Forum immer die längsten werden!!!"gg" Dabei sind die Probleme> die ich habe ja wohl die einfachsten die es nur geben kann.
So sehe ich das nicht. Du bringst eine interessante aber - für meinen
Level als Hobbyist - nicht zu exotische/schwierige Fragestellung auf,
kannst sie verständlich formulieren, nimmst Rat an, bist bereit selbst
zu denken/arbeiten... dann mag man/ich auch antworten. Der Platz
"kostet" nix; da muss man nix sparen.
Hallo
Also ich habe jetzt für meinen kapazitiven Sensor folgenden Schaltplan
angefertigt. Ich habe jetzt die Möglichkeit 6 LEDs zum leuchten zu
bringen. Gibt es eigentlich hier auch die Möglichkeit über #define so zu
konfigurieren dass man nur noch LED_1on oder wie auch immer schreiben
kann. Wenn ich z.B. LED1 anschalten will sieht ja der Code
folgendermaßen aus:
DDRB |= (1<<PB0); // Ausgang
DDRA |= (1<<PA7); // Ausgang
DDRA &= ~(1<<PA5); // Eingang
PORTB |= (1<<PB0); // PB0 auf High
PORTA &= ~(1<<PA7); // PA7 auf GND
PORTA &= ~(1<<PA5); // PA5 Tristate (hängt quasi in der Luft)
Das ist natürlich extrem lästig wenn man immer diesen ganzen Schrott
schreiben muss. Wie kann ich mir da behelfen weil ich ja mit #define
immer nur z.B. einen Port bearbeiten kann. Oder kann man da verunden???
Als nächstes nochmal zu dem Problem in meiner Schaltung mit dem
Betauungssensor. Ich möchte ja den Spannungsteiler statt an VCC auf
einen Portpin legen. Dadurch erhoffe ich mir eine gewaltige
Stromersparnis im Zustand Power-Down. Habe jetzt einfach mal gesagt dann
leg ich den Spannungsteiler an Pin 10. Das ist PA3. Da war früher in
meiner alten Schaltung eine LED dran. Der ist aber jetzt frei.
Es war ja die Frage was die Zeile
messwert = adcmessung((0<<REFS1)|(0<<REFS0)|(0<<MUX5)|(0<<MUX0));
bedeutet. REFS1 und REFS0 auf 0 bedeutet VCC als analoge Referenz. Ich
sehe gerade dass mit 01 für REFS1 und REFS0 die externe AREF an PA0
angesprochen werden kann. Ist das quasi schon die Lösung. Sprich der
Spannungsteiler zieht die Spannung aus PA0. Mit MUX5:0 auf 0 wähle ich
den Eingang PA0 für meine zu wandelnde Spannung (also zwischen
Vorwiderstand und res. Sensor auf Gnd). Das müßte ich dann z.B. auf PA1
legen damit der PA0 als Spannungsversorgung frei wird. Ist das so
richtig?
NOCH WAS: Es ist selbstverständlich immer nur EIN Sensor in Betrieb.
Also es gibt jetzt nen Prototypen für den Betauungssensor und einen für
den kap. Sensor. Wobei bei dem Prototypen mit dem kap. Sensor auch der
Betauungssensor drauf ist. Mit Jumper hald dass man umswitchen kann.
Damit hat sich die Sache mit der Benutzung von MOSI erledigt. Ich
benutze nur noch Miso wie im Schaltplan zu sehen für die Ansteuerung der
LEDs. Es dürfte ja kein Problem geben wenn ich den auf Ein- oder Ausgang
ziehe oder? Könnte ja sein dass die Schnittstelle gestört wird.
Funktionieren tuts prima. Kann jede LED ansteuern.
Leider kann ich meinen Schnittstellenstecker nicht vermeiden da mein
Basissubstrat kein FR4 ist. Alle Schaltungen haben andere Formen also
funktioniert auch die Möglichkeit mit dem Nadeladapter nicht.
Nochmal zum TIMER. Ich versuche im Moment mit Timer0 meine LEDs zum
blinken zu bringen. Das sollte recht einfach sein. Also sprich pro
Prozessor Takt wird ein Timer um eins erhöht. Ich habe mich entschlossen
bei 1MHz Taktung den 1024 Vorteiler zu benutzen. Das bedeutet bis der
Timer 1 mal überläuft vergehen 0,262144 Sekunden. Wenn ich mein LED also
alle Sekunde ein und nach einer Sekunde wieder ausschalten will könnte
ich den Interrupt bei Overflow verwenden. Allerdings löst der doch bei
jedem Überlauf aus. Wie kann ich dem klarmachen dass er erst beim 4.
Überlauf den Interrupt auslösen soll? Werde gegebenenfalls morgen den
Code den ich bis jetzt habe auch noch hier reinstellen. Der Timer wäre
ja für mich quasi der Schlüssel damit alles funktioniert. Möchte den ja
auf der Schaltung vom Betauungssensor für die Tastenentprellung
verwenden. Da habe ich ja das delay mit 80ms. Außerdem für das blinken
der roten LED und vor allem für das alle 4 Sekunden aufblinken der
Batterie LED.
So wie ich das verstanden habe kann ich da ein und denselben Timer
benutzen. Ich muss dann praktisch nur in der Interruptserviceroutine für
die drei verschiedenen Ereignisse etwas festlegen. Ist diese Überlegung
richtig?
Gruß
Thomas
Bastler schrieb:
> Also ich habe jetzt für meinen kapazitiven Sensor folgenden Schaltplan> angefertigt. Ich habe jetzt die Möglichkeit 6 LEDs zum leuchten zu> bringen.
Es wäre deutlich einfacher, wenn du die LEDs nur an einem PORT hängen
hättest. Dann könnte man prima den Zustand einlesen, verrechnen
(verUNDen/verODERn) und in einem Rutsch setzen. Bei der jetzigen
Variante musst du teuflisch aufpassen, was mit den übrigen LEDs
passiert, wenn du eine LED schaltest.
Generell Du kannst die Grobarbeit "verstecken" und für einen
Anweisungsblock ein mehrspaltiges #define benutzen, wenn du den
Funktionsoverhead nicht möchtest
1
// LED1_ON:
2
// PB0 Output HIGH
3
// PA7 Output LOW
4
// PA5 Input Z (int. Pull-up aus)
5
#define LED1_ON() \
6
do { \
7
DDRA |= (1<<PA7); \
8
PORTA &= ~(1<<PA7); \
9
DDRA &= ~(1<<PA5); \
10
PORTA &= ~(1<<PA5); \
11
DDRB |= (1<<PB0); \
12
PORTB |= (1<<PB0); \
13
} while(0)
oder eine Inline-Funktion, wenn wenige Aufrufe der Funktion kommen
1
// LED1_ON:
2
// PB0 Output HIGH
3
// PA7 Output LOW
4
// PA5 Input Z (int. Pull-up aus)
5
staticinlinevoidLED1_ON(void)
6
{
7
DDRA|=(1<<PA7);
8
PORTA&=~(1<<PA7);
9
DDRA&=~(1<<PA5);
10
PORTA&=~(1<<PA5);
11
DDRB|=(1<<PB0);
12
PORTB|=(1<<PB0);
13
}
oder eine reguläre Funktion, wenn viele Aufrufe im Programm verstreut
sind
1
// LED1_ON:
2
// PB0 Output HIGH
3
// PA7 Output LOW
4
// PA5 Input Z (int. Pull-up aus)
5
staticvoidLED1_ON(void)
6
{
7
DDRA|=(1<<PA7);
8
PORTA&=~(1<<PA7);
9
DDRA&=~(1<<PA5);
10
PORTA&=~(1<<PA5);
11
DDRB|=(1<<PB0);
12
PORTB|=(1<<PB0);
13
}
Beim Umschalten von LEDs sollten Blitzer der anderen LEDs vermieden
werden. Deshalb würde ich zuerst alles abschalten (fehlt oben) und dann
die Anschaltfunktionen so schreiben, dass das Anschalten der jeweiligen
Versorgungsspannung der letzte Befehl ist.
Die Abschaltfunktion dafür könnte man bei allen LEDs an einem Port
wunderschön universell halten und z.B. die betreffenden PORTx auf LOW
setzen - unabhängig von der DDRx Stellung!
> Als nächstes nochmal zu dem Problem in meiner Schaltung mit dem> Betauungssensor. Ich möchte ja den Spannungsteiler statt an VCC auf> einen Portpin legen. Dadurch erhoffe ich mir eine gewaltige> Stromersparnis im Zustand Power-Down. Habe jetzt einfach mal gesagt dann> leg ich den Spannungsteiler an Pin 10. Das ist PA3. Da war früher in> meiner alten Schaltung eine LED dran. Der ist aber jetzt frei.
Siehe oben! Überlege dir dringend, was an PA3 und PB0 hängt zu tauschen!
> Es war ja die Frage was die Zeile> messwert = adcmessung((0<<REFS1)|(0<<REFS0)|(0<<MUX5)|(0<<MUX0));
Die Frage hatte ich im gleichen Posting beantwortet ;-) Mir war der Teil
bei dem kapazitiven Sensor nicht klar. Die Funktion zur Feuchtemessung
muss dort komplett anders aussehen. Der Code für den Betauungssensor hat
in dem Programm für den kapazitiven Sensor eigentlich nichts zu suchen.
> NOCH WAS: Es ist selbstverständlich immer nur EIN Sensor in Betrieb.> Also es gibt jetzt nen Prototypen für den Betauungssensor und einen für> den kap. Sensor. Wobei bei dem Prototypen mit dem kap. Sensor auch der> Betauungssensor drauf ist. Mit Jumper hald dass man umswitchen kann.
Wie soll das fertige Gerät aussehen - auch beide Sensoren oder nur
einer? Zeichne das unbedingt in deinen Stromlaufplan ein! Nur wenn man
alle Fakten kennt, kann man Änderungsvorschläge oder Kontrollen machen.
> Nochmal zum TIMER. Ich versuche im Moment mit Timer0 meine LEDs zum> blinken zu bringen.> Wie kann ich dem klarmachen dass er erst beim 4.> Überlauf den Interrupt auslösen soll?
Statische Zählervariable in der ISR hochzählen lassen und nur bei jedem
vierten Mal die Aktion ausführen.
> Ich muss dann praktisch nur in der Interruptserviceroutine für> die drei verschiedenen Ereignisse etwas festlegen. Ist diese Überlegung> richtig?
Beschreibe vorher in einfachen Worten die Funktion der LEDs bzw. die
Ereignisse. Welche sind Nurleuchter? Welche sind Blinker? Welche können
zusammen leuchten oder blinken? Wenn mehrere blinken - gleichzeitig oder
wechselseitig oder egal?
Z.B.
Batteriecheck:
Batterie low => LED6 blinkt 4x im 1Hz Takt
Batterie nicht low => LED6 aus
Feuchtemessung:
Feuchte zu hoch => LED1 (rot) leuchtet dauernd
Feuchte normal => LED2 (grün) blinkt im 1Hz Takt dauernd
Feuchte zu niedrig => LED3 (gelb) leuchtet dauernd
Jeweils eine LED ist aktiv!
Mahlzeit!
Also die Schaltung für den kap. Feuchtemesser ist umgebaut. Die LEDs
liegen jetzt an PA3, PA5 und PA7. Für den Betauungssensor lasse ich die
Schaltung mit 3 LEDs weil das ja ohnehin sehr ungenau ist.
Ich glaube so weit ich das selbst beurteilen kann dass ich das über
define Regeln möchte. Allerdings funktioniert das leider so nicht wie
ich es mir dachte. Habe den Code mitgeschickt. Mir geht es im ersten
Schritt nur darum die 6 LEDs möglichst einfach zum leuchten zu bringen.
Im zweiten Schritt möchte ich dann wie man sieht versuchen über den
Timer0 OVF ein Blinken herbeizuführen.
Es kann sein dass mein Fehler sehr einfach ist. Er erwartet jedenfalls
einen identifier oder ein ( vor dem do und jeweil vor allen whiles.
Keine Ahnung ob ich das jetzt immer noch so kompliziert machen muss wenn
alle LEDs am gleichen Port hängen. Man könnte deine Ausführungen auch so
verstehen dass ich nur DDR definen soll und Spannung oder nicht dann im
Programm. Ist natürlich schon seeehr unübersichtlich wenn das define
über mehrere Zeilen geht!
Das mit dem Ausschalten müßte ja passen dass ich die Ports auf 0 setze.
Man könnte das aber wohl auch außerhalb von Main machen.
Nochmal zu den Problemen mit dem Betauungssensor. Eine spätere fertige
Schaltung besteht entweder aus dem Betauungssensor oder dem kap.
Feuchtesensor. Wie es aussieht werde ich den Betauungssensor dann auch
mit 3 LEDs belassen. Wenn ich das also richtig verstanden habe gehört
der Spannungsteiler des Betauungssensors an PA0 gehängt. Da steht ja
auch AREF. Die eigentliche Auswertung zwischen dem "Vorwiderstand" und
dem veränderlichen Widerstand könnte ich ja mit MUX5:0 auf PA7 legen.
Sprich dann sollte dort die AD Wandlung stattfinden und nicht mehr auf
PA0. Und genauso wie ich die LEDs vorm einschlafen ausschalte muss ich
dann den PIN PA0 (mit AREF) wohl auf 0 legen. Dieser Pin wird wohl auch
als Ausgang geschaltet werden müssen.
Der kapazitive Sensor wäre die Kür wenn ichs schaffe. Der soll dann mit
den 6 LEDs an PA3, Pa5 und PA7 betrieben werden. Mir ist klar dass der
Code vom Betauungssensor beim kap Sensor null verloren hat. Die
Auswertung passiert ja über den Comparator mit dem Timer1 wie du schon
geschrieben hast.
FÜr den Anfang möchte ich mich aber einfach mal damit begnügen
herauszufinden wie ich die 6 LEDs steuern kann und wie man mit Timer0
und dem OVF Timerinterrupt umgeht. In der Anfängermethode bringe ich die
LEDs ja schon zum leuchten und habe mit dem im Anhang befindlichen Code
ein Lauflicht realisiert.
Das mit dem Timer muss ich wirklich erst noch verstehen.
Gruß
THomas
In dem Code fehlen bei den #define die A\ Zeichen am Ende der Zeile.
Zeilen mit \ am Zeilenende werden vom C-Präprozessor als eine Zeile
behandelt. Fehlen die \ zählen die Zeilen als (sinnloser) Code.
Wenn alle LED am gleichen Port hängen, ist es wesentlich einfacher!
1
#define MASKE (~((1<<PA3) | (1<<PA7) | (1<<PA5)))
2
3
#define LED_OFF()
4
do \
5
{ \
6
PORTA&=MASKE;/* alle LEDs aus */ \
7
}while(0)
8
9
//
10
// LED1_ON
11
// PA3 Output HIGH
12
// PA7 Output LOW
13
// PA5 Input Z
14
//
15
#define LED1_ON() \
16
do \
17
{ \
18
uint8_t tmp; \
19
/* hier LED_OFF() bzw. am Anfang der ISR */ \
20
tmp = DDRA & MASKE; \
21
tmp |= (1<<PA3) | (1<<PA7) | (0<<PA5); \
22
DDRA = tmp; \
23
PORTA |= (1<<PA3); \
24
} while (0)
Bei der Multiplex-Schaltung kannst zu einem Zeitpunkt immer nur eine LED
leuchten lassen. Damit es aussieht, als ob mehrere LEDs leuchten
(Batterie+Feuchte z.B.), musst du umschalten.
Du musst also die ISRs häufiger aufrufen lassen und die Aktionen für die
LEDs schneller durchführen. Durch die Trägheit des Auges verschmilzt das
Flackern bei genügend schnellen Wechseln zu einem konstanten Leuchten.
Die Möglichkeiten für den Prescaler sind begrenzt. Rechne mal mit
verschiedenen Werten. Ganzzahlen kann man durch Tunen der Schritte 256-x
bekommen. Und wenn du EXAKT eine Sekunde haben willst, dann gibt es
dafür einen ausführlichen Artikel im Wiki ([[AVR - Die genaue Sekunde /
RTC]]).
1.000.000 1024 256 => 3,x Aufrufe zu 262,x ms. Bei Bei 6 LEDs kommen
3 überhaupt nicht an die Reihe!
1.000.000 64 256 => 61,x Aufrufe zu je 16,x ms. Bei 6 LEDs kommt
jede LED ca. 10 mal an die Reihe. Das flackert wahrscheinlich noch.
Ausprobieren.
1.000.000 8 256 => 488,x Aufrufe zu je 2,x ms. Bei 6 LEDs bekommt
jede LED ca. 80 mal die Möglichkeit jeweils für ca. 2ms zu leuchten.
Zusammen dann etwa 160ms. Das ist 1/6tel Leuchtzeit einer
nichtgemultiplexten LED.
Und noch schneller - Prescaler 1... Bereits Prescaler 8 geht deutlich
auf Kosten der Zeitverteilung Userprogramm / Interruptprogramm.
Irgendwann bekommt das Userprogramm seine Arbeit nicht mehr erledigt.
Und noch schlimmer: bei zuviel Code in der ISR und zu kurzen Abständen
gehen Interrupts verloren - es wird ungenau!
Wenn du ein Mittelding zwischen Prescaler 64 und Prescaler 8 haben
willst, dann kannst du noch mit dem Startwert des Timers arbeiten. Statt
die vollen 256 Schritte bis zum nächsten Overflow, dürfen es ja auch
weniger sein. Hier kommen die verschiedenen Betriebsmodi des Timers ins
Spiel, die den Startwert bzw. den Wert bei dem der Interrupt auftritt
nutzen und ggf. automatisch nachladen.
OK. Das war jetzt das Dauerleuchten der LEDs. Jetzt zum Blinken z.B. mit
1s an und 1s aus (1 Hz). Du kannst das in der ISR machen. Bei
Prescalerfall 8 488 Aufrufe LED im Multiplex halten und brav anschalten.
Dann 488 Aufrufe lang nicht anschalten! Dann muss aber die ISR wissen,
welche LED Blinken sollen und welche Dauerleuchten und welche Aus sind.
Das sind 3 Zustände und das passt nicht schön zu dem was unten noch
kommt ;-)
Oder du kannst das im Userprogramm machen. Die ISR zählt nur Sekunden
hoch (alle 488 Aufrufe Sekundenzähler um eins erhöhen) und im
Userprogramm setzt du bei geraden Sekunden BLINKEN_AN und bei ungeraden
Sekunden BLINKEN_AUS.
Das bringt das Thema Kommunikation zwischen ISR und Userprogramm auf.
Woher weiss die ISR welche LEDs an und welche aus sein sollen? Hier gibt
es den Weg über gemeinsame volatile definierte Variablen. Für An und Aus
bietet sich eine Bitvariable an, weil das Platz spart.
volatile uint8_t led_zustand;
Im Userprogramm (im grossen while(1)) setzt du dann für eine LED die in
der ISR über Multiplex angeschaltet werden soll das betreffende Bit in
der Bitvariablen hier am Beispiel Blinken:
volatile uint8_t sekunden;
#define LED1 1
// Userprogramm
if (!(sekunden & 1)) // gerade Sekunden
led_zustand |= (1<<LED1); // AN
else
led_zustand &= ~(1<<LED1); // AUS
Oder wenn du das Blinken komplett in der ISR behandeln willst, dann
kannst du zwei solche Bitvariablen nehmen. Ich rate aber davon ab, weil
die dann notwendige Fallunterscheidung den Code in der ISR deutlich
aufbläht.
#define LED1 1
#define LED2 2
volatile uint8_t led_daueran;
volatile uint8_t led_blinken;
// Userprogramm
led_daueran |= (1<<LED2); // LED2 an
led_blinken |= (1<<LED1); // LED1 blinken;
OK. die Aufgabe der ISR ist jetzt grob umrissen. Jetzt die Feinheiten.
Beim Einstieg in die ISR werden zunächst alle LEDs ausgeschaltet.
Dann wird geschaut, welche von den 6 LEDs grundsätzlich beim Multiplexen
dran ist. Hier wird mit einem statischen Zähler gearbeitet, der die
Nummer der LED angibt. Die Nummer der LED kann man aus dem Zähler über
den Modulo-Operator bekommen (zähler % 6 ergibt die Zahlen 5,4,...,1,0)
Für die betreffende LED wird geschaut, ob sie laut led_zustand leuchten
soll. Soll sie, wird sie angeschaltet. Das kann man schön in ein switch
packen.
Jetzt noch an die Sekunden fürs Blinken denken. Wenn der zähler 488
erreicht hat, ist eine Sekunde verstrichen. Ups das sind mehr als 8-Bit!
Also zahler 16 Bit gross machen ODER einfach halbesekunden zählen, d.h.
244 Durchläufe... Fertig in der ISR.
Und der Fall oben mit den halbesekunden:
#define LED1 1
// Userprogramm
if (!(halbesekunden & 2)) // 0,0 bis 0,5 bis <1,0
led_zustand |= (1<<LED1); // AN
else // // 1,0 bis 1,5 bis <2,0...
led_zustand &= ~(1<<LED1); // AUS
Hallo!!
Oje da hatte ich jetzt wieder zu kämpfen. Naja ich lerne dazu. Jetzt
wird der Beitrag glaube ich bald geschlossen bei so vielen
Einträgen!!“g“ Für diesen „Crashkurs“ könntest du ja wirklich Geld
verlangen!!“g“
Zunächst nochmal zu den „\“ Zeichen. Ich habe da in meinem C-Buch auf
die Schnelle nichts gefunden. Ich versteh das einfach mal so dass es das
Gleiche wäre wenn ich alles in eine Zeile schreiben würde. Verstehen tu
ich das nur nicht warum das so zusammenhängend sein muss. Kann ich da
einfach sagen weil es in einer do/while Schleife einfach so ist dass des
in einer Zeile sein muss? Do/while frägt ja im Unterschied zu while erst
am Ende ab ob es weitergeht. Ich vermute mal das while(0) heißt dass es
immer weiter geht…? Andererseits sieht es mir unlogisch aus dass man
hierfür überhaupt eine Schleife braucht. Rein von der Logik hätte ich
gesagt könnte ich doch schreiben
#define LED_OFF (PORTA &= ~((1<<PA3)|(1<<PA7)|(1<<PA5)))
Unabhängig davon ergeben ja dann meine ganze #define-Befehle eine halbe
bis ganze Seite. Ist das normal in der Programmierung???
Zu #define LED1_ON():
Ich definiere zunächst die Variable tmp. tmp = DDRA & MASKE; wird die
LEDs wohl löschen. Warum muss da aber DDRA dabei sein?? Dann schreibe
ich die Bits für die Datenrichtung in tmp und schreibe dies dann
wiederrum in DDRA. Das letzte ist dann dass ich PORTA3 auf high setze.
Nur den Anfang verstehe ich dabei eben nicht.
Zu dem mit do … while(0) habe ich jetzt gefunden dass man das macht wenn
man mehrere Anweisungen in ein Makro packen möchte. Und while(0) heißt
scheinbar einmal ausgeführt. Also sprich bei jedem Aufruf im Programm
einmal. Ist das richtig?
Also ich bekomme jetzt alle LEDs so nacheinander zum leuchten. Das war
mir klar dass immer nur eine leuchten kann. Das ist auch voll in
Ordnung. Für die Batterie habe ich ein 7. LED vorgesehen. Das hat dann
auch eine andere Farbe.
Also wegen dem Vorteiler. Ich brauche sicher nicht exakt eine Sekunde.
Es wird keiner mit der Stopuhr da sitzen und schaun ob die LED exakt
alle 4 Sekunden ein und ausgeht. Also bei dem 1024-Teiler könnte ich gut
mit den 0,26.. Sekunden leben. Und für die 4 Sekunden nehme ich das hald
mal 16. Also quasi 16 Überläufe. Wenn ich den Timer für Unterschiedliche
Anwendungen benutze muss ich ja immer den gleichen Prescaler verwenden
oder? Meinen Taster habe ich ja z.B. mit 80ms entprellt. Sprich hier
könnte ich dann 3 Überläufe verwenden. Nur wie weiss der Timer dann wo
er gerade steht?? Sagen mir das LED-Bat leuchtet. Dann wird der Taster
Power Down betätigt. Dann muss er ja wissen wo muss ich einsteigen.
Steigt er dann erst beim nächsten Überlauf mit 0 ein???
Das mit dem CTC Mode brauche ich dann wohl für den kap. Sensor. Da kann
ich ja einen bestimmten Wert eingeben. Sprich die Spannung die erreicht
werden soll oder? Und wenn er die erreicht hat dann weiss ich die Zeit.
Das kann aber doch Timer0 auch. Du hast ja gemeint dazu benötige ich
Timer1.
Also du würdest mir keinen 1024er-Vorteiler empfehlen. Sehe ich das
richtig oder war das nur wegen dem Missverständnis dass 2 LEDs
gleichzeitig leuchten sollen was ja nicht der Fall ist.
Also die ganzen Dinge mit dem Multiplexen kann ich dann wohl
vernachlässigen wenn immer eine LED leuchten soll? So wie ich das
verstanden habe steht dann in der ISR ganz wenig. Das wird ja wohl
besser sein wenn ich das so löse weil ja auch noch das Entprellen dazu
kommt. Dann mach ich die ISR nicht so voll.
Allerdings habe ich jetzt noch ein Denkproblem. Also angenommen ich
nehme den Teiler 8. Was bedeutet das mit den 488,x Aufrufen?? Ich komme
nie auf diese Zahl. Ich dachte immer bei dem Overflow muss ich die
Anzahl der Überläufe zählen??? Sprich nach dem 4. Überlaufen oder was
auch immer. Das kann man ja über TOV0 zählen lassen. Ich vermute mal
wenn es zum ersten Mal überläuft dann steht da ne 1 drin. Durch die ISR
wird’s dann wieder gelöscht. Ich dachte ich zähle da bis da 4 mal eine 1
drinstand. Also werde ich der ISR auch noch sagen müssen mache beim 1.,
2. und 3. Überlauf nichts oder. Die ISR wird ja grundsätzlich ausgelöst
beim Überlauf. Außer ich definiere des außerhalb so. Man kann doch den
Teiler gar ned so groß machen dass ich eine Sekunde ohne Überlauf
realisieren kann!! Bei 1024 komme ich ja auf 262,144ms. Also zunächst
1000000 / 1024. Das Ergebnis als Kehrwert dann hab ich die Zeit für 1
Erhöhung. Ich glaub Inkrement ist das. Bei mir sind das 1,024ms. Also
immer alle Milisekunde wird der Timer eins mehr. Und das dann mal 256 =
0,262144 s. Das mit den halben Sekunden verstehe ich nicht.
Ok. Also jetzt habe ich die 2,048ms. Sprich: Takt: 1MHz. Teiler =8. Nach
genau 2,048ms läuft der Timer über. Das verstehst du jetzt wohl unter
Aufrufen. Ok und die 488,28 habe ich jetzt auch. Wobei ich die noch ned
ganz verstehe. Den Timertakt verstehe ich das ist der normale Clock
durch den Vorteiler. Aber warum das dann geteilt durch 256??? Da Herz ja
1/s ist heißt das quasi 488 mal ein Interrupt pro Sekunde!!!
OKKKKKKKKKKKKKKK. Jetzt hab ichs geschnallt auch wenn es lange gedauert
hat.
Naja erst noch mal Danke für die Erklärung. Ich werde jetzt versuchen da
was zu basteln auch wenn es sich immer noch unglaublich schwer anhört.
Gruß
Thomas
Bastler schrieb:
> Zunächst nochmal zu den „\“ Zeichen. Ich habe da in meinem C-Buch auf> die Schnelle nichts gefunden. Ich versteh das einfach mal so dass es das> Gleiche wäre wenn ich alles in eine Zeile schreiben würde. Verstehen tu> ich das nur nicht warum das so zusammenhängend sein muss. Kann ich da> einfach sagen weil es in einer do/while Schleife einfach so ist dass des> in einer Zeile sein muss? Do/while frägt ja im Unterschied zu while erst> am Ende ab ob es weitergeht. Ich vermute mal das while(0) heißt dass es> immer weiter geht…? Andererseits sieht es mir unlogisch aus dass man> hierfür überhaupt eine Schleife braucht. Rein von der Logik hätte ich> gesagt könnte ich doch schreiben>> #define LED_OFF (PORTA &= ~((1<<PA3)|(1<<PA7)|(1<<PA5)))
Du könntest es so schreiben. Es wird aber bei grösseren Sachen leicht
unübersichtlich und da ist es in mehreren Zeilen angenehmer zu lesen.
Das Verhalten von \ am Ende von Zeilen ist z.B. im folgenden PDF in
Abschnitt 5.1.1.2 Translation phases beschrieben. Dort wird beschrieben,
wie ein C-Quellcode übersetzt wird.
http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1124.pdf
"Each instance of a backslash character (\) immediately followed by a
new-line character is deleted, splicing physical source lines to form
logical source lines. Only the last backslash on any physical source
line shall be eligible for being part of such a splice. A source file
that is not empty shall end in a new-line character, which shall not be
immediately preceded by a backslash character before any such splicing
takes place."
Das müsste aber auch in üblichen C-Büchern drin stehen.
Der Grund für die do...while(0) Klammer in den Makros ist z.B. hier
erklärt: http://www.rtems.com/ml/rtems-users/2001/august/msg00086.html> Unabhängig davon ergeben ja dann meine ganze #define-Befehle eine halbe> bis ganze Seite. Ist das normal in der Programmierung???
ja. Wenn das stört, kann man die Makros in eine Headerdatei stecken.
> Zu #define LED1_ON():> Ich definiere zunächst die Variable tmp. tmp = DDRA & MASKE; wird die> LEDs wohl löschen.> Warum muss da aber DDRA dabei sein?? Dann schreibe> ich die Bits für die Datenrichtung in tmp und schreibe dies dann> wiederrum in DDRA. Das letzte ist dann dass ich PORTA3 auf high setze.> Nur den Anfang verstehe ich dabei eben nicht.
Noch nicht. Nachlesen kannst du die Technik mit der Maske in
Bitmanipulation
Die Zeile ist da, um den Zustand von DDRA zu holen und um mit der Maske
die LED-Pins in DDR0 auf 0 zu setzen und die Nicht-LED-Pins zu schützen
(so zu lassen wie sie sind). In den folgenden Anweisungen wird in tmp
der wunschzustand für DDR der LED-Pins reingeodert. Dann wird DDRA *in
einem Rutsch* gesetzt. Die Konstruktion mit der Hilfsvariable tmp ist
dafür da, dass man DDRA (bzw. später PORTA) in einem Rutsch setzen kann.
> Zu dem mit do … while(0) habe ich jetzt gefunden dass man das macht wenn> man mehrere Anweisungen in ein Makro packen möchte. Und while(0) heißt> scheinbar einmal ausgeführt. Also sprich bei jedem Aufruf im Programm> einmal. Ist das richtig?
Ja siehe oben.
> Also ich bekomme jetzt alle LEDs so nacheinander zum leuchten. Das war> mir klar dass immer nur eine leuchten kann. Das ist auch voll in> Ordnung. Für die Batterie habe ich ein 7. LED vorgesehen. Das hat dann> auch eine andere Farbe.
Ich glaube du hast akute Featuritis. Ist aber nicht schlimm ;-)
> Also wegen dem Vorteiler. Ich brauche sicher nicht exakt eine Sekunde.> Es wird keiner mit der Stopuhr da sitzen und schaun ob die LED exakt> alle 4 Sekunden ein und ausgeht. Also bei dem 1024-Teiler könnte ich gut> mit den 0,26.. Sekunden leben. Und für die 4 Sekunden nehme ich das hald> mal 16. Also quasi 16 Überläufe. Wenn ich den Timer für Unterschiedliche> Anwendungen benutze muss ich ja immer den gleichen Prescaler verwenden> oder?
Wie gesagt, ich denke mit Prescaler 1024 funktioniert das Multiplexen
der vielen LEDs nicht.
> Meinen Taster habe ich ja z.B. mit 80ms entprellt. Sprich hier> könnte ich dann 3 Überläufe verwenden. Nur wie weiss der Timer dann wo> er gerade steht??
Der Timer kann doch in der ISR eine Variable hochzählen, die du anlegst.
Im Programm schaust du in der Variablen nach, wieviele Aufrufe der Timer
hat, dann wartest du bis x weitere Aufrufe stattgefunden haben.
> Sagen mir das LED-Bat leuchtet. Dann wird der Taster> Power Down betätigt. Dann muss er ja wissen wo muss ich einsteigen.> Steigt er dann erst beim nächsten Überlauf mit 0 ein???
Auf Power Down reagiert dein Userprogramm, d.h. der Teil in dem while(1)
in main(). Die ISR vom Timer hat damit zunächst nichts zu tun.
Im Userprogramm weisst du du musst schlafen gehen. Dann schaltest du die
LEDs aus und lässt den µC pennen gehen. Nach dem Wecken setzt du wieder
den LED-Zustand von vor dem Pennen und weiter geht es.
> Das mit dem CTC Mode brauche ich dann wohl für den kap. Sensor. Da kann> ich ja einen bestimmten Wert eingeben. Sprich die Spannung die erreicht> werden soll oder? Und wenn er die erreicht hat dann weiss ich die Zeit.> Das kann aber doch Timer0 auch. Du hast ja gemeint dazu benötige ich> Timer1.
Nein, das ist noch eine komplett andere Geschichte.
Im Moment bist du noch am Timer0 am bauen. Und der ist nur als Zeitgeber
für das Multiplexen der LEDs und ggf. als Ticker für
Sekunden/Halbsekunden o.ä. am arbeiten.
Die Messung der Kapazität des Sensors ist eine Sache vom Analog
Comparator und der Input Capture Unit eines anderen Timers. Da ist noch
Hirnschmalz gefordert. So weit bin ich auch noch nicht; muss ich mir bei
Elm Chan ansehen. Ich hatte ja geschrieben, dass ich sowas noch nie
gemacht habe.
> Also du würdest mir keinen 1024er-Vorteiler empfehlen. Sehe ich das> richtig oder war das nur wegen dem Missverständnis dass 2 LEDs> gleichzeitig leuchten sollen was ja nicht der Fall ist.
Auch wegen dem Bedienen von >3 LEDs überhaupt und weil flackerndes
Dauerleuchten hässlich wäre.
> Also die ganzen Dinge mit dem Multiplexen kann ich dann wohl> vernachlässigen wenn immer eine LED leuchten soll? So wie ich das> verstanden habe steht dann in der ISR ganz wenig. Das wird ja wohl> besser sein wenn ich das so löse weil ja auch noch das Entprellen dazu> kommt. Dann mach ich die ISR nicht so voll.
Du darfst nicht die Menge an Code in der ISR mit der Zeitdauer in der
ISR verwechseln. Es wird nicht bei jedem Interrupt der komplette Code in
der ISR ausgeführt! Es gibt einen gemeinsamen Teil und einen Teil für
die jeweilige LED. Die Auswahl der jeweiligen LED kann man z.B. mit dem
switch sehr schnell auswählen. Der Code für die restlichen LED kommt in
den folgenden Aufrufen an die Reihe.
> Allerdings habe ich jetzt noch ein Denkproblem. Also angenommen ich> nehme den Teiler 8. Was bedeutet das mit den 488,x Aufrufen?? Ich komme> nie auf diese Zahl. Ich dachte immer bei dem Overflow muss ich die> Anzahl der Überläufe zählen??? Sprich nach dem 4. Überlaufen oder was> auch immer. Das kann man ja über TOV0 zählen lassen. Ich vermute mal> wenn es zum ersten Mal überläuft dann steht da ne 1 drin. Durch die ISR> wird’s dann wieder gelöscht. Ich dachte ich zähle da bis da 4 mal eine 1> drinstand. Also werde ich der ISR auch noch sagen müssen mache beim 1.,> 2. und 3. Überlauf nichts oder. Die ISR wird ja grundsätzlich ausgelöst> beim Überlauf. Außer ich definiere des außerhalb so. Man kann doch den> Teiler gar ned so groß machen dass ich eine Sekunde ohne Überlauf> realisieren kann!! Bei 1024 komme ich ja auf 262,144ms. Also zunächst> 1000000 / 1024. Das Ergebnis als Kehrwert dann hab ich die Zeit für 1> Erhöhung. Ich glaub Inkrement ist das. Bei mir sind das 1,024ms. Also> immer alle Milisekunde wird der Timer eins mehr. Und das dann mal 256 => 0,262144 s.
Und wenn du deine Rechnung mit anderen Prescalerwerten machst?
1.000.000 / 8 dann Kehrwert: Zeit für eine Erhöhung 0,000008 Sekunden (8
µs). Das mal 256 sind dann 0,002048 s (2,048 ms) zwischen den
Overflow-Interrupts.
1s sind 1000ms. Durch 2,048 ms sind... 488,28125 Overflow-Interrupts in
1einer Sekunde!
Wenn du mit Ganzzahlen rechnest (wie oben mit den 4) also mit 488 statt
488,28125, dann ist deine ungenaue "Sekunde" 0,999424 s lang, also etwas
zu kurz.
> Das mit den halben Sekunden verstehe ich nicht.
Um in der ISR Sekunde zu zählen, muss man dort bis 488 zählen. Die
Halbesekunde ist nur eine Hilfskonstruktion, damit in der ISR keine
Zählvariable gebraucht wird, in die 488 reinpasst. Um Halbesekunden zu
zählen muss man nur bis 244 zählen. Und das passt in ein Byte.
Man könnte auch wesentlich feiner zählen z.B. in 80ms Schritten (=ca. 40
Overflows). Vielleicht fällt dir auf, wo man die 80ms gut gebrauchen
könnte...
> Ok. Also jetzt habe ich die 2,048ms. Sprich: Takt: 1MHz. Teiler =8. Nach> genau 2,048ms läuft der Timer über. Das verstehst du jetzt wohl unter> Aufrufen. Ok und die 488,28 habe ich jetzt auch. Wobei ich die noch ned> ganz verstehe. Den Timertakt verstehe ich das ist der normale Clock> durch den Vorteiler.
Mist hätte ich mal weiterlesen sollen, bevor ich erkläre. Zweites Mal
reingefallen.
> Aber warum das dann geteilt durch 256???
Um von den Timertakten auf die Abstände der Overflow-Interrupte zu
kommen. Nach 256 Timertakten kommt der Oberflow-Interrupt. Bzw. kann man
durch Vorbelegung des Timerzählers weniger als 256 Timertakte erhalten.
> Da Herz ja
^^^^ Hertz!
> 1/s ist heißt das quasi 488 mal ein Interrupt pro Sekunde!!!> OKKKKKKKKKKKKKKK. Jetzt hab ichs geschnallt auch wenn es lange gedauert> hat.
Siehst du!
Guten Morgen!
Ok jetzt habe ich wieder was gelernt mit den Masken. Ich kann ja
Kommentare auch nicht nach dem "\" schreiben sondern nur innerhalb.
Ok das mit der Variablen temp ist mir auch klarer geworden. Ich habe
jetzt für jede LED eine andere Variable temp benutzt also temp1 temp2
temp3 usw. Ist das nötig. Doch eigentlich nicht weil ja immer nur eine
LED aufgerufen wird und dann keine Verwechslungsgefahr besteht oder?
Noch eine Sache zu
tmp=DDRA & MASKE. Also DDRA kann ja theoretisch irgendein Zustand sein.
MASKE da sind definitiv alle Zustände der LED PORTs auf 0. Wenn ich
verunde und eine Null dabei ist habe ich als Ergebnis immer 0. Klar. Ich
schreibe das in tmp. Dann müßte ich doch aber erst sagen DDRA|= tmp;.
Dann ist tmp auf DDRA drauf. In der nächsten Zeile wird ja tmp schon
wieder mit dem Wunschzustand der LEDs beschrieben. Sprich es wird nur
tmp "gelöscht" aber nicht die LEDs an DDRA. Ist das richtig? Also Ziel
war nicht die LEDs erst mal abzuschalten. Das kommt dann erst anfangs in
Main oder?
Jetzt noch mal zu der Sache mit dem Multiplexen. Also darunter verstehst
du das Blinken der roten Lampe? Oder die Sache dass 6 LEDs an 3
Leitungen hängen (dieses Problem ist ja aber über define gelöst und kann
dann ja immer zuordnen und kann sagen LED2_ON bei diesem Wert usw? Oder
verstehst du unter Multiplexen dass die LEDs nicht dauernd an sind
sondern in einer ganz hohen Frequenz leuchten und das Auge des als
Dauerleuchten ansieht. Also auf letzteres zum Stromsparen glaube ich
könnte man verzichten. Und es müssen auch keine 2 LEDs gleichzeitig
leuchten immer nur eine. Also der Übergang so wie mit den 3 LEs. Ganz
einfach also.
Was den Vorteiler betrifft habe ich aber trotzdem auf Vorteiler 8
umgedacht so wie du angedacht hast. Das werde ich machen.
Also die Information wo der Timer gerade steht bekommt die LED und der
Taster durch die ISR. Läuft der Timer dann erst an wenn er das erste mal
gefordert wird? Also sagen wir mal es ist so nass das rot leuchtet (rot
soll ja blinken). Genau dann wenn rot gefordert ist läuft mein Timer los
und erzeugt mir hier ein blinken mit 1 Mal pro Sekunde. Angenommen wenn
jetzt genau in dem Moment die Batterie schwach wird dann sieht die
Routine für die BatterieLED in der ISR nach und sieht ok mein Timer
steht auf sagen wir mal 111 (von 255). Die Batterieled weiss aber sie
braucht x-Aufrufe und die Aufrufe beziehen sich ja darauf dass der Timer
von 0 wegläuft. Also kommt der erste Aufruf bei 111 ja schon nach glaube
ich 144. Sprich er muss nach dem x-ten Umlauf kappieren es fehlt ja noch
was weil der Timer ja bei 111 stand wo es losging. Sprich er müsste nach
meiner Theorie dann nochmal bis 144 zählen dass er genau die x-Aufrufe
erreicht. Analog dazu dann natürlich der Taster Power Down mit der
Entprellung. Wo liegt der Fehler in meinem Denkprozess wenn es denn
einen gibt?
OK. Das mit dem CTC vergesse ich erstmal. War nur ein Geistesblitz weil
ich dachte des braucht man da.
Tut mir leid. Ich lese oft was frage dann und verstehe es nachträglich.
Erst denken dann schreiben! Werde ich mir merken.
Also der ganze Spass mit dem Timmer einstellen. Startwert des Timers,
select interrupt passiert wie ichs gemacht habe in meinem main.
Mal sehen wie ich das jetzt hinbekomme. Das in der ISR ist noch bisschen
ein Problem. Allerdings hilft mir das mit switch case und dass es etwas
gibt was für alle Komponenten ist und dann für die einzelnen.
Bastler schrieb:
> Guten Morgen!
Mahlzeit ;-)
>> Ok jetzt habe ich wieder was gelernt mit den Masken. Ich kann ja> Kommentare auch nicht nach dem "\" schreiben sondern nur innerhalb.> Ok das mit der Variablen temp ist mir auch klarer geworden. Ich habe> jetzt für jede LED eine andere Variable temp benutzt also temp1 temp2> temp3 usw. Ist das nötig. Doch eigentlich nicht weil ja immer nur eine> LED aufgerufen wird und dann keine Verwechslungsgefahr besteht oder?
Die Variable ist innerhalb des do ... while im Makro angelegt und nur
dort belegt sie auch Platz auf dem Stack oder einem Register (jenachdem
was der Compiler frei hat). Wie die heisst, ist piepegal.
> Noch eine Sache zu> tmp=DDRA & MASKE. Also DDRA kann ja theoretisch irgendein Zustand sein.> MASKE da sind definitiv alle Zustände der LED PORTs auf 0. Wenn ich> verunde und eine Null dabei ist habe ich als Ergebnis immer 0. Klar. Ich> schreibe das in tmp. Dann müßte ich doch aber erst sagen DDRA|= tmp;.> Dann ist tmp auf DDRA drauf. In der nächsten Zeile wird ja tmp schon> wieder mit dem Wunschzustand der LEDs beschrieben. Sprich es wird nur> tmp "gelöscht" aber nicht die LEDs an DDRA. Ist das richtig? Also Ziel> war nicht die LEDs erst mal abzuschalten. Das kommt dann erst anfangs in> Main oder?
Das Makro zeilenweise erklärt...
#define MASKE (~((1<<PA3) | (1<<PA7) | (1<<PA5)))
Die MASKE sieht jetzt so aus:
PA:76543210
01010111
#define LED_OFF()
do \
{ \
PORTA &= MASKE; /* alle LEDs aus */ \
} while (0)
Bsp:
PORTA #x#x#xxx
MASKE 01010111
Ergeb. 0x0x0xxx
D.h. Nur die Pins PA3, PA5, PA7 werden gelöscht. In diesem Zustand
leuchtet keine der LEDs die mit Charliemultiplex angeschlossen sind.
//
// LED1_ON
// PA3 Output HIGH
// PA7 Output LOW
// PA5 Input Z
//
#define LED1_ON() \
do \
{ \
uint8_t tmp; \
Das ist die zeitweilige Hilfsvariable. Sie ist nur zwischen dem
umschliessenden {} gültig (s. oben)
/* hier LED_OFF() bzw. am Anfang der ISR */ \
Man kann alle LED hier beim Code für die einzelne LED ausschalten oder
zentral einmal bevor die Codestücke für die einzelnen LEDs aktiv sind.
Letztes spart Code.
tmp = DDRA & MASKE; \
Bsp:
DDRA #x#x#xxx
MASKE 01010111
tmp 0x0x0xxx
DDRA #x#x#xxx
DDRA ist noch nicht geändert!
tmp |= (1<<PA3) | (1<<PA7) | (0<<PA5); \
Hier bauen wir das den neuen Wert für DDRA auf, der später gesetzt wird
DDRA = tmp; \
Da ist das Setzen in einem Rutsch
PORTA |= (1<<PA3); \
Und zum Abschluss Vcc auf einen Pin geben. Die anderen PORTA Pins für
diese LED sind vom Löschen er noch 0 und brauchen hier nicht
berücksichtigt zu werden. Ab jetzt leuchtet die LED.
} while (0)
> Jetzt noch mal zu der Sache mit dem Multiplexen. Also darunter verstehst> du das Blinken der roten Lampe?
Das nicht. Das Blinken wird anders gelöst.
> Oder> verstehst du unter Multiplexen dass die LEDs nicht dauernd an sind> sondern in einer ganz hohen Frequenz leuchten und das Auge des als> Dauerleuchten ansieht.
Letzeres und mehr, nämlich überhaupt in einer gegebenen Zeit alleLEDs
bedienen zu können.
1,2,3,... steht für die jeweilige LED
# steht für Ende/Beginn ISR
Die Zeit läuft von links nach rechts
------------------- Zeit ---------------------->
Man kann die LEDs so leuchten lassen
11111111111#22222222222#33333333333#44444444444#55555555555#66666666666.
..
Oder so
1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6.
..
Angenommen der Zeitstrahl ist eine 1s lang (260ms * 4), dann schaffst du
bei Methode 1 nur ein Leuchten bei LED1 bis LED4. Die LED5 und LED6
kommen nicht an die Reihe bzw. kommen in der folgenden Sekunde dran,
knappsen aber Zeit von zwei anderen LEDs ab. Beobachtet man die LED1,
sieht man in 1s ein 260ms Hell und 3*260ms Dunkel. Also Blinken, obwohl
man vielleicht ein Dauerleuchten wollte! Das Blinken ist systembedingt
beim Multiplexen da!
bei Methode 2, dort wo die ISR häufiger aufgerufen wird (kleinerer
Prescaler), kommen a. alle LEDs an die Reihe und b. die Zeit zwischen
dem Drankommen einer LED ist deutlich kürzer. Bei geeignete schnellem
Wechsel verschmilzt das schnelle Blinken im Auge zu einem Dauerleuchten!
Bei dieser einfachen Darstellung sieht man auch gut noch was anderes!
Der Overhead # für das Anspringen/Beenden der ISR ist mei Methode 2
deutlich grösser. Die nutzbare Rechenzeit (Anzahl Systemtakte) ist
insgesamt geringer. Eine beliebige Steigerung der Frequenz der ISR
Aufrufe ist nicht möglich.
Jetzt zur Arbeitsweise von ISR und Userprogramm:
------------------------- Zeit (1s) --------------------------------->
Das Userprogramm macht beim 0,5sAN / 0,5s AUS Blinken von LED3 alleine:
Wenn 1. Halbsekunde: led_zustand |= (1<<LED3); // AN
Wenn 2. Halbsekunde: led_zustand &= ~(1<<LED3); // AUS
Der Inhalt von Bit LED3 in led_zustand ist also:
11111111111111111111111111110000000000000000000000000000000000000000000
Die ISR macht generell:
1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6.
..
Die Aktion für LED3 wird jetzt nur durchgeführt, wenn der Inhalt von
Inhalt von Bit LED3 in led_zustand 1 ist
1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6#1#2#3#4#5#6.
..
1 1 1 0 0 0
"Leuchtzeit" "Dunkelzeit"
> Also auf letzteres zum Stromsparen glaube ich> könnte man verzichten. Und es müssen auch keine 2 LEDs gleichzeitig> leuchten immer nur eine. Also der Übergang so wie mit den 3 LEs. Ganz> einfach also.
Es ist nicht zum Stromsparen gedacht, abwohl das ein positiver
Nebeneffekt sein kann (den man auch per grösseren Vorwiderstand
erreichen könnte).
> Was den Vorteiler betrifft habe ich aber trotzdem auf Vorteiler 8> umgedacht so wie du angedacht hast. Das werde ich machen.> Also die Information wo der Timer gerade steht bekommt die LED und der> Taster durch die ISR. Läuft der Timer dann erst an wenn er das erste mal> gefordert wird? Also sagen wir mal es ist so nass das rot leuchtet (rot> soll ja blinken). Genau dann wenn rot gefordert ist läuft mein Timer los> und erzeugt mir hier ein blinken mit 1 Mal pro Sekunde.
Kommt darauf an, was du dem Timer an Aufgaben zuteilst und wie dein
Messablauf bzw. die Gerätefunktion aussieht.
Man könnte die Gerätefunktion grob strukturieren:
1. Einschalten
2. Batterie checken
3. Batteriecheck anzeigen
4. Tasteneingabe (EIN/AUS) prüfen
5. Feuchte messen
6. Feuchte anzeigen
7. Option: Laufzeit prüfen
8. ggf. Wecker stellen und Schlafen legen
9. wiederholen bei 4. oder 2.
Wenn der Timer nur die LED Anzeige macht, braucht er nur bei 3 und 6 zu
laufen.
Wenn der Timer zusätzlich die 80ms für die Entprellung abpasst, wird er
zusätzlich bei 4. laufen.
Wenn der Timer optional die Laufzeit überwacht, wird er zusätzlich bei
7. laufen; ja im Prinzip während des gesamten Programms ausser
vielleicht bei den eigentlichen Messungen. man würde dann auch die
"Trigger"-Konstruktion rauswerfen und mit der hochgezählten Zeit des
Timers arbeiten. Beispiel: Batteriecheck immer einmal beim Einschalten
und dann alle 60 Sekunden. Feuchtemessung nach dem Einschalten und dann
alle 2 Sekunden. Länger als 5 Min. starrt keiner auf das Gerät, deshalb
nach 5 Min. automatisch abschalten (Schlafen).
> Angenommen wenn...
Diese Frage vielleicht noch mal stellen, wenn die Gerätefunktion / der
Ablauf festgelegt ist.
> OK. Das mit dem CTC vergesse ich erstmal. War nur ein Geistesblitz weil> ich dachte des braucht man da.
CTC kann man vorteilhaft nutzen, wenn man nicht mit 256 Schritten
zwischen den ISRs leben will. Man könnte zwar ohne CTC den Timerzähler
statt bei 0 z.B. bei 127 loslaufen lassen. Dann hat man 128 Schritte bis
zum nächsten Timer-Overflow. Dafür müsste man in der ISR eine Anweisung
Timerzähler = 127; schreiben. ODER man füllt ein Hardwareregister des
Timers mit dem Wunschwert bei dem der Interrupt kommen soll (der Vektor
heisst dann nur anders) aber ab dann ist keine extra Anweisung in der
ISR notwendig! Das ist der CTC Modus.
Fang einfach an. Schreib zunächst dein obiges Testprogramm für die LEDs
weiter. Das ergänzen mit Taster/Messung/Schlafen kommt dann im zweiten
Schritt.
Guten Morgen!
Also ehrlich gesagt bin ich mir immer noch nicht sicher ob wir beide das
richtige meinen. Ich möchte da nochmal darauf zurückkommen. Also der
Betauungssensor hat ja nur 3 LEDs die an 3 Ports hängen. Bei diesen LEDs
soll nur die rote blinken. Also ganz einfach.
Der kapazitive Sensor hat 6 LEDs weil der ja hoffentlich genauer ist. 2
rote 2 gelbe und 2 grüne LEDs. Die grünen sollen in ihrem Bereich
jeweils Dauerleuchten. Also ganz trocken 1. grüne. Bei vielleicht 20
%rel. Feuchte die 2. grüne LED. Das blinken soll erst bei den gelben
beginnen. SAgen wir mal bei der 4. LED. Die erste gelbe soll Dauerlicht
sein. Die 4. gelbe soll vielleicht mit 1Hz blinken. Die erste rote mit
doppelt so schnell und die letzte rote LED wieder doppelt so schnell.
Das wäre meine theoretische Vorstellung. Darum dachte ich man kann da so
ne allgemeine Blinkroutine entwerfen und kann die dann jeweils bisschen
abgeändert auf diese drei LEDs anwenden.
Du bist ja glaube ich immer noch bei dem Multiplexen. Dass alle LEDs
quasi "blinken" nur dass man es hald nicht bei allen sieht. Ich weiss
hald nicht ob das für mich dann zu kompliziert wird fürn Anfang.
Bei 1111111#2222222# usw. vergeht also mehr Zeit. Unglaublich wie
untalentiert ich dabei bin. Ich kann mir das einfach sehr schwer
vorstellen was da abgeht. Würde es ohne Multiplexen leichter???? Also
sprich LED 1-3 Dauerleuchten und nur LED 4-6 Blinken??? Das mit dem
Strom sollte ja kein Problem sein weil man das Gerät ja nach Benutzung
in den Power Down versetzt. Vielleicht habe ich das auch noch nicht so
gesagt. Das wären ja auch alles gleich lange Abläufe oder??? Kann man
das varieren. Es sollen ja nicht alle LEDs gleichschnell blinken dann.
Ich vermisse hald in allen ISR das Flag wo der Überlauf eingetragen
wird. Habe mir das tutorial angeschaut und noch zwei Bücher. Irgendwie
scheint ja das volatile sowas ähnliches zu machen. Da wird ja irgendwas
hochgezählt oder eingetragen was in diese Richtung geht.
Nochmal zum Ablauf der Lampenfolge
Es geht von LED 1 auf 6 und dann natürlich wieder zurück von 6 auf 1
wenn es trockener wird. ICh denke mal das hast du ja auch gedacht.
Moment das ist nicht zum Stromsparen?????????????????? Wofür dann?? Weil
das sauberes programmieren ist??? Oder weil der Übergang fließender
ist????? Warum macht man das so???
Also das mit der Gerätefunktion ist jetzt wieder klarer. Das ist jetzt
auch allgemeiner.
1. Einschalten
2. Batterie checken
3. Batteriecheck anzeigen
4. Tasteneingabe (EIN/AUS) prüfen
5. Feuchte messen
6. Feuchte anzeigen
7. Option: Laufzeit prüfen
8. ggf. Wecker stellen und Schlafen legen
9. wiederholen bei 4. oder 2.
Ideal wäre es natürlich wenn der Timer alles machen würde. Das Blinken
der LED beim Batteriecheck. Das Blinken der Sensor LEDs und das
Tasterentprellen. DAs gilt für Betauungssensor und kap. Sensor.
Ich bin jetzt erstmal stolz dass ich ein Programm habe das keine Fehler
bringt auch wenn ich nur ein Dauerleuchten von LED5 erziehlt habe!!"g"
Der Code ist im Anhang oben. Habe da auch bissl rumprobiert aber das ist
wieder auskommentiert. Vielleicht kannst du mir ja sagen ob das mit dem
Timer einstellen in main so in Ordnung ist
Gruß
Thomas
Bastler schrieb:
Morschen!
> Also ehrlich gesagt bin ich mir immer noch nicht sicher ob wir beide das> richtige meinen. Ich möchte da nochmal darauf zurückkommen. Also der> Betauungssensor hat ja nur 3 LEDs die an 3 Ports hängen. Bei diesen LEDs> soll nur die rote blinken. Also ganz einfach.> Der kapazitive Sensor hat 6 LEDs weil der ja hoffentlich genauer ist. 2> rote 2 gelbe und 2 grüne LEDs. Die grünen sollen in ihrem Bereich> jeweils Dauerleuchten.> Also ganz trocken 1. grüne.> Bei vielleicht 20 %rel. Feuchte die 2. grüne LED.> Die erste gelbe soll Dauerlicht sein.> Die 4. gelbe soll vielleicht mit 1Hz blinken.> Die erste rote mit doppelt so schnell und> die letzte rote LED wieder doppelt so schnell.> Das wäre meine theoretische Vorstellung. Darum dachte ich man kann da so> ne allgemeine Blinkroutine entwerfen und kann die dann jeweils bisschen> abgeändert auf diese drei LEDs anwenden.
Ich versuche in deinen Fragen rauszulesen, um welche Hardware es jeweils
gehen soll. Vielleicht machst du es mir einfacher und schreibst jeweils
in getrennten Beiträgen nur zu einer Hardware (und dem jeweiligen
Programm). Oder du trennst in einem Beitrag mit fetten Überschriften.
> Du bist ja glaube ich immer noch bei dem Multiplexen. Dass alle LEDs> quasi "blinken" nur dass man es hald nicht bei allen sieht. Ich weiss> hald nicht ob das für mich dann zu kompliziert wird fürn Anfang.> Bei 1111111#2222222# usw. vergeht also mehr Zeit. Unglaublich wie> untalentiert ich dabei bin. Ich kann mir das einfach sehr schwer> vorstellen was da abgeht. Würde es ohne Multiplexen leichter????
Es geht auch ohne das Multiplexen im Timer. IMHO ist es uneleganter,
aber es geht, wenn nie mehr als eine der über Charlieplexing
angeschlossenen LEDs gleichzeitig aktiv sein müssen.
> Also> sprich LED 1-3 Dauerleuchten und nur LED 4-6 Blinken??? Das mit dem> Strom sollte ja kein Problem sein weil man das Gerät ja nach Benutzung> in den Power Down versetzt. Vielleicht habe ich das auch noch nicht so> gesagt. Das wären ja auch alles gleich lange Abläufe oder??? Kann man> das varieren. Es sollen ja nicht alle LEDs gleichschnell blinken dann.> Ich vermisse hald in allen ISR das Flag wo der Überlauf eingetragen> wird.> Habe mir das tutorial angeschaut und noch zwei Bücher. Irgendwie> scheint ja das volatile sowas ähnliches zu machen. Da wird ja irgendwas> hochgezählt oder eingetragen was in diese Richtung geht.
Das "Flag" ist eine von dir angelegte Zählvariable. Die muss global und
volatile sein, wenn in der ISR und im Userprogramm z.B. in main() darauf
zugegriffen wird.
> Nochmal zum Ablauf der Lampenfolge> Es geht von LED 1 auf 6 und dann natürlich wieder zurück von 6 auf 1> wenn es trockener wird. ICh denke mal das hast du ja auch gedacht.
Die Entscheidung welche LED geschaltet wird macht das Userprogramm.
Entweder die feuchtemessung() selbst oder die aufrufende Routine über
den Rückgabewert von feuchtemessung().
> Moment das ist nicht zum Stromsparen?????????????????? Wofür dann?? Weil> das sauberes programmieren ist??? Oder weil der Übergang fließender> ist????? Warum macht man das so???
Weil es "eleganter" ist und um alle Optionen zu haben. Bsp. statt 6
Stufen beim kap. Messgerät, hättest du so 11 Stufen:
LED1
LED1 + LED2
LED2
LED2 + LED3
...
LED5 + LED6
LED6
> Ich bin jetzt erstmal stolz dass ich ein Programm habe das keine Fehler> bringt auch wenn ich nur ein Dauerleuchten von LED5 erziehlt habe!!"g"> Der Code ist im Anhang oben.
Ich simuliere es mal heute abend im AVR Studio...
> Habe da auch bissl rumprobiert aber das ist> wieder auskommentiert. Vielleicht kannst du mir ja sagen ob das mit dem> Timer einstellen in main so in Ordnung ist
Hier ein Tipp: Statt Codeteile wie in
1
/*if(count==1)
2
{
3
...
mit /* */ auszukommentieren, mache das z.B. so
1
#if 0
2
if(count == 1)
3
{
4
...
5
#endif
Das ist übersichtlicher und weniger fehlerträchtig, besonders wenn im
auskommentieren Codeteil selbst noch /* */ Kommentare stehen.
Du kannst auch Makros verwenden und die am Quellcodeanfang je nach zu
testender Funktion schalten:
Hallo!!
So in meiner ersten Mail erstmal wieder ein paar Codes die aber nur
teils funktionieren. Habe es so konfiguriert wie du vorgeschlagen hast.
Testversion 3 läuft zumindest schon mal so weit dass nach ca.3 Sekunden
die LED angeht und nach weiteren 3 Sekunden wieder erlischt. Allerdings
funktioniert das mit while(1) auch nicht dauern. Ich kann mir nur
vorstellen dass Zeit oder takt nicht zurückgesetzt wird und der Zähler
immer weiter hochläuft. Aber rein von der Sache ist das ja schon mal
ganz ok.
Ich werde in der nächsten Email auch gleich den Stromlaufplan schicken.
Eigentlich unterscheiden sich meine beiden Hardwares ja nur durch die
LEDs bzw die spätere Schaltung für den kap. Feuchtesensor. Ich bin
derzeit nur noch an der Platine am spielen die auch die 6 LEds enthält.
Für den Betauungssensor den ich jetzt auch nochmal hier aufgebaut habe
werde ich hald nur 3 LEDs ansteuern. Ist ja nur ein Prototyp.
Bei meinem Talent werde ich wohl auf die Sache mit dem Multiplexen erst
mal verzichten. Es muss ja wirklich nur immer eine LED leuchten und da
ist mir der Übergang auch nicht so wichtig. Schließlich kann ich hier
einiges vereinfachen wenn ich das erstmal ausspare. Und auch so ist der
Zweck für mich erst einmal erfüllt.
Die Initialisierung des Timers habe ich jetzt in einem eigenem
unterprogramm erledigt weil ich mir dachte das ist eleganter.
Testversion 3 benützt außerdem anstatt des 8er Teilers den 64er Teiler.
Wäre froh wenn du des mal testen könntest und mir sagen könntest warum
da nur einmal ein blinken stattfindet. Heißt ja wohl dass meine
Überläufe schon mal funktionieren.
Ebenso stellt sich noch die Frage wie ich LED1_ON() verneine. Mit
~LED1_ON() geht es nicht. Was geht ist LED_OFF(). Aber das sieht wieder
komplizierter aus dann...
Das mit #if und #endif ist eingearbeitet und funktioniert bei mir auch.
Das ist eine wunderbare Funktion weil ich jetzt schön umschalten kann
ohne doofe Kommentare zu machen!
Gruß
Thomas
Eine Berichtigung. Der Stromlaufplan ist noch nicht fertig umgeändert.
Die LEDs über R1 hängen jetzt nicht mehr an PB0 sondern an PA3. Das was
an PA3 angeschlossen war (vom kap. Sensor) hängt dafür an PB0. Die
Widerstände von den LEDs habe ich jetzt halb so groß dimensioniert wie
davor mit den 680Ohm Widerständen da ja hin und rückweg da ist. Damit
komme ich ja auch wieder auf 680 Ohm.
Der kap. Sensor ist nur für später auch schon auf diesem Board. Ich habe
aber noch keine Absichten den hier irgendwie anzusprechen. Stattdessen
hängt noch mit Jumper der Betauungssensor dran damit ich beides mit
dieser Platine testen kann. Das ist allerdings fürs Lampen blinken
erstmal unerheblich. Mein Ziel ist ja die LEDs4, 5, 6 und 7 zum blinken
zu bringen und den Taster S1 zu entprellen. Dann werde ich versuchen das
in das Programm vom Betauungssensor einzuarbeiten.
Wenn das dann funktioniert möchte ich mich an die Herausforderung mit
dem kap. Sensor und evt dem multiplexen machen.
Gruß
Th.
Bastler schrieb:
> So in meiner ersten Mail erstmal wieder ein paar Codes die aber nur> teils funktionieren. Habe es so konfiguriert wie du vorgeschlagen hast.> Testversion 3 läuft zumindest schon mal so weit dass nach ca.3 Sekunden> die LED angeht und nach weiteren 3 Sekunden wieder erlischt.
Ausschnitt aus Testversion3:
1
/****************/
2
#if Testversion3
3
/****************/
4
5
#define F_CPU 1000000
6
7
// Aufrufe pro Sekunde bei 64er-Teiler für Testversion3
8
//
9
// 1. Makros schreibe ich gerne GROSS, dann kann man sie im Code
10
// schnell von Variablen und Funktionen unterscheiden.
11
// 2. Klammern kann man bei Makros nie zu viel haben.
volatileuint8_ttakt;// Initalisierung auf 0 macht GCC
16
volatileuint8_tsekunde;// Lesbarere Schreibweise
17
18
ISR(TIM0_OVF_vect)
19
{
20
takt--;
21
if(takt==0)
22
{
23
takt=ANZAHL_OVERFLOWS_PRO_SEKUNDE;
24
sekunde++;
25
/*
26
Abfrage und Schalterei wurde ins Userprogramm verlagert
27
Die ISR läuft "unabhängig" vom Userprogramm und weiss
28
nicht, welche LED vom Programmablauf her blinken soll.
29
30
Man kann eine Zusatzvariable zwischen ISR und Userprogramm
31
vereinbaren, die der ISR diesen Sachverhalt mitteilt. Dann
32
kann man den Blinkcode hier rein ziehen. Vorher nicht.
33
*/
34
}
35
}
36
37
voidinit(void)
38
{
39
// Timer einstellen
40
// WGM01 und WGM00 auf für Normalbetrieb
41
// Vorteiler 64; 1 Overflow - 16,384ms
42
// 1s = 61,03515625 Aufrufe oder Überläufe
43
// 40ms = 2,44140625 Aufrufe
44
TCCR0B|=(1<<CS01)|(1<<CS00);
45
TIMSK0|=(1<<TOIE0);// Timeroverflow Interrupt ein
46
TCNT0=0;// Startwert des Timers bei 0
47
takt=ANZAHL_OVERFLOWS_PRO_SEKUNDE;
48
sekunde=0;
49
}
50
51
intmain(void)
52
{
53
LED_OFF();
54
init();
55
sei();
56
57
while(1)// for(;;) {} geht scheinbar auch??? Ja!
58
{
59
/*
60
Sekunde: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...
61
Sekunde & 6: 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 ...
62
Schaltaktion: Aus An Aus An Aus ...
63
*/
64
switch((sekunde&6))// & ist der MODULO-Operator
65
{
66
case3:
67
LED5_ON();
68
break;
69
case0:
70
LED_OFF();
71
break;
72
}
73
}
74
}
75
#endif /* Testversion3 */
> Bei meinem Talent werde ich wohl auf die Sache mit dem Multiplexen erst> mal verzichten.
Du lernst das auch. Das haben schon andere geschafft ;-) Das Gute ist:
Die spätere Änderung ist nur eine Firmwareänderung. Auf dem gleichen
Prototypen kannst du auch die elegantere Firmware laufen lassen.
> Die Initialisierung des Timers habe ich jetzt in einem eigenem> unterprogramm erledigt weil ich mir dachte das ist eleganter.
Ist es!
> Testversion 3 benützt außerdem anstatt des 8er Teilers den 64er Teiler.> Wäre froh wenn du des mal testen könntest und mir sagen könntest warum> da nur einmal ein blinken stattfindet. Heißt ja wohl dass meine> Überläufe schon mal funktionieren.
Siehe oben. Wenn bei deiner Version sekunde > 3 ist wird nie mehr
eingeschaltet und wenn sekunde > 6 ist wird nie mehr ausgeschaltet. Bzw.
doch, wenn uint8_t sekunde überläuft, d.h. in ca. 4 Min. 19s Abstart
geht die LED5 wieder an...
> Ebenso stellt sich noch die Frage wie ich LED1_ON() verneine. Mit> ~LED1_ON() geht es nicht. Was geht ist LED_OFF(). Aber das sieht wieder> komplizierter aus dann...
LED_OFF() schaltet alle LEDs aus, in dem alle Portpins für die LEDs auf
LOW gesetzt werden. Vcc wird dadurch ausgeschaltet. Man bräuchte nur den
einem Portpin auf LOW zu schalten, der im Moment Vcc für die eine LED
liefert. Dafür bräuchte man aber 6 Makros LED1_OFF(),... , LED6_OFF().
Um das zu vermeiden, die Holzhammermethode und alle drei Portpins LOW.
> switch((sekunde & 6)) // & ist der MODULO-Operator
Stimmt nicht ;-)
% ist der MODULO-Operator. Ich brauch' dringend einen Kaffee! Die
korrekte Zeile lautet:
switch((sekunde % 6)) // % ist der MODULO-Operator
Hallo!
Erst nochmal herzlichen Dank. Ich habe jetzt mein erstes Timerblinken
erzielt! Eine tolle Sache. Also ich kann das Lämpchen minimal mit 1Hz
blinken lassen. Also 1 s an und wieder 1 s aus. Für ein halbes Herz
brauche ich dann das define mit Overflows pro 500ms oder sogar pro
250ms. Kann ich wenn ich alles gleichzeitig will das dann auch in einer
ISR Routine abhandeln vermute ich mal.
Dann stellt sich für mich nur noch die Frage wie ich es dann schaffe die
jeweiligen Blinkrythmen in meinem main anzuwählen. Oder soll ich dann
für jedes Lämpchen ein eigenes Unterprogramm machen? Wäre ja auch für
später sinnvoll wenn ich den AD-Wandler auswerte. Habe ja jeweils gesagt
in dem Bereich rote LED. In dem Bereich gelbe LED und in dem Bereich
grüne LED. Dann würde ich da nur noch die Unterfunktionen aufrufen oder?
Jetzt kann ich mich zum ersten Mal wieder kurz fassen! :-)
Gruß
Thomas
Sehr schön, dass das jetzt klappt!
Du kannst neben sekunde ja auch halbesekunde oder viertelsekunde
zählen. Schau dir den MODULO Operator an. Grob gilt (ungenau wg.
Ganzzahlrechnung):
(takt % ANZAHL_OVERFLOWS_PRO_SEKUNDE == 0) => sekunde++, takt
zurücksetzen
(takt % (ANZAHL_OVERFLOWS_PRO_SEKUNDE/2) == 0) => halbesekunde++
(takt % (ANZAHL_OVERFLOWS_PRO_SEKUNDE/4) == 0) => viertelsekunde++
usw.
"Ein Unterprogramm für jede LED", das würde ich auch erst mal so machen.
Hier noch eine kleine Änderung, um unnötige Aufrufe für das An- und
Ausschalten zu vermeiden:
1
staticuint8_tletzte_sekunde=~0;// damit if bei sekunde==0 wahr ist
Jetzt versuche ich gerade mehrere verschiedene Blinktakte zu
programmieren. Allerdings habe ich da wieder ein Problem. Mit einmal
Variable takt werde ich das ja wohl nicht schaffen. Ich werde ja wohl
für alle 3 LEDs eine Variable benötigen. Die Bedinung (also if) wann die
LEDs blinken sollen steht wohl wieder in der ISR. Dann ist nur noch die
Frage wie ich das dann in main für die einzelnen LED anwählen kann. Wohl
auch wieder mit einer neuen switch case Abfrage.
Für die Batterie LED kann ich wohl wieder das mit den Überläufen pro 1
Sekunde verwenden vermute ich mal. Muss hald dann 4 mal passieren.
Grundsätzlich kann ich jedes Lampenblinken anwählen. Also auch das mit
0,5 Hz und 0,25 Hz wenn ich das jeweilige define für Takt eintrage.
Gruß
Thomas
Bei mehreren Blinkraten macht es Sinn wieder vom Switch/Case wegzugehen.
Man müsste sich sonst einen "Zeitstrahl basteln" und überlegen, wie man
die einzelnen Aktionen darauf anordnet.
Mit deinen Hz Angaben komme ich nicht zurecht. 0,5 Hz blinkt langsamer
als 1 Hz. Dann passen die ...500MS und ...250MS Makros nicht. Ich
vermute du willst einfach hektischeres und doppelt hektischeres Blinken
also 2 Hz und 4 Hz, oder?
Das Basteln des Zeitstrahls, kann man in die Timer-ISR verlagern. Auf
die Schnelle hingeschrieben aber nicht getestet:
Ups. Jetzt war ich zu schnell! ;-) Bin im Moment dabei das zu verstehen
was ich da genau programmiert habe. Ich glaube ich habe ja eine
Ungenauigkeit drin weil ich ja keine Kommazahlen habe. Sprich bei
61,.... irgendwas Überläufe wird meine Maschine 61 benutzen vermute ich.
Aber jetzt noch mal zur Funktion meines Programmes. Ich beginne mal mit
der ISR. Der takt der in init belegt wurde wird zunächst in der ISR um
eins verringert. Also bei 1 Sekunde 61 Überläufe da das nach dem Komma
wegfällt. Wenn es dann von 61 bis auf null runtergezählt hat wird die
if-Schleife in der ISR aufgerufen. warum man hier aber nochmal takt =
ANZAHL_.... schreibt ist mir nicht klar. Und dann wird das gleiche für
die nächste Sekunde gemacht weil man die Sekunden in init ja wieder
zurücksetzt. Ist meine Annahme richtig?
Bei dem neuen Programmteil habe ich aber ein Problem. Also zunächst mal
wieder eine neue variable (letzte Sekunde) die alles (von 1 - 255) sein
darf aber nicht 0. Wenn letzte_sekunde dann ungleich Sekunde ist wird
die if-Abfrage ausgeführt. Jetzt ist für mich die Frage wann ist das
ungleich? Eigentlich ja immer oder? Dann sagst du letzte Sekunde =
Sekunde???? Dann das mit dem Modulo. Also switch. letzte_Sekunde geteil
durch 2. Wenn Rest null alle LEDs aus und wenn Rest 1 LED6 an.
Ist das jetzt so einigermaßen richtig gedacht?
Gruß
Thomas
Bastler schrieb:
> Ich glaube ich habe ja eine> Ungenauigkeit drin weil ich ja keine Kommazahlen habe.> Sprich bei> 61,.... irgendwas Überläufe wird meine Maschine 61 benutzen vermute ich.
Genau. Deine sekunde auf deinem AVR-Gerät ist dadurch etwas kürzer als
eine Sekunde auf deiner Uhr.
> Aber jetzt noch mal zur Funktion meines Programmes. Ich beginne mal mit> der ISR. Der takt der in init belegt wurde wird zunächst in der ISR um> eins verringert. Also bei 1 Sekunde 61 Überläufe da das nach dem Komma> wegfällt.> Wenn es dann von 61 bis auf null runtergezählt hat wird die> if-Schleife in der ISR aufgerufen. warum man hier aber nochmal takt => ANZAHL_.... schreibt ist mir nicht klar.
Um takt auf den Startwert zu stellen, damit du eine Periode von
ANZAHL_OVERFLOWS_PRO_SEKUNDE Takten bekommst. Würdest du das nicht
machen, würde takt im nächsten Umlauf von 0 bei takt-- auf 255
springen (8-Bit Unterlauf) und die nächste Sekunde wäre gut viermal so
lang!
> Und dann wird das gleiche für> die nächste Sekunde gemacht weil man die Sekunden in init ja wieder> zurücksetzt. Ist meine Annahme richtig?
Nein. init() läuft nur einmal am Programmanfang, vor der Endlosschleife.
Das Initialisieren von sekunde auf 0 ist dort überflüssig, weil es für
globale Variable im C-Startupcode (vor main) bereits gemacht wurde.
> Bei dem neuen Programmteil habe ich aber ein Problem. Also zunächst mal> wieder eine neue variable (letzte Sekunde) die alles (von 1 - 255) sein> darf aber nicht 0. Wenn letzte_sekunde dann ungleich Sekunde ist wird> die if-Abfrage ausgeführt. Jetzt ist für mich die Frage wann ist das> ungleich? Eigentlich ja immer oder? Dann sagst du letzte Sekunde => Sekunde????
Exakt nicht. Das ist der Clou an volatile Variablen und der ISR. Die
parallel laufende ISR erhöht ja sekunde regelmäßig. Und im
Userprogramm wird durch die Kennzeichnung volatile immer der frische
Wert genommen und in den Vergleich einbezogen!
> Dann das mit dem Modulo. Also switch. letzte_Sekunde geteil> durch 2. Wenn Rest null alle LEDs aus und wenn Rest 1 LED6 an.> Ist das jetzt so einigermaßen richtig gedacht?
Jo. Statt MODULO 2 kann man auch das letzte Bit abfragen mit dem BIT-UND
Operator &. Das ist in der frischen Source so.
Hallo!
Zunächst Danke für die Erklärung und das Blinkprogramm. Ich habe jetzt
auch wieder einen Code angehängt. Kurz zur Erklärung:
Testversion 1 ist das Programm welches die rote LED mit 1Hz blinken
läßt. Natürlich meinte ich bei schnellerem Blinken auch nicht mit 0,5 Hz
sondern mit 2 und 4 Hz. Also quasi 2 bzw. 4 mal pro Sekunde.
Testversion 2 ist dein Programm. Es waren ein paar Fehler drin die ich
inzwischen aber soweit herausbekommen haben. Also 0 Warnings. Allerdings
leuchtet da irgendwie alles durcheinander. Zuerst mal LED4 und 5
miteinander. Dann LED1 und6. Und dann wieder 4 und 5 ganz schnell. Weiss
nicht ob meine ganzen defines inzwischen stören.
Testversion 3 ist wieder mein eigentlicher Betauungssensor. Ich habe das
Programm umgeschrieben damit ich es mit dem Prototypen mit den 6 LEDs
benutzen kann. Allerdings werde ich auch hier nur 3 LEDs nutzen nämlich
LED2, 4 und 6. Da habe ich die Ansteuerung korrigiert. LEDBat kann man
lassen. Was interessant ist: Power-Down funktioniert. grüne LED leuchtet
auch ganz normal am Anfang. Batterie LED funkitoniert aber nicht. Und
wenn ich den Sensor anhauche dann leuchten plötzlich das grüne und das
rote LED gleichzeitig!!! Also irgendwie scheint da ein Timer
mitreinzuspielen. Evt von einem anderen define oder so?? Normal soll ja
grün, gelb und rot sein. Keine Ahnung. Meine Vermutung ist hald dass
sich da was stört. Aja nach dem Rot und grün gleichzeitig geleuchtet
haben verlöschen die beiden und es passiert nichts mehr. Erst wieder
nach einem Reset!
Evt. wäre eine Programmtrennung doch wieder sinnvoll? Hier hätte ich
hald alles drin gehabt. Zum probieren und für den Betauungssensor.
Kannst du dir eigentlich vorstellen dass man den Betauungssensor auch
eichen muss? Wohl ja befürchte ich oder??
Gruß
Thomas
Mittlerweile drei Programme für zwei unterschiedliche Hardwares in
einen Quellcode zu stecken, das ist etwas zu viel. Willst du die alle
behalten und pflegen?
Testversion1 würde ich rausschmeissen. Die interessiert nicht mehr.
Testversion2 ist das Demoprogramm für die Ansteuerung der LEDs im
Charlieplexing ohne irgendeine andere Funktion. Diese Version setzt auf
den Timer0, um das abgestufte Blinken zu ermöglichen.
Das Blinken über Testversion3 zu machen, d.h. ohne den Timer, das wird
schwer, weil die Laufzeit von Codestücken die Blinkzeiten beeinflusst.
Das geht in einfachen Demos, um die grundsätzliche Funktion zu zeigen,
aber ich halte den Weg für eine Sackgasse im Endgerät.
Die wilde Blinkerei der LEDs im Demoprogramm ist vielleicht zu viel
gewesen. Es kann auch sein, dass ich mir ein falsches Demo ausgedacht
habe; ich kann es derzeit auch nicht testen, weil ich erst löten müsste.
Du kannst in main() Zeilen auskommentieren und sehen, was dann passiert.
Testversion2 kann man rel. einfach um die eigentlichen Funktionen
erweitern.
Welche Varianten sind denn jetzt im Rennen?
Variante1 Betauungssensor auf dem Einfachboard> Also der> Betauungssensor hat ja nur 3 LEDs die an 3 Ports hängen. Bei diesen LEDs> soll nur die rote blinken. Also ganz einfach.
Diese Hardware wird im Moment nicht mehr eingesetzt. Die Teile fliegen
aus dem Sourcecode raus.
Variante2 Betauungssensor auf dem Board mit dem kapazitive Sensor> Testversion 3 ist wieder mein eigentlicher Betauungssensor. Ich habe das> Programm umgeschrieben damit ich es mit dem Prototypen mit den 6 LEDs> benutzen kann. Allerdings werde ich auch hier nur 3 LEDs nutzen nämlich> LED2, 4 und 6.
Charlieplex LED1 = GRUN = Ohne Funktion (aus)
Charlieplex LED2 = GRUN = Dauerleuchten
Charlieplex LED3 = GELB = Ohne Funktion (aus)
Charlieplex LED4 = GELB = Dauerleuchten
Charlieplex LED5 = ROT = Ohne Funktion (aus)
Charlieplex LED6 = ROT = Dauerleuchten
Solo LED7 = LED_BAT = ROT = Blinken (1 Hz?, Wie lange?)
Variante3 kapazitiver Sensor> Der kapazitive Sensor hat 6 LEDs weil der ja hoffentlich genauer ist. 2> rote 2 gelbe und 2 grüne LEDs. Die grünen sollen in ihrem Bereich> jeweils Dauerleuchten.> Also ganz trocken 1. grüne.> Bei vielleicht 20 %rel. Feuchte die 2. grüne LED.> Die erste gelbe soll Dauerlicht sein.> Die 4. gelbe soll vielleicht mit 1Hz blinken.> Die erste rote mit doppelt so schnell und> die letzte rote LED wieder doppelt so schnell.
Charlieplex LED1 = GRUN = Dauerleuchten
Charlieplex LED2 = GRUN = Dauerleuchten
Charlieplex LED3 = GELB = Dauerleuchten
Charlieplex LED4 = GELB = Blinken 1 Hz (bis nächste Messung?)
Charlieplex LED5 = ROT = Blinken 2 Hz (bis nächste Messung?)
Charlieplex LED6 = ROT = Blinken 4 Hz (bis nächste Messung?)
Solo LED7 = LED_BAT = ROT = Blinken (1 Hz?, Wie lange?)
Man sieht, dass hier und in der Variante1 vorher noch die Funktion für
das Dauerleuchten zu schreiben ist.
Da sich der Einsatz von LED4, LED5 und LED6 bei den beiden Varianten
unterscheiden, sieht der Inhalt der ISR bei beiden Varianten
unterschiedlich aus. Im Moment ist er für Variante3 (nur Blinken)
geschrieben. Wenn du jetzt zu Variante2 wechseln willst, kann man das
machen.
1
#define VARIANTE2 1
2
#define VARIANTE3 0
3
4
#if VARIANTE3
5
volatileuint8_ttakt_LED1;
6
volatileuint8_ttakt_LED3;
7
volatileuint8_ttakt_LED5;
8
#endif /* VARIANTE3 KAP.SENSOR */
9
10
volatileuint8_ttakt_LED2;
11
volatileuint8_ttakt_LED4;
12
volatileuint8_ttakt_LED6;
13
volatileuint8_ttakt_LED7;
14
15
ISR(TIM0_OVF_vect)
16
{
17
takt--;
18
19
// Die LEDs haben eine Vorrangreihenfolge
20
// LED1 vor LED2 vor LED3 vor LED4 vor LED5 vor LED6!
21
22
#if VARIANTE2
23
if((takt%ANZAHL_OVERFLOWS_PRO_SEKUNDE)==0)
24
{
25
// Sonderfall LED7 (Batterie)
26
// Hängt nicht am Charlieplexing, d.h. LED7 kann parallel
27
// zu anderen LED Blinken. Braucht aber eigene AN/AUS Makros!
28
if(takt_LED7)
29
{
30
PORTB&=~LED7_ON;
31
if(!(takt_LED7&1))
32
PORTB|=LED7_ON;// ### ACHTUNG: nicht &= ###
33
takt_LED7--;
34
}
35
36
sekunde++;
37
takt=ANZAHL_OVERFLOWS_PRO_SEKUNDE;// nur hier!
38
}/* 1 Hz Aktionen */
39
40
// Dauerleuchter
41
if(takt_LED6)
42
{
43
LED_OFF();
44
LED6_ON();
45
}
46
47
// LED5 keine Funktion
48
49
// Dauerleuchter
50
if(takt_LED4)
51
{
52
LED_OFF();
53
LED4_ON();
54
}
55
56
// LED3 keine Funktion
57
58
// Dauerleuchter
59
if(takt_LED2)
60
{
61
LED_OFF();
62
LED2_ON();
63
}
64
65
// LED1 keine Funktion
66
#endif /* VARIANTE2 Betauungssensor */
67
68
#if VARIANTE3
69
/*
70
* Blinken von LED4, LED5 und LED6
71
*/
72
if((takt%ANZAHL_OVERFLOWS_PRO_250MS)==0)
73
{
74
if(takt_LED6)
75
{
76
LED_OFF();
77
if((takt_LED6&1)==0)
78
LED6_ON();
79
takt_LED6--;
80
}
81
}/* 4 Hz Aktionen */
82
83
if((takt%ANZAHL_OVERFLOWS_PRO_500MS)==0)
84
{
85
if(takt_LED5)
86
{
87
LED_OFF();
88
if((takt_LED5&1)==0)
89
LED5_ON();
90
takt_LED5--;
91
}
92
}/* 2 Hz Aktionen */
93
94
if((takt%ANZAHL_OVERFLOWS_PRO_SEKUNDE)==0)
95
{
96
/*
97
* Blinken von LED4, LED5 und LED6
98
*/
99
if(takt_LED4)
100
{
101
LED_OFF();
102
if((takt_LED4&1)==0)
103
LED4_ON();
104
takt_LED4--;
105
}
106
107
// Sonderfall LED7 (Batterie)
108
// Hängt nicht am Charlieplexing, d.h. LED7 kann parallel
109
// zu anderen LED Blinken. Braucht aber eigene AN/AUS Makros!
110
if(takt_LED7)
111
{
112
PORTB&=~LED7_ON;
113
if(!(takt_LED7&1))
114
PORTB|=LED7_ON;// ### ACHTUNG: nicht &= ###
115
takt_LED7--;
116
}
117
118
sekunde++;
119
takt=ANZAHL_OVERFLOWS_PRO_SEKUNDE;// nur hier!
120
}/* 1 Hz Aktionen */
121
122
// Dauerleuchter
123
if(takt_LED3)
124
{
125
LED_OFF();
126
LED3_ON();
127
}
128
129
// Dauerleuchter
130
if(takt_LED2)
131
{
132
LED_OFF();
133
LED2_ON();
134
}
135
136
// Dauerleuchter
137
if(takt_LED1)
138
{
139
LED_OFF();
140
LED1_ON();
141
}
142
#endif /* VARIANTE3 KAP.SENSOR */
143
}
Und noch die Verwendung im Programm:
1
#define DAUERFEUER_EIN 1
2
#define DAUERFEUER_AUS 0
3
#define BLINKEN_4S_1HZ (4*1*2)
4
#define BLINKEN_AUS 0
5
6
// Dauerleuchter anschalten (dauert max. 16ms bis zu nächsten ISR)
7
takt_LED2=DAUERFEUER_EIN;
8
9
// Dauerleuchter ausschalten (dauert max. 16ms bis zu nächsten ISR)
10
takt_LED2=DAUERFEUER_AUS;
11
12
// Blinker einschalten (dauert max. 16ms bis zu nächsten ISR)
13
takt_LED7=BLINKEN_4S_1HZ;
14
15
// Blinker ausschalten (dauert max. 16ms bis zu nächsten ISR)
16
takt_LED7=BLINKEN_AUS;
Wenn die weiteren Funktionen in Testversion2 eingebaut werden, muss man
beim Schlafen gehen etwas aufpassen: Die LEDs sind über takt_LEDx und
LED_OFF() auszuschalten. Dann wird der Timer0 disabled. Nach dem
Aufwachen wird der Timer0 wieder enabled. Die LEDs braucht man nach dem
Aufwachen nicht den Vorschlafzustand zu setzen; lieber macht man frische
Messungen (trigger passend auf 0-1 setzen)!
Testversion3 hat die eigentlichen Funktionen und hast bereits versucht
das Charlieplexing hier einzubauen.
Die Ursache für die komische Reaktion der LEDs muss ich mir genauer
ansehen; mit dem hier nicht vorhandenen Timer können die nichts zu tun
haben.
Mir fällt auf, dass du kein einziges LED_OFF() in feuchtemessung() hast!
Die Makros leben davon, dass zuvor ein LED_OFF() gemacht wird. Das
LED_OFF() setzt die Pins, die auf LOW gehen sollen; die LEDx_ON() Makros
schalten ja nur die Vcc dazu! Wenn das anders laufen soll, kann man
die LED_OFF() Funktionalität in die LEDx_ON() Makros reinziehen:
1
#define LED1_ON() \
2
do \
3
{ \
4
uint8_t tmp; /* unsigned integer 8bit 0-255 */ \
5
PORTA &= MASKE; /* alle LEDs aus */ \
6
tmp = DDRA & MASKE; /* holt Zustand von DDRA und setzt ihn auf 0 */ \
7
tmp |= (1<<PA3)|(1<<PA7)|(0<<PA5); /* Wunschzustand LED */ \
Hallo!
Nene diese Software ist für den neuen Prototypen. Ich kann jedes dieser
drei Programme mit der gleichen Hardware betreiben. Dieser Prototyp
gehört ja für die spätere Kapazitätsmessung. Wie ich aber schon sagte
habe ich jetzt auch noch meinen Betauungssensor mit Jumer drangehängt.
Das heißt ich kann beide Sensoren mit einem Board auswerten. Diese
Leiterplatte ist nicht das Endprodukt. Das Endprodukt wird nicht auf FR4
Material entstehen und wird auch nicht gelötet. Also das auf FR4 ist
rein zum testen ob das Programm und die Hardware funktioniert. Es ist
schon richtig es gibt auch noch die alte Hardware. Da war nur der
Betauungssensor. Das war mit den 3 LEDs. Ich hätte auch einen Schaltplan
von dem neuen Prototypen mit den Jumpern falls es nötig sein sollte.
Klar. Testversion 1 war einfach für mich mal zu sehen wie funktioniert
der Timer. Habe damit noch nie was gemacht.
Mein Ziel ist ja jetzt in Testversion drei dieses Blinken auch mit Timer
zu machen. Habe es nur einfach mal hier rein gezogen damit man sich
stückchenweise ranarbeiten kann an des gewünschte Ziel. Also ich
beabsichtige nicht das Blinken ohne Timer zu machen. Das einzige was ich
mir vorstellen könnte dass man die Tastenentprellung mit dem delay
beibehält. Aber das blinken der roten LED und der BAT LED soll mit Timer
gemacht werden (also rote LED beim Betauungssensor wo nur 3 LEDs
verwendet werden!!)
Achso das heißt es kann zu störungen kommen? Dachte mit dem #if kann man
das quasi rauslöschen oder es ist so als würde es gar nicht dortstehen?
Nochmals zu den Varianten die existieren:
Variante 1:
Betauungssensor auf dem alten Prototypen. 3 LEDs. Jedes an einem eigenen
Port. PowerDown. Keine Timer. Nur delay die sich zu stören scheinen.
Variante 2:
Neues Board. Kleiner leichter. Gebaut um das mit dem kap. Sensor zu
überprüfen. 6 LEDs an drei Ports. Jetzt erweitert mit Jumper damit ich
auch den res. Sensor damit testen kann. Allerdings muss ich dann die
Software die für Prototyp 1 geschrieben wurde umschreiben weil sonst
keine Lampe leuchtet. Klar weil ich das mit den LEDs jetzt anders habe.
Nicht mehr jede LED an eigenem Portpin. Warum ich das gemacht habe dass
ich das so nochmal aufbau. Weiss auch nicht. Ich hab es einfach nochmal
sauberer verdrahtet dass das Board ansehnlich ist. Sprich vom
Betauungssensor muss es zwei verschiedene Programme geben. Eines für das
alte Board und eines für den neuen Prototypen. Wobei für meine
revolutionäre Technologie werde ich Software und Schaltung des alten
Boards verwenden. Natürlich erweitert um das mit dem Timerblinken. In
der besonderen Technologie werden also nur 3 LEDs realisiert weil es eh
sehr ungenau ist. Das mit dem kap. Sensor ist nur noch die Zugabe. Wenn
es klappt wunderbar. Testversion 3 ist der Code von dem alten Board. Ich
habe aber schon versucht die Teile zu entfernen wo ich meine dass ich
sie auf dem neuen Board nicht mehr benötige.
JAAAAAAAAAAAAAAAA. Ganz genau. Fast richtig. Bei Variante 2.
Charlieplex. ist das eigentlich der offizielle Name?? Oder kann man auch
sagen gemultiplext?? Wobei das passt ja auch nicht...
LED1, 3 und 5 auf neuem Board für Betauungssensor unerheblich
LED2 und 4 (grün und gelb) mit Dauerleuchten
LED 6 rot mit blinken. Wobei man auch für das gelbe LED ein blinken
verwenden könnte. Dann ist es noch ähnlicher zum kap. Sensor. Also sagen
wir um es zu vereinfachen. LED4 blinkt wie bei kap. Sensor mit 1 Hz und
LED6 blinkt doppelt so schnell. Also für den Betauungssensor. Hoffe ich
habe das jetzt verständlich geschrieben was der Plan ist.
LED_BAT oder LED7 je nachdem soll alle 4Sekunden kurz aufflashen. Also
ich kann da jetzt praktisch keine Frequenz sagen.
4 Sekunden gar nichts und sagen wir mal 0,5 Sekunden aktiv und immer
weiter so. Batterieled immer gleich. Ist bei beiden Boards am gleichen
Pin. Also hier dürfte sich absolut nichts verändern.
STOP!!!
Also ich glaube des wird jetzt wirklich zu kompliziert dann. Da ich ja
einerseits auch die Schaltung des alten Prototyps verwende macht es ja
keinen Sinn das für den neuen zu programmieren beim Betaungssensor. Im
Anhang nochmal der Schaltplan und der Code für das alte Board. Also
Betauungssensor. Und die allererste Variante. Ziel: Timer 0 zum blinken
von LED2 und LED3 sowie LED_BAT und evt Tasterentprellung. Außerdem wie
in Stromlaufplan 4: Spannungsteiler an PA7 um Strom zu sparen. Das müßte
ja relativ leicht sein hoffe ich.
Ich schreibe mir gerade etwas zusammen. Also vergessen wir erstmal das
mit dem Prototypen 2. Da werde ich rangehen sobald der Prototyp 1 seine
wirklich endgültige Funktion hat. Werde mir aber da paar Codestücke
rausnehmen. Werde das dann wieder hier reinstellen wenn ich schneller
bin als du!
Gruß
Thomas
So. Ich habe jetzt schon mal versucht ein Stück vorzuarbeiten. Habe
allerdings immer noch ein Problem wie das dann bei dem LED_BAT und dem
Tasterentprellen geht. Keine Ahnung irgendwie. Das Timerinit dürfte ja
eh passen. Und die ISR habe ich auch schon mal geschrieben so weit wie
möglich. Spannungsteiler an Portpin das habe ich noch nicht gemacht.
Das ganze bisherige Zeug mit dem Blinken kann man ja alles vergessen.
DAs ahbe ich erst mal auskommentiert. Ich habe auch noch eine Frage
wegen der Abfrage in der ISR.
z.B.
if((takt % ANZAHL_OVERFLOWS_PRO_500MS) == 0)
takt sind meine 61 Überläufe pro Sekunde die ich ihm in Timerinit
gegeben habe. ANZAHL_OVERFLOWS_PRO_500MS ist wohl 30 (genau:
30,51757813). Der Modulo Operator sagt mir ja den Rest. Also sprich die
If Schleife wird ausgeführt wenn Rest 0 ist. Der Takt wird von 61
runtergezählt. Ups. Stimmt das ist dann einmal. 61 dürfte ne Primzahl
sein. ABER: Ich kann mit dene 61 Überläufe aus dem Timerinit ja jetzt
nicht die für ne halbe Sekunde oder 80ms Sekunden steuern. Bei 80ms sind
es 4 Überläufe und bei 500ms wie gesagt 30. Moment. Also das mit 30
funktioniert. ABer das mit den 4 Überläufen. Z.B. 60 geteilt durch 4 ist
auch Rest 0 und 40 geteilt durch 4 auch. Das heißt für die 80 ms
Sekunden braucht man was spezielles und für das LED_BAT auch oder??
Gruß
Thomas
Vielleicht sowas wie im Anhang. Achtung, das war noch nicht im Compiler,
kann also noch Schreibfehler haben und logische Fehler sowieso.
Beim Entprellen ist im Moment nur das _delay_ms() durch einen Zähler
ersetzt, der von der Timer0 ISR gefüttert wird. Gleiches Prinzip wie die
warte() vorher mit Sekunden.
Eingefügt ist noch die Behandlung des Timers beim Schlafen/Wecken. Die
Zustände der LEDs werden jetzt auch nicht gerettet, sondern nach dem
Aufwecken wird neu gemessen. Im Moment unmittelbar beim nächsten
Durchlauf durch das grosse while(1).
Die Schalterei der LEDs siehst du in der Source. Alles wird dem Timer
überlassen. dadurch kann es max. 500ms dauern, bis eine LED an geht. Am
"ehesten" wäre das bei der gelben LED zu beoabchten.
Ups, mir war nicht aufgefallen, dass der Aufruf von init() bereits in
Test3.c fehlte. Das habe ich nachgetragen und ein paar Änderungen für
den Simulator habe ich auch eingefügt.
Bastler schrieb:
> Charlieplex.
Das geht nur mit speziellen ICs (Maxim), die interne
Konstantstromquellen haben oder wenn Deine VCC kleiner als die 2-fache
LED-Spannung ist.
Ansonsten kriegst Du Geister-LEDs.
> Also ich glaube des wird jetzt wirklich zu kompliziert dann.
Das sehe ich schon länger so.
Du mußt aufhören, drauflos zu programmieren und Dir erstmal nen
Programmablaufplan machen.
Und mal verbal beschreiben, welche Zustände es überhaupt gibt und wann
welche LED wie schnell zu blinken hat.
Ich bleibe dabei, ohne Statemaschine wirst Du das Chaos nicht
beherrschen können.
Dein Gefrickel wird nie vollständig funktionieren. Du drehst an einer
Schraube, damit etwas geht und dafür geht aber was anderes nicht mehr.
Peter
Hallo!
Zunächst mal wieder danke für die Unterstützung. Also ein und
ausschalten funktioniert und die Feuchtemessung grundsätzlich auch.
Allerdings blinkt LED Gelb und LED Rot ziemlich ungleichmäßig. DAs
Batterie LED leuchtet nur durchgängig aber grundsätzlich geht das ja
schon ganz gut.
Das mit dem define der Schwellwerte finde ich super weil es einfach
übersichtlicher ist.
Das mit den Testfällen im Simulator dürfte ja für das Programm keine
Rolle spielen da ja 0 dahinter steht oder?
Also das mit der State Machine wäre wohl einfach nicht mehr möglich von
der Zeit her...
Gruß
Th.
Guten Morgen!
Kein Problem. Die Frage ist ja ob da alle liebe Mühe umsonst ist weil es
fast nur mit der Statemashine zu realisieren ist oder ob man das mit dem
Timer hinbekommt. Bin gerade dabei zu verstehen wann der wo rumspringt.
Ist hald gerade etwas verwirrend mit dem Lampendurcheinander. Ich glaube
schon dass des unangenehm ist wenn man die Schaltung nicht vor sich. Vor
allem wird jetzt das langsam zum Problem dass debuggen nicht möglich ist
mit dieser ICP Schnittstelle. Habe ja leider keine JTAG Schnittstelle.
Die Beschaffung von dem ATTINY24 scheint bisschen schwer zu sein ja.
Habe ihn beim Reichelt bestellt. Beim Conrad gibts den nicht. Habe
trotzdem nochmal den Code mitangehängt. Der Code liefert auf jeden Fall
keine Fehler mehr.
Gruß
Thomas
Bei der Statemachine käme sicher auch der Timer zur Anwendung.
Sobald du ein Projekt hast, bei dem Zeit eine Rolle spielt und bei dem
Aktionen annähernd parallel ablaufen sollen bsp. Blinken, ist es
geschickt einen Timer einzusetzen.
Die state machine hätte den Vorteil, dass du 1. zu jedem Zeitpunkt
exakt und leicht nachvollziehbar weisst, in welchem Zustand sich dein
Programm befindet und wie die Übergänge dazwischen passieren und 2. dass
es keine ungültigen/unvorhergesehenen Zustände und Übergänge gibt (bei
richtiger Planung und Umsetzung).
Die grosse Gefahr bei der Implementierung ohne state machine ist die
Verzettelung. Bei jeder Änderung kann es passieren, dass das fragile
Projekt zusammenstürzt, weil plötzlich Nebeneffekte auftreten bsp.
längere Laufzeit in einem Codeteil A zerbricht einen feingetunten
Codeteil B. Und diese Gefahr steigt mit jedem Tag an, an dem du
vergisst, was du vorher programmiert hast. Solche Programme zu debuggen
und zu warten oder an Dritte zu übergeben ist der Horror.
Bei dem grossen Zeitdruck den du beschreibst, würde ich zuerst eine
funktionierende 0.1 Version der Firmware festklopfen. Später kannst du
in einer ruhigen Stunde die Firmware deines Projekts auf eine /state
machine/ umschreiben. Du wirst sicher wertvolles für die nächsten
Projekte lernen. Die Hardware braucht ja - µC sei Dank - nicht geändert
zu werden.
Also dann dürfte des praktisch zu schwer werden ohne Statemachine einen
vernünftigen Code hinzubekommen oder? Hat mich ja auch gewundert dass
die Tasterentprellung scheinbar funktioniert hat. Aber die LEDs machen
wirklich die lustigsten Sachen. Wäre hald schön zu wissen was im
Controller in den einzelnen Registern und Variablen steht. So dürfte es
ja fast unmöglich sein den Fehler zu finden. Könnte natürlic das Blinken
der einen LED nach wie vor mit dem delay erledigen. Wie gehe ich da dann
weiter am besten vor außer den Fehler im vorhandenen Code suchen?
Gruß
Th.
Du kannst systematisch an die Sache rangehen und ein Problem nach dem
anderen lösen. (#)
Betrifft das Problem die Batterie-LED, dann lasse die Steuerung der
anderen LEDs mal weg (Stelle in feuchtemessung() auskommentieren). Bei
der Batterie-LED auch darüber nachdenken, dass sich ein "Kurzes
Aufblitzen dann 4s Pause" mit der derzeitigen Praxis beisst, die
Batteriemessung zu machen, wenn trigger gleich 0 ist. Letzteres ist
nämlich deutlich schneller als die 4s. Deshalb wird es hier garantiert
eine lustige Sache geben.
Ähnliches kann bei den Feuchte-LEDs passieren. Die Routine zum Setzen
einer Feuchte-LED ist die Timer-ISR. Die wird alle 16,x ms aufgerufen.
Die Feuchtemessung selber wird aufgerufen, wenn trigger durch 16 teilbar
ist.
Letzteres ist
a) wohl schneller als 16 ms, d.h. die Anzeige ist verzögert zur Messung.
Hier ist zu entscheiden, wie kurz hintereinenader gemessen werden
muss/soll. IMHO ist es nicht sinnvoll das Messintervall kürzer als das
Anzeigeintervall zu machen.
Und b) - mein Fehler! - die Setzerei der drei Werte für die Flags,
welche LED an und welche aus sein soll, ist nicht atomar, d.h. die
Timer-ISR kann (und wird nach Murphys Gesetz) irgendwann nicht
konsistente Werte sehen, wenn die Timer-ISR die drei Zeilen unterbricht,
die beim Setzen des LED Zustands verwendet werden.
Man kann das z.B. auf zwei Arten lösen:
1. ATOMIC-Makro um die jeweils drei Zeilen mit dem Setzcode in
feuchtemessung(). Das kennst du aus der Hauptschleife.
Oder
2. Verkürzung des Codes auf eine atomare Anweisung z.B. Verwendung von
Bit-Flags statt uint8_t Flags. Dabei muss man im vom GCC erzeugten
Assemblercode die Annahme prüfen, ob tatsächlich eine Anweisung erzeugt
wurde...
Also:
Hallo!!
Ok dann vergessen wir einfach mal dieses 4sekündige aufblitzen. Nur die
Feuchteleds sollen blinken und der Taster soll entprellt sein. Ist das
dann bei der Feuchtemessung ein Problem mit den Aufrufen alle 16 ms.
Könnte ja sagen alle 19 oder so. Also wenn trigger geteilt durch 19
teilbar ist oder?
Also das mit dem was du falsch gemacht haben sollst verstehe ich noch
nicht. Du sagst also dass das
volatile uint8_t takt_LED1_GRUEN;
volatile uint8_t takt_LED2_GELB;
volatile uint8_t takt_LED3_ROT;
nicht funktioniert und man mit einer Variablen für alle LEDs arbeiten
muss richtig? Theoretisch ist mir das klar. Da ja nie alle LEDs
gleichzeitig blinken müssen kann man das wohl mit etwas Zeitverlust so
machen.
Das mit dem takt_LED_FEUCHTE bedeutet man wählt Möglichkeit 2. Was
bedeutet das mit dem Bit-Flag??
Ich habe jetzt versucht das umzuschreiben alles und es zu durchdenken.
Grundsätzlich funktioniert die Feuchtemessung auch noch. Allerdings
blinkt jetzt gar nichts mehr und LED gelb verlischt nicht wenn rot
angeht. Bzw. rot und gelb bleiben ein wenn schon wieder grün leuchten
sollte.
Das dürfte wohl dadurch kommen dass ich ja bei der Anwahl der LEDs die
anderen nicht mehr deaktiviere oder?
Ich versuche im Moment auch noch die Abläufe in meinem Timer zu
verstehen. Mein Power Down funktioniert auch allerdings kann ich mir
nicht vorstellen dass da was entprellt ist. Also vermute ich dass mein
Taster derzeit ohne Entprellung arbeitet.
Wann platzt dieser Beitrag im Forum eigentlich???"g"
Gruß
Th.
Bastler schrieb:
> Allerdings> blinkt jetzt gar nichts mehr und LED gelb verlischt nicht wenn rot> angeht. Bzw. rot und gelb bleiben ein wenn schon wieder grün leuchten> sollte.
Auf den ersten Blick: Klar bei diesem Code...
1
if((takt_LED_FEUCHTE&LED_GRUEN)==AUS)
2
PORTA&=~LED_GRUEN;
3
if((takt_LED_FEUCHTE&LED_GELB)==AUS)
4
PORTA&=~LED_GRUEN;
5
if((takt_LED_FEUCHTE&LED_ROT)==AUS)
6
PORTA&=~LED_GRUEN;
da wird immer nur die grüne LED geschaltet! Ich schaue mir den Rest an
und laden dann den neuen Code hoch.
Bastler schrieb:
> Ok dann vergessen wir einfach mal dieses 4sekündige aufblitzen. Nur die> Feuchteleds sollen blinken und der Taster soll entprellt sein.
Dazu ist jetzt ein #if 0 #endif in batteriemessung(). Daran denken, das
später wieder rauszuholen.
> Ist das> dann bei der Feuchtemessung ein Problem mit den Aufrufen alle 16 ms.> Könnte ja sagen alle 19 oder so. Also wenn trigger geteilt durch 19> teilbar ist oder?
Es kommt auf die Anwendung an, die ich nicht kenne. Ändert sich die rel.
Luftfeuchte bei deiner Anwendung tatsächlich so schnell oder würde es
reichen in grösseren Abständen zu messen. Von der Anzeige her, bekommt
keiner mit, ob die LED 16ms später an- oder ausgeht.
> Also das mit dem was du falsch gemacht haben sollst verstehe ich noch> nicht. Du sagst also dass das>> volatile uint8_t takt_LED1_GRUEN;> volatile uint8_t takt_LED2_GELB;> volatile uint8_t takt_LED3_ROT;>> nicht funktioniert und man mit einer Variablen für alle LEDs arbeiten> muss richtig? Theoretisch ist mir das klar. Da ja nie alle LEDs> gleichzeitig blinken müssen kann man das wohl mit etwas Zeitverlust so> machen.
Wenn du wie im alten Code drei Anweisungen hast, um einen Anzeigezustand
einzustellen, kann dir zwischen die drei Anweisungen ein Interrrupt
reinfunken und du endest mit einem teilweise vor und teilweise nach dem
Interrupt gesetzten Zustand. Das kann hier dazu führen, dass kurzzeitig
nicht nur eine LED leuchtet oder gar keine LED leuchtet. Deshalb die
Suche nach einer Möglichkeit mit einem ununterbrechbaren Maschinenbefehl
einen Anzeigezustand einzustellen.
> Das mit dem takt_LED_FEUCHTE bedeutet man wählt Möglichkeit 2. Was> bedeutet das mit dem Bit-Flag??
Diese Möglichkeit bietet eine Variable, deren einzelne Bits als Schalter
benutzt werden. Alle Bits können bei einer 8-Bit Variablen in einer
Zuweisung an die Variable zugewiesen werden. Die C-Anweisung wird
(prüfen!) in einen Maschinenbefehl übersetzt und der wird dann ohne
Unterbrechung durch einen Interrupt abgearbeitet.
> Ich versuche im Moment auch noch die Abläufe in meinem Timer zu> verstehen.
Die Timer-ISR wird alle 16.x ms aufgerufen.
61 Aufrufe heisst 1s sind rum. Bei jedem Aufruf wird daher ein mit 61
vorbelegter Zähler (takt) runtergezählt. Wenn der Zähler bei 0 landet,
wird ein zweiter Zähler (sekunde) hochgezählt. Das ist die Funktion
"Uhr"
In der Timer-ISR wird bei jedem Durchlauf nachgesehen, ob das
Userprogramm angegeben hat, dass bestimmte LEDs AUSgeschaltet werden
sollen. Die Variable dazu sind die Variablen takt_LED_FEUCHTE und
takt_LED_BAT. Wenn in takt_LED_FEUCHTE bestimmte Bits 0 sind, wird die
entsprechende LED ausgeschaltet. Wenn takt_LED_BAT = AUS ist, wird die
Batterie LED ausgeschaltet. Das ist die Funktion "Ausschalter".
In der Timer-ISR wird bei jedem Durchlauf nachgesehen, ob das
Userprogramm angegeben hat, dass bestimmte LEDs EINgeschaltet werden
sollen. Die Variable dazu sind die Variablen takt_LED_FEUCHTE und
takt_LED_BAT. Wenn in takt_LED_FEUCHTE bestimmte Bits 1 sind, wird die
entsprechende LED eingeschaltet. Wenn takt_LED_BAT = EIN ist, wird die
Batterie LED ausgeschaltet. Das ist die Funktion "Einschalter".
Als Besonderheit gilt hier, dass die gelbe und rote Feuchte-LED und die
Batterie-LED blinken sollen.
Bei den blinkenden Feuchte-LEDs (1 Hz und 2 Hz) erfolgt das durch
Abpassen des richtigen Moments (takt % ...) und Toggeln des Ports an dem
die LED hängt (^=).
Bei der blinkenden Batterie-LED erfolgt das durch getrennte AN/AUS
Schalterei, weil der Rhythmus "kurz aufblitzen, dann 4s Ruhe" sein soll.
Die 4s werden dadurch realisiert, dass takt_LED_BAT hochgesetzt wird und
eine bestimmte Anzahl von Durchläufen mit Runterzählen verstreichen
müssen, bis die LED wieder angeschaltet wird.
> Mein Power Down funktioniert auch allerdings kann ich mir> nicht vorstellen dass da was entprellt ist. Also vermute ich dass mein> Taster derzeit ohne Entprellung arbeitet.
Die Entprellung des EIN/AUS-Tasters wird in tastenabfrage() dadurch
sichergestellt, dass eine bestimmte Zahl (80/16) von Timer-ISRs
verstrichen sein müssen und der Pegel am Pin dann gleich dem zuerst
abgefragten Pegel sein muss. Es wurde nur das _delay_ms(80) ersetzt.
Der Taster an INT0 zum Aufwecken ist nicht entprellt. Hier wird auf den
ersten ankommenden LOW-Pegel reagiert.
> Wann platzt dieser Beitrag im Forum eigentlich???"g"
Das Forum ist sehr stabil. Ich habe noch nie einen Thread platzen sehen.
Und wir brauchen nur noch 4 Fragen/Antworten dann sind wir bei 100
So, ich hatte heute abend etwas Zeit und habe dein Programm auf den
Attiny2313 portiert, weil ich den zu Hause hatte.
In der Source ist dazu am Anfang ein #define für mein POLLIN... Board
mit dem Attiny2313 bei 8 MHz, was auch einen anderen Vorteiler verlangt.
Das #define lässt du für den Attiny24 einfach auskommentiert stehen.
Da beim Wechsel vom Attiny24 zum Attiny2313 alle Pins anders verstrippt
werden mussten, habe ich dafür Makros eingeführt. Der Attiny2313 hat
auch keinen ADC, deshalb arbeite ich hier mit künstlichen Prüfwerten. Du
kannst ja die echte Messung machen.
Beim Praxistest ist mir als erstes der Schluckauf beim Blinken
aufgefallen. Ursache war, dass der Hilfszähler takt nicht
zurückgesetzt wurde, wenn er 0 erreicht hatte. Wo der Codeschnippsel in
der langen Diskussion verloren ging, weiss ich nicht. Er war mal da.
Im Moment gibt es auch nur einen aktiven Taster - den Wecktaster an dem
INT0 Pin. Damit schaltet man den AVR EIN (wecken) und AUS (schlafen).
Dafür wurde auch die Entprellung etwas sorgfältiger behandelt, aber 100%
optimal ist es noch nicht. Man kann das einfach auf zwei Taster (1xAUS
und 1xWecken) ändern, wenn dir das lieber hast.
Ich hoffe du kommst mit dem Code zurecht. Wenn nicht frag einfach.
Guten Morgen!!
Nochmal herzlichen Dank. Ich bin bis jetzt noch nicht dazu gekommen mir
deine erste Mail anzuschauen und alles auszuwerten. Ich hoffe aber dass
ich es heute noch schaffen werde!!
Gruß
Thomas
Hallo!
Zunächst mal zum Code deiner ersten Email. Es funktioniert schon mal
wesentlich besser. Allerdings scheint das schnelle Blinken der LED doch
manchmal etwas hektisch. Man könnte also durchaus damit es einfacher
wird für gelb und rot den gleichen Blinktakt wählen. Also 1 Hz. Das
sollte die Sache dann wohl noch einfacher gestalten. Das blinken ist
allerdings unregelmäßig.
Ok also das #if 0 #endif ist so wie wenn ich "/*......*/" mache. Das ist
mir schon klar. Mit #if 1 aktiviere ich diesen Teil des Codes. Wozu
gehört dann dass #ifdef und #else??
Es reicht leicht in größeren Abständen zu messen weil es eh immer dauert
und die Messung ja von Haus aus sehr ungenau ist. Was bedeutet größere
Abstände?? Halbe Sekunde??
Ok das mit den 61 Aufrufen pro Sekunde ist mir klar. Also grundsätzlich
wird mein Timer Interrupt alle 16,.. ms aufgerufen. Es sind auch
wirklich 16 ms weil das nach dem Komma wegfällt. Dann arbeitet er da
durch und schaut ob er was zu blinken oder was auch immer hat. Wenn
nicht springt er wieder ins Programm zurück. Richtig? Ja das mit dem
takt-- ist klar. Also jeden Aufruf -1. Am Ende der ISR ist dann ja noch
takt_Taster ++. Das wird also hochgezählt oder wie? Funktion Ausschalter
ist klar. Ja genau mit dem ^= habe ich auch noch meine Probleme. &= ist
mir klar und |= ist mir auch klar.
Zum Aufwecken wird eine Entprellung ja wohl nicht nötig sein oder??
Zweiter Eintrag von dir:
Das sieht ja schon mal völlig anders aus irgendwie.... Also zwei Taster
wäre schlecht wegen meiner Technologie. Es sollte schon bei einem
bleiben. Ok nochmal zu dem #if. Also wenn #if 0 dort steht und danach
#else wird in dem Fall der else teil ausgeführt oder?
WOW!! Ich glaube jetzt klappt das wirklich alles. Mein LED Bat LED
leuchtet wie gewünscht und das andere klappt auch super. So jetzt werde
ich aber erst mal heimgehen!!"g" Da stürze ich mich morgen wieder drauf.
Nochmals vielen Dank. Normal würd ich sagen des kost a Mass!!!"g"
Gruß
Th.
Und hier mal der Ansatz mit Statemachine.
Ich hab aber nur nen ATmega48 gehabt, der ATtiny24 paßt nicht aufs
STK500.
Die Messungen werden mit 4 Tasten simuliert.
Ich hoffe mal, ich hab die Blinkmuster richtig aus Deinem Code
interpretiert.
Das Power-Down ist noch nicht drin. Das sollte man auch besser zum
Schluß machen, wenn alles andere richtig funktioniert.
Im Anhang sind alle nötigen Files.
AAARRRRRGGGHHHH - Jetzt schnappt sich der Peter die 100 ;-)
Bastler schrieb:
> Ok also das #if 0 #endif ist so wie wenn ich "/*......*/" mache. Das ist> mir schon klar. Mit #if 1 aktiviere ich diesen Teil des Codes. Wozu> gehört dann dass #ifdef und #else??
#if, #ifdef, #else, #endif... sind Anweisungen für den C-Präprozessor.
Wenn du mehr in C programmierst, brauchst du die und du solltest dir das
in einem C Buch anschauen.
> Es reicht leicht in größeren Abständen zu messen weil es eh immer dauert> und die Messung ja von Haus aus sehr ungenau ist. Was bedeutet größere> Abstände?? Halbe Sekunde??
Weiss nicht, du musst ein Gefühl dafür bekommen, wie dein Gerät
eingesetzt wird und wie geduldig/ungeduldig die Anwender sind. Wenn der
Prototyp einsatzbereit ist, gib ihn mal einem vollkommen unbedarften
Anwender. Sag nix zur Bedienung und schau eine halbe Stunde zu...
> Ok das mit den 61 Aufrufen pro Sekunde ist mir klar. Also grundsätzlich> wird mein Timer Interrupt alle 16,.. ms aufgerufen. Es sind auch> wirklich 16 ms weil das nach dem Komma wegfällt.
Nein, überlege das nochmal durch.
Es sind exakt 16,384 ms von Überlauf zu Überlauf, ABER du zählst für
die Sekunde ganzzahlig 61 mal diesen Überlauf statt exakt 61,03515625
mal, d.h. deine "Pseudosekunde" ist nur 16,384*61 = 999,424 ms lang
statt 16,384*61,03515625 = 1000 ms. Exakt heisst hier natürlich nur im
Rahmen der Genauigkeit der Taktquelle.
> Ja genau mit dem ^= habe ich auch noch meine Probleme. &= ist> mir klar und |= ist mir auch klar.
Steht auch in jedem C Buch unter dem Abschnitt Operatoren für
Bitmanipulation (Bits invertieren).
> Zum Aufwecken wird eine Entprellung ja wohl nicht nötig sein oder??
Der INT0 ist ein extrem scharfer Wachhund. Sobald die Leitung vom Taster
an den Pin LOW geht, schlägt der Interrupt zu. Da ist zunächst nix mit
Entprellen, zumal der AVR ja noch pennt und für die Entprellung in
Software erstmal aufwachen muss. Im Code fehlte aber das Warten auf das
Loslassen der Aufwecktaste.
An der Stelle müsste man noch etwas sorgfältiger arbeiten und die
Tasterabfrage aufräumen. Ich könnte mir vorstellen, dass die Timer-ISR
auch regelmäßig den Tastenzustand abfragt und entprellt und die
tasterabfrage() nur das Ergebnis bekommt. Wahrscheinlich hat Peter im
Code oben das so gemacht; seine bewährte Routine zur Tastenentprellung
arbeitet mit dem Timer.
> Zweiter Eintrag von dir:> Das sieht ja schon mal völlig anders aus irgendwie.... Also zwei Taster> wäre schlecht wegen meiner Technologie. Es sollte schon bei einem> bleiben.
Ja, mit den zwei Tastern war ein Mistverständnis von mir.
> Nochmals vielen Dank. Normal würd ich sagen des kost a Mass!!!"g"
Gerngeschehen. Das Maß gönne ich mir am Wochenende.
Hallo!
Also überblicksmäßig sieht das ja toll aus mit der Statemachine. Das ist
ja wirklich viel einfacher. Da ist der Code ja nur noch 2 Seiten lang
anstatt meinen 8 oder 9 Seiten.
Im Endcode kommen die ganzen #if Kommentare dann ja raus vermute ich
oder? Das wäre ja ein unsauberer Stil.
Gefällt mir alles so weit gut. Also mein gelbes LED blinkt jetzt
praktisch mit 1Hz. Das heißt 0,5s an und 0,5s aus. Das rote ist 0,25s an
und 0,25s aus. Naja beides auf 1Hz setzen das schaffe ich auch noch. Was
mir nur auffällt ist dass wenn dass Bat-LED blitzt und rot oder gelb
blinkt dann zuckt das hin und wieder. Das ist nicht schlimm wird sich
auch so nicht beheben lassen vermute ich.
Naja jetzt steht nur noch an dass man den Spannungsteiler nicht an VCC
hängt sondern an einen Portpin. Das geht wohl über die REFS1 und REFS2
Bits oder?
Gruß
Thomas
Bastler schrieb:
> Im Endcode kommen die ganzen #if Kommentare dann ja raus vermute ich> oder? Das wäre ja ein unsauberer Stil.
Wieso wäre das unsauber? "Legale" Anwendung solcher #if..#endif Klammern
ist z.B. die Konfiguration auf unterschiedliche Hardware oder als
Unterscheidung von Debug/Release-Code.
Beides wird oben verwendet. Einmal als Unterscheidung zwischen dem
unterschiedlichen Anschluss an einen Attiny24 von dir und einen
Attiny2313 von mir. Und einmal als Debugcode mit bestimmten Testwerten
statt aktueller Hardware und dem Releasecode mit der tatsächlichen
Messung.
Wenn etwas unsauber ist, dann die Stellen bei denen lediglich ein #if 0
oder #if 1 steht. Die sollte man sauber dokumentieren oder streichen,
wenn es alter nicht mehr benutzter Testcode ist.
> Gefällt mir alles so weit gut. Also mein gelbes LED blinkt jetzt> praktisch mit 1Hz. Das heißt 0,5s an und 0,5s aus. Das rote ist 0,25s an> und 0,25s aus. Naja beides auf 1Hz setzen das schaffe ich auch noch.
Ähm, du wolltest doch extra, dass Gelb langsam blinkt und Rot doppelt so
schnell. Jetzt willst du das wieder nicht?
> Was> mir nur auffällt ist dass wenn dass Bat-LED blitzt und rot oder gelb> blinkt dann zuckt das hin und wieder. Das ist nicht schlimm wird sich> auch so nicht beheben lassen vermute ich.
Ist mir so nicht aufgefallen, werde ich mal darauf achten. Ich betreibe
die Schaltung aber auch an einem Netzteil mit genügend Saft und nicht an
einer Batterie. (Batterie-)betrieb mit <5V (>=9V vor
Festspannungsregler) ist dort nicht möglich.
> Naja jetzt steht nur noch an dass man den Spannungsteiler nicht an VCC> hängt sondern an einen Portpin. Das geht wohl über die REFS1 und REFS2> Bits oder?
Du hast doch schon den Jumper JP1 drin, um entweder Vcc oder die
Spannung von PA7 auf den Spannungsteiler zu geben. Wenn der Jumper JP1
auf Versorgung durch PA7 gesetzt wird, muss vor der Feuchtemessung PA7
einen HIGH-Pegel ausgeben und am besten direkt nach der Feuchtemessung,
aber spätestens vor dem Schlafengehen einen LOW-Pegel (Stromsparen).
Die Einstellung der ADC-Referenz kann gleich bleiben. Als ADC-Referenz
kann immer die im AVR intern geführte Vcc benutzt werden oder im
Spezialfall die iM AVR interne Bandgap-Referenz von 1.1V, wenn die
erwartete Maximalspannung an dem Messeingang ADC0 kleiner 1.1V ist.
Welche von beiden du benutzt, wird über REFS1 und REFS2 eingestellt.
Wenn du die Referenz von Vcc auf 1.1V umstellst, weil vielleicht die
max. Messspannung bei Versorgung durch PA7 kleiner als 1.1V wird, dann
denk daran, dass sich die SCHWELLE_... Werte bei der Feuchte ändern. Die
Batteriemessung ist davon nicht betroffen.
So, hier jetzt mal mit kompletter Funktion.
Du mußt nur noch die Anpassungen an Deine Schaltung machen.
Die Pinanpassungen sind ja einfach zu machen.
Der Timer0 müßte beim ATtiny24 sogar gleich sein (mal prüfen).
Unterschiede könnten noch beim ADC sein (MUX).
Die einzelnen Spannungsschwellen mußt Du einfach nur eintragen.
Für die Messung muß ja an den Bereichsgrenzen ne Hysterese erfolgen,
damit die LEDs nicht flackern.
Die Bandgap ist sehr hochohmig, d.h. die ersten 8 Messungen stimmen
nicht. Daher werden erstmal 16 Dummymessungen gemacht.
Den Sensor habe ich mit einem Poti simuliert und die
Unterspannungserkennung mit dem STK500 (Einstellen der Targetspannung).
Wurde Unterspannung erkannt, kommt man erst wieder durch an/aus in den
Meßmodus. Es kann also auch da kein Flackern passieren.
Bei mir funktioniert somit alles einwandfrei.
Als letzter Schritt ist dann nur noch das Stromsparen übrig (sollte man
ja immer als letztes machen).
So, hier nun die fertige Version.
Für das Schlafen habe ich den Pin-Change Interrupt genommen.
Das hat den Vorteil, daß man bereits beim Drücken schlafen gehen kann
und man ist außerdem flexibler mit der Pin-Wahl.
Für das Schlafen habe ich noch ne extra Funktion in die Get-Key Routine
geschrieben. Mit dieser kann man testen, ob das Entprellen der
Aufwachtaste schon beendet ist. Erst dann darf man schlafen gehen.
An der Schlaffunktion ist nichts besonderes. Sobald mit der Taste der
Zustand "OFF" ausgewählt wurde, wird sie aufgerufen und versucht
schlafen zu gehen. Da die Taste prellt, wird mehrmals sofort wieder
aufgewacht, aber das stört überhaupt nicht.
Durch die Trennung von Schlaffunktion und Entprellfunktion gibt es keine
unerwünschten Zustandswechsel. Die Schlaffunktion kümmert sich nur um
das Stromsparen und die Entprellfunktion nur um die Statemachine.
Die Blinkfunktionen habe ich noch etwas verständlicher geschrieben
(if/else).
Ich denke, an den 3 Schritten sieht man auch schön eine sinnvolle
Vorgehensweise:
1. Grundgerüst mit Dummyfunktionen
2. Ersetzen der Dummyfunktionen mit den Meßfunktionen
3. Stromsparen
Besonders für den 3.Schritt ist es wichtig, daß die Entprellung schon
einwandfrei funktioniert, sonst wird das nix.
Der Code ist insgesamt auf 676 Byte angewachsen.
Peter
Guten Morgen!!
Zunächst wieder mal herzlichen Dank für eure umfangreiche Hilfe...!
Zu Stefans Nachricht:
Wußte ich nicht dass man dieses #if ... #endif so verwendet. Ist aber
umso besser wenn das möglich ist!! Solang es mit der Codegröße kein
Problem ergibt. Weiss ja nicht wieviel mein Attiny 24 schluckt.
Irgendwann wird der Kanal wohl mal zu sein?!
Ja ich weiss ich wollte die verschiedenen Blinkfrequenzen. Ich werde da
auch nochmals nachfragen was gewünscht wird. Ich wollte es hald nur mal
testen ob ich das auch anders machen kann mit gleicher
Blinkgeschwindigkeit!
Meinst du das hängt mit der Batterie zusammen dieses "überblinken"?? Es
ist nur immer wenn das Ereignis doppelt auftritt.
Ja. Also hardwaremäßig brauche ich nichts mehr verändern um den
Spannungsteiler an einen Portpin zu hängen. Sprich des sieht dann so aus
wie bei meinem Power Down Taster. Referenz kann gleich bleiben auch wenn
ich das nicht verstehe. Ich lege den Portpin auf Eingang und auf High.
Dann hat er wohl Vcc - x als Versorgungsspannung. Vorm schlafen gehen
setze ich das dann auf 0 und nach dem aufwachen wieder auf 1 vermute ich
mal. Glaubst du dass an dem Portpin unter 1,1 V anliegen. Da sollte doch
annähernd mein Vcc sein? Kann man ja leicht messen da beim PowerDown
Taster.
Zu Peters Nachricht:
Also mit einer State Machine (Zustandsautomat) bin ich wohl auf der
sicheren Seite vermute ich mal?! Ich werde auch den Code mal
ausprobieren. Die ersten 8 Messungen stimmen nicht. Dürfte ja kein
Problem sein da mein Sensor grundsätzilch schon ungenau ist. Ich
verwende ja auch kein Display sondern nur die 3 LEDs. Ok. Bei mir waren
es ja die 4 Dummymessungen und jetzt sind es hald 16.
Was meinst du mit Stromsparen? Beim PowerDown dass alles ausgeschaltet
wird?? Das Problem für mich wird ja nur sein den Code in meiner
Facharbeit dementsprechend zu beschreiben!!"g" Da ich natürlich erst mal
immer viele Seiten schreiben möchte wäre natürlich der "normale" Code
besser weil man da wohl mehr beschreiben kann so weit ich das bewerten
kann. State Machine wäre hald wohl die professionelle Lösung so wie ich
das jetzt deinen Aussagen entnehme.
Den pin-Change Interrupt hast du benutzt. Mir wurde aber doch gesagt
dass das mit dem Taster mehrere Zustände sind. Drücken, der Zustand wo
Taster gedrückt und dann der Zustand wo Taster ausgelassen wird. Und
sollte nicht dann erst was passieren??? Habe ich da was falsch
verstanden?
Das mit der Schlaffunktion verstehe ich noch nicht. Die Taste prellt hat
aber eine Entprellung???? Das widerspricht sich doch oder??
676 Byte muss ich da beim Attiny 24 Angst haben?? Schafft er das noch???
Danke!
Gruß
Th.
Bastler schrieb:
> Meinst du das hängt mit der Batterie zusammen dieses "überblinken"?? Es> ist nur immer wenn das Ereignis doppelt auftritt.
Das weiss ich nicht. Viele Gedanken habe ich mir da nicht gemacht, weil
ich die Situation nicht komplett nachstellen kann.
> Ja. Also hardwaremäßig brauche ich nichts mehr verändern um den> Spannungsteiler an einen Portpin zu hängen. Sprich des sieht dann so aus> wie bei meinem Power Down Taster.
Ich verstehe nicht was der Power Down Taster mit der Spannungsversorgung
des Spannungsteilers zu tun hat.
> Referenz kann gleich bleiben auch wenn> ich das nicht verstehe.
Aus dem Portpin PA7 käme maximal Vcc raus (in der Praxis etwas weniger,
Datenblatt), d.h. wenn deine Messung mit der Vcc-Versorgung und der
Referenz Vcc funktioniert, wird die Messung auch mit der
Portpin-Versorgung und der Referenz Vcc funktionieren.
> Ich lege den Portpin auf Eingang und auf High.> Dann hat er wohl Vcc - x als Versorgungsspannung. Vorm schlafen gehen> setze ich das dann auf 0 und nach dem aufwachen wieder auf 1 vermute ich> mal.
So sieht es aus. Und: Wenn gerade keine Feuchtemessung läuft, braucht
der Spannungsteiler auch keinen Strom... Abgesehen davon könnte es für
den Sensor auch gesund sein, wenn er nicht dauernd stromführend ist,
auch wenn es sich um sehr kleine Ströme handelt (Datenblatt).
> Glaubst du dass an dem Portpin unter 1,1 V anliegen. Da sollte doch> annähernd mein Vcc sein? Kann man ja leicht messen da beim PowerDown> Taster.
Die Messung würde nichts bringen. Hier ist ein anderen Portpin gemeint:
Der Messeingang der Spannung des Spannungsteilers, also deine
Signalspannung an PA0. Nicht der Portpin zur Spannungsversorgung des
Spannungsteilers!
Wenn die Signalspannung an PA0 immer kleiner als 1.1V ist, könntest du
statt der Referenz Vcc die Referenz 1.1V einsetzen und so die Auflösung
(Auflösung und Genauigkeit) erhöhen.
Hallo!
Der Power Down hat nichts mit der Spannungsversorgung für den
Spannungsteiler zu tun. Mir ging es da nur um die Pinbeschreibung. Ich
werde für meine Spannungsversorgung die gleichen Werte benötigen wie für
den Power-Down Taster. Also auf Eingang und High für Pull-Up. Ok das mit
dem Portpin PA7 ist auch klar.
Dann werde ich das mal versuchen. Werde mich diesbezüglich wohl bald
wieder melden!
Bastler schrieb:
> Die ersten 8 Messungen stimmen nicht. Dürfte ja kein> Problem sein da mein Sensor grundsätzilch schon ungenau ist.
Nö, das betrifft nur die Bandgap-Messung, ich hatte oben schonmal Links
dazu gepostet.
> Das Problem für mich wird ja nur sein den Code in meiner> Facharbeit dementsprechend zu beschreiben!!"g"
Vielleicht kann ja mal Stefan drüberschauen, ob er ihn versteht.
> Da ich natürlich erst mal> immer viele Seiten schreiben möchte wäre natürlich der "normale" Code> besser weil man da wohl mehr beschreiben kann
Ich glaub, zu der Statemachine gibts auch genug zu schreiben.
Der Vorteil ist, daß man die Funktionen getrennt beschreiben kann, da
sie voneinander unabhängig sind.
> Mir wurde aber doch gesagt> dass das mit dem Taster mehrere Zustände sind. Drücken, der Zustand wo> Taster gedrückt und dann der Zustand wo Taster ausgelassen wird. Und> sollte nicht dann erst was passieren???
Genau daher eben die Trennung zwischen Power-Down und Entprellen.
Die Entprellfunktion wurde schon woanders beschrieben:
http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29> 676 Byte muss ich da beim Attiny 24 Angst haben?? Schafft er das noch???
Schau mal ins Datenblatt, da stehts drin.
Peter
Bastler schrieb:
> Ich> werde für meine Spannungsversorgung die gleichen Werte benötigen wie für> den Power-Down Taster. Also auf Eingang und High für Pull-Up. Ok das mit> dem Portpin PA7 ist auch klar.> Dann werde ich das mal versuchen. Werde mich diesbezüglich wohl bald> wieder melden!
Tu das, mich interessiert, ob die Vorsorgung durch einen *Inputpin mit
Pull-Up* funktioniert.
Du hast eine Vcc abhängige und auf wenige µA begrenzte Versorgung durch
den internen 20k bis 50k Pull-Up (Abschnitt 21.6 Pin Pull-up im
Datenblatt).
Als zweiten, aber kleinen Stromabnehmer hast du neben dem
Spannungsteiler den sehr hochohmigen Inputpin (im Bereich von typ.
<0.05µA bis max. 1µA bei Vcc 5V, Input Leakage Current I/O Pin in Table
20-1. DC Characteristics).
Ich bin gespannt, ob der Spannungteiler (1M5 bis 2M5 Ohm tot. je nach
Feuchte) dann ausreichend befeuert wird.
Hallo!!
Peter:
Zunächst mal danke für das Programm. Werde es testen sobald es mir
möglich ist.
Stefan:
Bin gerade dabei am Programm paar Änderungen vorzunehmen. Hardwaremäßig
habe ich meinen Prototyp 1 umgebaut. Ich habe den Spg.teiler an PA7
hängen und es scheint zu funktionieren. Im Power-Down scheine ich jetzt
noch viel weniger Strom zu verbrauchen. Kann man das so schreiben wie
ich es in Test 13 gemacht habe?? Der Ausgang an PA7 ist fast Vcc. Nur
paar mV weniger.
Außerdem habe ich versucht für die rote LED noch eine Definition auf 1
Hz zu machen. Sprich dass rot genauso schnell blinkt wie gelb.
Funktioniert aber nicht. Kann das ja mit dem #define beliebig
umschalten!
Gruß
Th.
Bei den Alternativen 1Hz/2Hz hast du zu viel Code genommen. Es reichen
ein paar wenige Zeilen. Der Sekundenzähler (im 1Hz-Timerteil) und die
Batterie-LED (im 2Hz-Timerteil) sind ja nicht betroffen.
Das Abschalten der Versorgung durch PA7 sollte IMHO direkt nach der
Messung gemacht werden. Je früher, desto weniger Energie entfleucht
nutzlos durch den Spannungsteiler. Und du sparst dadurch die
Sonderbehandlung vor dem Schlafen und nach dem Wecken.
Nur so als Anmerkung: Auch MCs müssen sich an Mathematikregeln halten:
Wenn (messwert >= SCHWELLE_ROT) falsch ist, brauchst Du nicht mehr auf
(messwert < SCHWELLE_ROT) testen.
Und wenn (messwert > SCHWELLE_GELB) falsch ist, bleibt dem Meßwert
nichts anderes übrig, als (messwert <= SCHWELLE_GELB) zu sein.
Diese beiden Tests sind also überflüssig.
Ich finde auch ROT, GELB und GRUEN nicht sehr aussagekräftig. Es soll
doch ne Feuchte geprüft werden, da wäre TROCKEN, NORMAL, FEUCHT viel
verständlicher.
Ich glaub auch nicht, daß der Sensor super stabil ist, d.h. nahe den
Umschaltwerten werden immer beide LEDs flackern. Das sieht unschön aus.
Schau mal in meinen Code, da habe ich ne Hysterese einprogrammiert.
> Bei den Alternativen 1Hz/2Hz hast du zu viel Code genommen.
Wenn ich so die Zeiten lese, 4s, 2s, 1s, 0.25s, da geht mir ein
Seifensieder auf, daß das ja alles Teiler von 4s sind.
Man könnte also ein Byte bis 4s zählen lassen (4s = 15.6ms * 256) und
dann sind die einzelnen Bits die gewünschten Zeitintervalle.
Dann je nach Blinktakt einfach nur das richtige Bit auf die LED geben.
Peter
Peter, du hast bei allen Punkten Recht. Man könnte an dem Programm
einiges verbessern.
Die Frage ist bei mir:
Wer schreibt das Programm, Thomas oder ein anderer?
Ich bin von Anfang an bei meinen Antworten mit dem Ziel vorgegangen,
dass Thomas sein Programm selbst schreiben muss. Anders als manch
anderer Fragesteller, war er ja auch dazu bereit und ist beharrlich
dabei geblieben.
Klar, zu Beginn war fast nur das Abfragen einer Taste und das Leuchten
lassen von LEDs da. Das hat sich aber mit der Zeit nach vielen Fragen,
Recherchen und Antworten hier im Forum mit der Teilnahme einiger User
gemausert. Dies ist ja nicht der einzige Thread dazu. Es ist inzwischen
eine Sleep-Implementierung drin. Es ist ein Aufwecken per INT0 drin. Es
ist eine Messung von Vcc per ADC drin (bei der ich einiges von euch
lernte) und eine Messung des Sensors... viel fehlt nicht mehr und er
wäre mit seinem Projekt das halbe Tutorial durch.
Gerade im letzten Monat hat Thomas mehrmals von Zeitdruck geschrieben.
Und mir schien, dass eine Featuritis akut war und dass die Gefahr
bestand, nicht mal eine Firmware 0.1 kurzfristig fertig zu bekommen.
Deinen ersten und zweiten Hinweis auf eine bessere Implementierung mit
einer Statemachine habe ich frühzeitig unterstützt. Das hätte aus Sicht
von Thomas aber auch bedeutet ein solala funktionierendes Programm
komplett auf andere Füsse zu stellen. Egal, er hat die Hinweise damals
nicht aufgegriffen und ich wollte das auch nicht erzwingen
Das Thema Timer war auch nicht verstanden und ich hielt den Timer für
essentiell, um überhaupt eine Chance auf ein im Zeitablauf stabiles
Programm zu haben.
Aus diesen Gründen habe ich mehr als anfangs beabsichtigt in die
Programmierung an sich eingegriffen, indem ich irgendwann das Gerüst von
Thomas für den Timer ergänzt habe. So gesehen habe ich geschummelt und
es mir leichter gemacht. Statt noch mehr Diagramme zu zeichnen und zu
erklären, habe ich die Nerven vorloren und Code vorgesetzt.
Und ich habe den Eindruck, dass genau der Programmteil Timer und damit
die LED füttern bei Thomas noch die meiste Zeit beim Nachvollziehen und
Dokumentieren braucht. Ich hoffte und hoffe noch, wenn der Druck "ich
brauche eine funktionierende Firmware" gelöst ist, hat Thomas Ruhe und
Muse diesen Teil zu verstehen.
SCHWELLE_ledfarbe habe ich genommen, um leichter Simulationswerte für
die drei LEDs einzugeben. Denn um die inzwischen absehbare Firmware 0.1
zu testen, habe ich mir an einem Abend einen Hardwaredummy ohne Sensor
und mit einem gerade vorhandenen Attiny2313 aufgebaut. Was Trocken oder
Nass bei dem Sensor und welcher LED bedeuten habe ich dabei nicht
nachvollzogen. Mir war wichtig, beim Testen bestimmte LEDs zu schalten.
Aber an der Namenswahl und dem Hysteresethema sieht man, dass fremde
Codestücke, eine Simulation oder ein Hardwaredummy nicht die Realität
und das Know-How des alten Hasen ersetzen können.
Ich hoffe Thomas stellt sein Projekt nach der Abgabe seiner Facharbeit
nicht ein, sondern rekapituliert die Diskussion und macht aus den
gesammelten Erkenntnissen eine bessere Firmware. Es würde ihn meiner
Meinung nach im Bereich µC weiterbringen, wenn er dabei bleiben will.
Wie heisst es nach dem Programmieren einer Software? "Es läuft, jetzt
müssten wir das eigentlich neu schreiben." Mit deiner Variante über
Statemachine hat Thomas sicher eine sehr gute Ausgangsbasis und den
direkten Vergleich.
In diesem Sinn
Stefan
Stefan B. schrieb:
> Aus diesen Gründen habe ich mehr als anfangs beabsichtigt in die> Programmierung an sich eingegriffen, indem ich irgendwann das Gerüst von> Thomas für den Timer ergänzt habe. So gesehen habe ich geschummelt und> es mir leichter gemacht. Statt noch mehr Diagramme zu zeichnen und zu> erklären, habe ich die Nerven vorloren und Code vorgesetzt.
Ich hab schon viel früher aufgegeben. Ab ner bestimmten Anzahl von
Problemstellen mag man sich nen Code nicht mehr weiter ansehen, auch
wenn er funktioniert.
Ich habe auch als Anfänger drauflos programmiert und nie zuerst nen
Programmablaufplan gemacht. Und wenn man dann vor dem absoluten Chaos
steht und doch nen Plan macht, entwirren sich mindestens 90% der
Probleme.
Was für nen Anfänger wohl schwer zu verstehen ist, ist die quasi
Gleichzeitig von Aufgaben in der Mainloop. Die Mainloop läuft so schnell
durch, daß es so aussieht, als mache sie viele Sachen gleichzeitig.
Ein Anfänger will immer alles streng der Reihe nach machen, bloß an der
ersten Wartestelle wirds dann haarig.
Da hilft dann ein Plan: Aha, hier muß ich warten, da mache ich
inzwischen mit den anderen Aufgaben weiter.
Letztendlich geht kein Programm ohne Plan, bloß macht man ihn als
Erfahrener für solche kleine Aufgaben im Kopf.
Die Tastenentprellung konnte ich ja aus der Schublade ziehen und das
Power-Down auch. Der Rest war dann fast nur Schreibarbeit.
Was ich hier das erste mal ausprobiert habe, ist die Switch-Anweisung
mit Bereichen. Das ist deutlich übersichtlicher, als ne If-Kaskade und
vermeidet automatisch unnütze Doppeltests.
Die Switchanweisung achtet nämlich streng darauf, daß kein Case doppelt
auftritt, da gibts sofort die rote Karte (Error-Meldung).
Und der erzeugte Code ist sogar schön klein und schnell.
> Mit deiner Variante über> Statemachine hat Thomas sicher eine sehr gute Ausgangsbasis und den> direkten Vergleich.
Da würde mich mal interessieren, ob Du denkst, da könnte sich ein
Anfänger durchwuseln oder ob es viel zu kompliziert ist.
Peter
Ich denke für den fortgeschrittenen Anfänger ist dein Code
nachvollziehbar. Aber es braucht Zeit, wie jeder fremde Code, den man
sich anschaut. Die wesentlichen Unterschiede beim ersten Darüberblicken
für mich waren:
1. Die Manipulation der Ports
Dein Verfahren arbeitet mit den SBIT Makros. Das habe ich bisher
seltener gesehen als die direkten Anweisungen in der Source (PORT... =
...) bzw. die darauf basierten dirkten Verfahren mit Makros. Keine
grosse Hürde.
2. Die Entprellung
Hier muss man sich einlesen, wie zunächst das Warteschleifen-Verfahren
durch ein Polling im Timer-Interrupt ersetzt wird. Und man muss den Dreh
rausbekommen was die Masken und Statusvariablen etc. bedeuten. Deine
anscheinend bevorzugte Manipulation von Bits z.B. mit ^ ist für den
Anfänger anspruchsvoll. Weil der Code an sich knapp geschrieben ist und
Kommentare selten sind, ist man aufs Tutorial angewiesen. Diese Stelle
ist IMHO die grösste Hürde.
3. Das doppelte switch in main
Anschaulicher für mich wäre es gewesen, alle Zustände in einem switch zu
behandeln. Man braucht aber eine schnelle Reaktion auf den OFF Zustand,
d.h. man darf man die Messungen nicht durchführen, wenn die Abfrage der
Taste OFF liefert. Ich hätte das mit einem if auf not OFF statt auf die
anderen Zustände abgefragt oder den OFF Zustand aus dem switch raus und
als if vor das switch gezogen.
4. Problemfall überschneidene Zustände
state ist eine Variable, die nur einen Zustand aufnehmen kann. Jetzt
kann aber gleichzeitig die Situation vorliegen, dass man ein neues
Ergebnis der Feuchtemessung hat und gleichzeitig das Ergebnis der
Batteriemessung LOW_BAT. Vom Projekt her soll die Feuchte weiter
gemessen werden, aber die Warnleuchte Batterie niedrig soll zusätzlich
blitzen. Derzeit hat das Ergebnis der Batteriemessung Vorrang und das
Ergebnis der aktuellen Feuchtemessung wird verworfen, was zur Anzeige
eines nicht aktuellen und u.U. falschen Feuchtewertes führt, solange der
LOW_BAT Zustand anhält.
5. Das Setzen der LEDs
Vorsicht: Geschmackssache! Die Manipulation vieler LEDs in den case
Fällen hatte mich in dem alten Code von Thomas gestört, wo das Teil der
Feuchtemessung war. Die Variante das zentral in einer Funktion (oder in
der Timer-ISR) zu machen gefällt mir besser. Keine grosse Hürde.
6. power_down/sleep_cpu
Ich habe etwas Bauchweh, dass power_down und sleep_cpu getrennt wurden,
weil ich eine Gefahr darin sehe, dass sich bei der Weiterentwicklung
Code zwischen set_sleep_mode( SLEEP_MODE_PWR_DOWN ), "implizites sei()"
und sleep_cpu(); schmuggelt.
7. Aufwecken mit WAKEUP_vect statt INT0_vect
Für mich war in der Source nicht offensichtlich, weshalb diese Änderung
gemacht wurde. Das Nachlesen im Thread (Reaktion vor Loslassen möglich,
freiere Pinwahl) hat das dann erklärt.
8. CTC Modus beim Timer
Hier muss man sich auf einen anderen Timermodus einlassen. Keine grosse
Hürde.
Stefan B. schrieb:
> 1. Die Manipulation der Ports>> Dein Verfahren arbeitet mit den SBIT Makros.
Ich finde diese Schreibweise deutlich besser lesbar.
Hauptsächlich gefällt mir aber daran, daß ich nicht extra Byteadresse
und Bitnummer definieren muß.
> 2. Die Entprellung>> Deine> anscheinend bevorzugte Manipulation von Bits z.B. mit ^ ist für den> Anfänger anspruchsvoll.
Das EXOR ist hier notwendig, da die Entprellung auf einem Vertical
Counter basiert.
Er ist natürlich nicht einfach zu verstehen, aber jeder, der ihn
verstanden hat, ist froh darüber.
> 3. Das doppelte switch in main>
Das erste Switch steuert die Meßaktionen (Eingabe), das 2. die Anzeige
(Ausgabe). Die Trennung erfolgte der Übersichtlichkeit wegen.
> Vom Projekt her soll die Feuchte weiter> gemessen werden, aber die Warnleuchte Batterie niedrig soll zusätzlich> blitzen. Derzeit hat das Ergebnis der Batteriemessung Vorrang und das> Ergebnis der aktuellen Feuchtemessung wird verworfen, was zur Anzeige> eines nicht aktuellen und u.U. falschen Feuchtewertes führt, solange der> LOW_BAT Zustand anhält.
Daran sieht man, wie wichtig es ist, erstmal überhaupt die
Aufgabenstellung zu formulieren.
Ich hab daher aus dem Code heraus rückwärts die Aufgabenstellung
rauslesen müssen und dabei können Fehler passieren.
Anbei die Funktion eingebaut. Die low-Batt Funktion braucht dann auch
eine Hysterese.
> 5. Das Setzen der LEDs>> Vorsicht: Geschmackssache! Die Manipulation vieler LEDs in den case> Fällen hatte mich in dem alten Code von Thomas gestört, wo das Teil der> Feuchtemessung war. Die Variante das zentral in einer Funktion (oder in> der Timer-ISR) zu machen gefällt mir besser.
Die LEDs werden auch bei mir zentral gesteuert, aber im Main.
Durch die Bitschreibweise wird aber ersichtlicher, wann welche LED
leuchtet.
> 6. power_down/sleep_cpu>> Ich habe etwas Bauchweh, dass power_down und sleep_cpu getrennt wurden,> weil ich eine Gefahr darin sehe, dass sich bei der Weiterentwicklung> Code zwischen set_sleep_mode( SLEEP_MODE_PWR_DOWN ), "implizites sei()"> und sleep_cpu(); schmuggelt.
Es kann sich ruhig was zwischenschmuggeln, wenn der Code so geschrieben
ist, daß immer ein sicherer Zustand vorliegt.
Es wird einmal atomar der Power-Down-Modus und der Pin-Change-Interrupt
enabled und andererseits im Pin-Change-Interrupt der Idle-Modus enabled
und der Pin-Change disabled.
Der gefährliche Zustand, Power-Down enabled und Pin-Change disabled,
kann also nirgends auftreten.
Es wird außerdem nicht das gefährliche Macro sleep_mode(), sondern das
sichere Macro sleep_cpu() verwendet.
Der Code ist somit in der Ausführungsreihenfolge abgesichert.
Du kannst alle Funktionen im Main beliebig vertauschen, das Programm
funktioniert immer.
Ich hab auchmal bei Atmel nachgefragt, was die Bemerkung im Datenblatt
soll, auf der das sleep_mode() Macro basiert.
Es wurde mir bestätigt, daß es keinerlei Auswirkung hat, wann das
Enable-Bit gesetzt wird.
Es muß nur irgendwann vor dem Sleep sein, daher ist im Init-Code der
optimale Platz dafür.
Auch logisch betrachtet bringt es reinweg garnichts, wenn man das
Enable-Bit nach dem Sleep löscht, da es ja immer vor dem nächsten Sleep
wieder gesetzt wird. Das sleep_mode() Macro hat also keinerlei
praktischen Nutzen.
Peter
Guten Morgen!!
Da habe ich ja jetzt ziemliche Diskussionen losgetreten in meinem
Beitrag. Mir ist klar dass man sowas am besten in der Freizeit machen
sollte. Da kann man rumprobieren und testen usw. Ich habe registriert
dass der Code nicht das Optimum darstellt. Mir ist eigentlich nur
wichtig dass des so weit einigermaßen funktioniert. Klar ich würde es
auch sehr gerne perfekt machen allerdings habe ich ja schon zu Beginn
gesagt ich bin Anfänger. So schnell von 0 auf 100 ist wohl schwer
möglich noch dazu wenn es sich eigentlich um eine Technologiearbeit
handelt. Ich bin froh dass ich von euch diese Hilfe erhalten habe weil
ohne wäre es nicht gegangen. Anfangs habe ich ja mit einer halben Seite
Code gerechnet. Inzwischen ist es ja doch sehr umfangreich. Wohl mehr
als das 10fache weil man hald immer neue Ideen hat. Diese Ideen in
knapper Zeit zu verwirklichen ist dann wohl fast unmöglich. Mir wurde
beim programmieren ja auch gesagt "learning by doing"! Jetzt kommt ja
beim zeitlichen auch noch dazu dass ich die Arbeit schreiben muss und am
Do eine Vorlesung besuche. Jetzt wird die Sache natürlich noch
schwieriger.
Mir ist natürlich auch klar dass die Sache mit dem kapazitiven Sensor
bis Dezember nur noch schwer zu realisieren sein dürfte. Ich muss mich
da ja auch selber erst hineindenken. Die Hardware dafür war ja noch das
leichteste.
Wegen der Sache mit der Statemachine wollte ich mich nochmals
informieren. Dieses Ding hat ja einen ständig defnieriten Zustand. Habe
schon mit Informatikern gesprochen. Eine Statemachine kann man ja
irgendwo mit case in verbindung bringen. Heißt das ich habe in Teilen
eine oder gibt es da nur entweder ganz oder gar nicht?
Ich hoffe jedenfalls dass ich nach Dezember zum Ende meiner Arbeit die
Zeit finde in meiner Freizeit programmieren zu können. Auch dann werde
ich wohl noch suppport benötigen. Allerdings habe ich dann endlich mal
die Zeit die in meinen Augen benötige! Möchte dann ja auch gerne mit
JTAG Schnittstellen Erfahrungen sammeln. Genauso wie mit TI -
Controllern. Ursprünglich war ja geplant meinen Sensor mit einem MSP430
auszuwerten. Mechanische Gründe gaben schließlich den Ausschlag den
ATTINY zu benutzen! Bin aber inzwischen ganz froh mit meiner Wahl!
Bis Dezember werde ich mich hald noch so damit durchschlagen müssen. Das
wichtigste ist jedoch dass ich das Interesse am Programmieren gefunden
habe. Das ist wohl unbezahlbar. Ok mich reißt Programme schreiben nach
wie vor nicht total vom Hocker aber ich habe erkannt welche tolle Dinge
man damit machen kann.
Evt. schaffe ich am Wochenende ja die Software mit der Statemachine zu
testen.
Stefan:
Ich habe meine Software jetzt abgeändert. Vom Stromverbrauch im
Power-Down bin ich schon sehr angetan. Sprich Spannungsteiler auf
Portpin klappt wunderbar. Was mir jedoch auffällt ist dass meine
Feuchteanzeige träger ist. Wenn ich meinen Sensor anhauche blinkt
irgendwann die rote LED. Aber es dauert jetzt wesentlich länger bis
wieder der Grundzustand mit dem grünen LED eintritt. Du hast ja davon
gesprochen dass ich evt noch eine Verzögerung einbauen soll nach der
Aktivierung des Spg.teilers. Sprich dieser Effekt würde dann ja wohl
nochmal zusätzlich verstärkt werden oder? Ebenso gibt es noch Probleme
die rote LED mit 1Hz Blinkfrequenz einzusetzen. Sie blinkt immer noch
schneller obwohl ja die 250ms für rot keine Rolle mehr spielen dürften.
Eine weitere Frage. Code habe ich mir von einem Entwicklungsleiter einer
Software-Firma sagen lassen erklärt man mittels Struktugrammen. Auch ich
sollte das ja wohl so machen. Habe das ja auch schon mal gehört.
Zeichnet man sowas am geschicktesten in Power-Point? Jedes Unterprogramm
wird ja wohl eine Bubble darstellen. Bzw. if-Abfragen macht man ja mit
Rauten und Abzweigungen für true und false. Was macht man bei case?? Das
muss ich ja auch noch darstellen!
Gruß und sorry für die verspätete Antwort!
Thomas
Generell gefällt mir das Verfahren im Weck-Interrupt den Sleepmodus neu
für das Userprogramm zu setzen. Das werde ich in Zukunft auch so machen.
Nicht einig bin ich damit, dass es nichts ausmachen soll, wenn sich Code
zwischen das implizite sei (Abschluss der ATOMIC-Klammer) und das
sleep_cpu schmuggelt bzw. dass man die Funktionen im main beliebig
vertauschen kann.
Du hast insofern Recht, dass dein Verfahren die Zombies d.h. Pennen bei
rausgezogenem Stecker am Wecker verhindert.
Ich sehe aber den Haken, dass Userinput verloren gehen kann, d.h. dass
sich der µC beim Druck auf den EIN/AUS-Taster nicht Schlafen legt
sondern wach bleibt.
Der Fall würde eintreten, wenn der Weckinterrupt zur Laufzeit des
eingeschuggelten Codes aktiv wird. Das dann folgende sleep_cpu würde in
den Schlafmodus des Weckinterrupts (IDLE) gehen und nicht in den des
Userprogramms (POWER_DOWN).
Im Code von V3B habe ich nicht überprüft, welche Auswirkungen das hätte.
Also ob ein gedrückt halten des EIN/AUS-Tasters automatisch beim
nächsten Durchlauf ein POWER_DOWN auslöst, oder ob ein 2. Tastendruck
nötig ist oder gar ein 2. (Pseudo-Wecken) und ein 3. (neues AUS).
@ Thomas
[Spekulation]
Strom durch einen Widerstand ist immer auch eine Heizung. Wenn du auf
eine kältere Oberfläche hauchst, wird die Feuchte länger dort bleiben
als auf einer wärmeren Oberfläche. Du kannst zwei Tests machen:
1. "Vorwärmzeit" vor der Messung mit einer kleinen Wartezeit vor der
eigentlichen Messung.
2. Rückänderung des Codes: Spannungsversorgung für den Spannungsteiler
bleibt immer an, nur vor dem Schlafen wird sie ausgeschaltet und beim
Wecken an. Also so wie du es in Test_13.c hattest.
Ich würde zuerst 2. testen, um zu sehen, ob es überhaupt einen Effekt
gibt.
[/Spekulation]
Und ich würde prüfen, ob die Schwellwerte mit der neuen
Spannungsversorgung über PA7 (d.h. Vcc-X) noch die gleichen sind wie bei
der alten Versorgung (Vcc).
Dazu würde ich mich langsam um die Kalibrierung des Sensors kümmern,
weil ich nicht reproduzierbar hauchen kann ;-)
Das 2Hz Blinken der roten Feuchte-LED ist ja richtig so, denn in der
Source Test_13.c und Test_13a.c steht:
#define TOGGLE_ROT_1HZ 0
#define TOGGLE_ROT_2HZ 1
Ein Programm für Flussdiagramme wäre z.B. die Freeware Diagram Designer.
Die findet man auf Sourceforge, aber auf
http://logicnet.dk/DiagramDesigner/ sieht man auch Screenshots. Ich habe
allerdings keine praktische Erfahrung damit.
Struktogramme nach DIN 66261 sind was anderes
(http://wwwlrh.fh-bielefeld.de/IN_Prak/inprak6.htm). Programme für
Nassi-Shneiderman-Diagramme ("Struktogramme") sind bei
http://de.wikipedia.org/wiki/Nassi-Shneiderman-Diagramm genannt. Ich
habe allerdings keine praktische Erfahrung damit.
Stefan B. schrieb:
> Ich sehe aber den Haken, dass Userinput verloren gehen kann, d.h. dass> sich der µC beim Druck auf den EIN/AUS-Taster nicht Schlafen legt> sondern wach bleibt.
Ne, das ist ja gerade das geniale an einer Statemachine.
Man kann unterscheiden zwischen Aktionen, die einen State setzen und
welchen, die den State auswerten.
Das Powerdown wertet nur den State OFF aus, d.h. solange OFF ist, muß es
die CPU schlafen legen.
Es stört überhaupt nicht, wenn durch Preller die CPU z.B. 10-mal wieder
aufwacht. Nach einigen ms sind die Preller vorbei und die CPU bleibt
schlafen.
Erst die Entprellroutine kann beim nächsten Tastendruck den State in WET
ändern. Und erst dadurch hört die CPU auf, immer wieder in Power-down zu
gehen.
Probleme beim Power-Down entstehen hauptsächlich nur dann, wenn man das
Sleep/Wakeup mit dem Entprellen verwuselt.
Auch hier gilt deshalb: "Divide and Conquer".
Peter
Guten Morgen!
So jetzt komme ich endlich mal wieder dazu meine Software zu
begutachten. Also ich habe meinen Code jetzt wieder so verwendet wie in
Test13.c! Sieht aber so aus als ob das ganze Teil träger ist als wenn
ich direkt an VCC meinen Spannungsteiler habe. Könnte natürlich die
Schwellwerte ändern.
Die Kalibrierung des Sensors stellt für mich immer noch ein Hindernis
da. Ich hatte gehofft das rechnerisch zu bestimmen. Gestaltet sich aber
schwer. Ich habe eine Kennlinie bei der es heißt rel. Feuchte bei dem
Widerstand. Klar ich kann mit meinen Stufen des AD-Wandlers
zurückrechnen. Ich kann dann sagen was für eine Spannung anliegt am
Sensor. Ich könnte somit auch den Widerstand meines Sensors bestimmen.
Ist ja ne ganz einfache Spg.Teilerberechnung. Allerdings bin ich hald
immer noch unsicher weil ja quasi parallel zum Sensor die IC-Strecke
liegt. Der "Vorwiderstand" hat bei mir ja 1,5 MOhm. Am liebsten wäre mir
wenn man den Widerstand beim IC vernachlässigen könnte. Ansonsten ist
das ja eine parallelschaltung von dem Sensor und dem
Controllerwiderstand.
Mein rotese LED blinkt leider immer noch nicht mit 1Hz selbst wenn ich
es richtig define.
Kann ich dir evt. wenn ich mein Flussdiagramm habe dieses zur Kontrolle
schicken?
Gruß
Thomas
Willst du der "trägeren Messung" nachforschen? Wenn ja, siehe die
Überlegungen oben (Heizeffekt) plus diese Überlegungen zu der neuen
Versorgung:
Die Input-PA7-Versorgung unterscheidet sich auf Hardwareebene von der
Vcc-Versorgung durch den 20-50k Pull-Up Widerstand zwischen Vcc und dem
Anschluss deines Spannungsteilers sowie durch den Leckstrom in den
Eingang von PA7. Man könnte versuchen diese Situation bei der
Vcc-Versorgung nachzustellen indem ein weiterer Spannungsteiler
aufgebaut wird.
Du könntest als drittes die Variante testen, bei die Versorgung aus PA7
bezogen wird, wobei aber PA7 als Outputpin betrieben wird
(Output-PA7-Versorgung).
Eine Änderung der Schwellwerte hängt davon ab, was du messen willst bzw.
wie du überhaupt auf die Schwellwerte gekommen bist. Es werden definitiv
andere Spannungen am ADC anliegen, wenn entweder Vcc oder Vcc-X in den
Spannungsteiler reingehen. Und bei gleichbleibendem Aref=Vcc müssen
"hinten" andere Werte rauskommen.
Ich halte eine Kalibrierung für unverzichtbar. Das Berechnen aus der
Kennlinie im Datenblatt ist ungenau. Die Kennlinie im Datenblatt ist
eine typ. Angabe des Herstellers, wie sich die Sensoren typischerweise
verhalten. Die kann man benutzen, um die Schaltung zu dimensionieren,
aber nicht, um die Messwerte zu interpretieren.
Den konkreten Zusammenhang zwischen rel. Feuchte und Widerstandswert bei
deinem konkreten Sensorexemplar musst du bestimmen, wenn dir was an
Genauigkeit (Auflösung und Genauigkeit) liegt.
Im Moment stocherst du im Trüben. Könntest du ausschliessen, dass du bei
Vcc-Versorgung zwar eine flinkere Messung aber mit ungenauen
Feuchtewerten hast aber dass eine PA7-Versorgung träger ist aber genaue
Feuchtewerte liefert?
Dieses Dilema kannst du nur lösen, wenn du dem Messsystem Umgebungen mit
genau bekannten rel. Feuchten vorsetzt und dann eine eigene
Kalibrierkurve machst. Am "wenigsten" Arbeit hast du, wenn du die rel.
Feuchte bei den beiden Schwellwerten einstellen kannst.
Ein Verfahren zur Kalibrierung von Feuchtesensoren arbeitet mit
gesättigten Salzlösungen bei bestimmten Temperaturen:
http://www.d-r-h.de/hilfstabellen/klima_def_luftfeuchte.htmlhttp://www.umnicom.de/Elektronik/Sonstiges/Messtechnik/tmKap2/tmKap224/tmKap224.html
Das 2Hz-Blinken der roten Feuchte-LED kann ich aus der Betrachtung der
Source test_13a.c im Moment nicht nachvollziehen. Leider sind in der
Source alle Anpassungen für meinen Attiny2313 Hardwaremockup
verschwunden und ich müsste die erst wieder neu einbauen, um das auf
Hardwareebene zu debuggen.
Sei mir nicht böse, aber bitte schick mir kein Flussdiagramm. Das würde
deutlich die Hilfe zur Selbsthilfe übersteigen. Das ist essentieller
Bestandteil deiner Facharbeit und ich möchte mich da nicht einmischen.
Bastler schrieb:
> Die Kalibrierung des Sensors stellt für mich immer noch ein Hindernis> da. Ich hatte gehofft das rechnerisch zu bestimmen. Gestaltet sich aber> schwer. Ich habe eine Kennlinie bei der es heißt rel. Feuchte bei dem> Widerstand. Klar ich kann mit meinen Stufen des AD-Wandlers> zurückrechnen.
Wenn Du ne Kennlinie hast, würde ich die Schwellen danach einstellen und
testen.
Du kannst die ADC-Werte selber ausrechnen oder die Formen hinschreiben
und es den Compiler ausrechnen lassen.
Der Compiler rechnet gerne für Dich konstante Ausdrücke aus. Der
Übersichtlichkeit halber kann man das in mehreren Schritten mit Defines
machen. Man muß also keine Monsterformel hinschreiben.
> Der "Vorwiderstand" hat bei mir ja 1,5 MOhm.
In dem Fall kann man die Spannung zum Sensor nicht zwischen den
Messungen abschalten sondern nur im Power-Down.
Außerdem muß ein Kondensator 100nF an den ADC-Eingang, der liefert dann
genug Energie für die Sample&Hold-Stufe des ADC.
Peter
Guten Morgen!
Mir ist hald aufgefallen dass meine Sensoren unterschiedlich sind. Ich
habe ein und den gleichen Sensor bestellt nämlich den SHS-A2. Das
Keramikplättchen war bei den ersten um ca. 1mm schmäler. Auch die
Beschichtung sieht bisschen anders aus. Wenn ich den Sensor anhauche
scheint er auch anders zu reagieren. Ich muss meine Schwellwerte
wesentlich höher setzen damit ich eine Reaktion erzeugen kann. Habe
jetzt auch die Spg.versorgung erstmal wieder auf VCC gesetzt um dieses
Problem auszuschließen. Das mit den 20-50KOhm habe ich im Datenblatt
gelesen. Bei VCC = 3V. Ich weiss nicht ob das dann so funktionieren
wird. Als Referenz zählt ja immer noch meine VCC. Sagen wir mal 3V.
Allerdings dürfte es theoretisch nichts ausmachen. Mit meinem PA7 kann
ich dann ja nur die höheren Spannungen nicht "anfahren". Das würde mir
ja nichts ausmachen weil ich mit meinem 1,5 MOhm Widerstand ohnehin
dachte dass ich die Spannung am Sensor auf knapp 0,8V begrenzt habe.
Beim anhauchen scheint es allerdings so als ob der Sensor einen
Widerstand im MOhm Bereich erziehlt obwohl das Datenblatt einen
maximalen Widerstand von ca. 500000 Ohm angibt. Sehr ominös. Ich bin
natürlich auch kein Klimaspezialist. Bedeutet anhauchen einen so großen
Unterschied wie die eigentliche Betauung. Wenn ich das Teil auf
anhauchen einstelle dann reagiert er bei wirklichem Tau ja gar nicht
mehr. Mir wurde damals ja auch von Hygrosens Instrument bestätigt dass
ich den Sensor im Notfall mit 0,8 V Gleichspannung betreiben kann. Er
ist dann zwar ungenau aber des ist meine Messung ja wohl auch.
Naja jetzt mal zu deiner Mail:
Das mit der Überlegung als Output Pin ist ja interessant. Glaubst du das
geht??? Kann ich hierbei was zerstören? Also ne Treiberüberlastung ist
ja ausgeschlossen da ich ja glaube ich max. 20mA Strom ziehen darf. Das
würde wohl nie erreicht werden. Die Schwellwerte habe ich mir ungefähr
hingerechnet. Bzw. ich habe erst probiert und mir dann berechnet wieviel
mV die einzelnen Stufen sind. Mit dem ersten Sensor waren das 0,146 und
0,439 V. Ich habe das jetzt versucht auf die Kennlinie hinzurechnen.
Wenn ich sage dass mein AD Pin keinen Widerstand gegen Masse aufweißt
dann wären diese Stufen ungefähr im Bereich von 70 und 90% relative
Feuchte. Aber ist hald alles so ungefähr aber das wußte ich von Anfang
an und damit wäre ich ja grundsätzlich zufrieden. Hab ja kein Display wo
genau der Prozentwert stehn soll.
Was will ich? Ich möchte hald dass wenn man das Teil anhaucht die LEDs
dementsprechend was machen. Ich werde das mit der Betauung wohl sicher
nicht machen. Das wäre zu kompliziert. Da müßte man dann ja auch immer
ein Therarium zur Verfügung haben um die Bedingungen zu erzeugen. Also
fällt meiner Meinung nach so eine richtige Dimensionierung weg. Das ist
mir bewußt. Ich werde andere Werte haben wenn ich VCC und VCC über PA7
anliegen habe. Also bei dem ersten Sensor könnte ich dir sagen dass die
VCC Versorgung "besser" ist. Meine Spannungswerte passen mit den
Schwellenwerten zusammen. Und 70 und 90% rel Feuchte scheint mir auch
sehr annehmbar bei anhauchen. Der neue Sensor bereitet mir noch Probleme
aber ich werde später noch damit bisschen arbeiten.
Das mit dem Flussdiagramm ist voll in Ordnung. Verstehe ich. Kein
Problem.
Moment. Neue Info. Das mit dem Kondensator an den ADC Eingang. Du meinst
den 100nF parallel zum Sensor vom ADC Pin auf GND. Warum kann ich mit
dem 1,5MOhm Widerstand die Spannungen zwischen den Messungen nicht
abschalten. Hat das was mit dieser "Vorwärmzeit" zu tun weil der
Widerstand so groß ist??? Ich habe den Code auch wieder so verändert wie
du gemeint hast. Ich aktiviere den Spg.teiler bei der Feuchtemessung und
deaktiviere ihn wieder wenn das Gerät ausschaltet. Das wäre auch ok da
das Gerät eh nur immer kurz angeschaltet ist.
Sorry dass ich deine Softwareänderungen aus meinem Code entfernt habe
und du nochmal diese Arbeit investieren mußtest! War nicht meine
Absicht!
Gruß
Th.St.
Naja was heißt frei wählen. Das Teil wird unterwegs sein in der Zukunft.
Genaueres kann ich dazu nicht sagen. Unterwegs weiss man hald nicht was
man für Bedingungen vorfindet und so ist das Anhauchen die einfachste
Variante etwas zu testen. Ich weiss das hört sich langsam wohl ominös an
bei mir! ;-)
Hallo!!
Mal wieder ich mit Problemen!! Und zwar. Auf meinen inzwischen fertigen
Bauteilen muss ein Fehler sein. Am AVRISP MKII blinkt die orange LED.
DAs heißt ja laut manual reversed target cable connection. Also wohl
meine Belegung ist verdreht. Ich habe das aber jetzt ein paar mal
kontrolliert da kann eigentlich nichts falsch sein. Jetzt meine Fragen:
Könnte es am Widerstand liegen. Ich habe durch meine Technologie bedingt
Widerstände <20 Ohm vom ICP Stecker auf meinen Controller. Ist das ein
Problem? Ich habe am 10kOhm Reset Widerstand merkwürdigerweise 17 Ohm
wenn ich im eingebauten Zustand messe. Sehr merkwürdig auf meiner
Versuchsplatine ist das nicht. Dürfte aber auch keine Brücke da sein.
Wenn ich auf meiner Versuchsplatine Reset R brücke um das Problem zu
simulieren leuchtet mein LED nach wie vor grün. DAs verstehe ich jetzt
gar nicht. Womit kann sowas noch zusammenhängen?? Könnte ich da ein paar
Tips bekommen?? Was passiert z.B. wenn Miso, Mosi nicht angeschlossen
wären?? Wenn VCC oder GND in der LUft hängt dann leuchtet ja das rote
LED. Das ist nicht der Fall. Das heißt die beiden müssen passen und
zwischen beiden ist auch kein Kurzschluss.
Gruß
Th.
Bastler schrieb:
> Mal wieder ich mit Problemen!! Und zwar. Auf meinen inzwischen fertigen> Bauteilen muss ein Fehler sein. Am AVRISP MKII blinkt die orange LED.> DAs heißt ja laut manual reversed target cable connection. Also wohl> meine Belegung ist verdreht.
Sorry habe kein AVRISP MKII und quassele deshalb ab jetzt ins Blaue...
"Reversed target cable connection, OR NOT CORRECT PULL-UP ON THE RESET
LINE."
http://support.atmel.no/knowledgebase/avrstudiohelp/mergedProjects/AVRISPmkII/HTML_Source/Hardware_Description.htm> Ich habe das aber jetzt ein paar mal> kontrolliert da kann eigentlich nichts falsch sein. Jetzt meine Fragen:> Könnte es am Widerstand liegen. Ich habe durch meine Technologie bedingt> Widerstände <20 Ohm vom ICP Stecker auf meinen Controller. Ist das ein> Problem?
Ich vermute, du benutzt so was wie Leitkleber als Draht- und
Lötmittelersatz.
Denke nicht, dass die 20R hier ein Problem sind. Kannst du aber am
Prototypen prüfen, wenn du dort 20R Widerstände einschleifst. Du kannst
auch einen Serienaufbau "opfern" und 0R Drähtchen parallel zu den 20R
Verbindungen ziehen. Wird es dann besser?
> Ich habe am 10kOhm Reset Widerstand merkwürdigerweise 17 Ohm> wenn ich im eingebauten Zustand messe. Sehr merkwürdig auf meiner> Versuchsplatine ist das nicht.
Das ist eindeutig falsch bzw. die Situation "NOT CORRECT PULL-UP ON THE
RESET LINE." Der Pull-Up darf laut Atmel nicht kleiner 4K7 sein.
Kontrolliere mal, ob du unter dem Widerstand einen Kurzschluss gebaut
hast z.B. Leitkleber zusammengelaufen.
> Dürfte aber auch keine Brücke da sein.> Wenn ich auf meiner Versuchsplatine Reset R brücke um das Problem zu> simulieren leuchtet mein LED nach wie vor grün. DAs verstehe ich jetzt> gar nicht.
Ich auch nicht.
> Womit kann sowas noch zusammenhängen?? Könnte ich da ein paar> Tips bekommen?? Was passiert z.B. wenn Miso, Mosi nicht angeschlossen> wären??
Sorry, habe kein AVRISP MKII. Bei meinem STK200-Kompatiblen
ISP-Programmieradapter würde das ISP Programmierprogramm (AVRDUDE) den
µC nicht finden.
Hallo!
Danke für deine Tips. Ich bin jetzt schon weiter. Habe Kurzschlüsse
unter meinem Wannenstecker.
Jetzt noch paar Fragen.
Zum LED-Bat das blinkt wenn meine Batterie sich leert. Ich bemerke schon
dass das Lämpchen blinkt aber es ist so schwach wie nochmal was. Woran
könnte das liegen? Wenn ich ganz einfach in einem kleinen Programm
ansteuere leuchtet es ganz normal. Ebenso habe ich ein Problem mit
meinem Power-Down Taster. Habe alles durchgemessen. Der Taster zieht den
Pin auf GND. Also kein Kurzschluss oder was auch immer. Man merkt auch
dass die LEDs aus sind solange der Taster gedrückt ist. Er geht aber
nicht in den Schlafmodus. Ich glaube nicht dass das an der Entprellung
liegt weil alleine vom Zufallsprinzip müßte es hin und wieder gehen.
Siehe ja auch PRototyp. Habe auch sicherheitshalber nochmal das mit dem
delay ohne den Timer getestet auch das funktioniert nicht. Dass die LEDs
erlöschen zeigt dass der Taster auch wirklich am Pin hängt. 1Hz und 2Hz
blinken der Feuchte LEDs funktioniert. Mal wieder sehr ominös. Wenn
nichts gehen würde wäre es wenigstens eindeutig. Dachte erst wegen
meinem LED-BAt dass ich einen zu großen Übergangswiderstand habe. Das
scheint es aber auch nicht zu sein weil es ja normal leuchtet wenn ich
es ganz normal ansteuere. Da ist guter Rat teuer. Ich befürchte jetzt
mal dass du mir da auch nicht helfen kannst oder?
Wir verstehen uns richtig. Das ist ein Bauteil das programmierbar ist
nicht eines wo es am AVRISP orange blinkt...
Gruß
Thomas
Da bin ich ziemlich ratlos. Software kann man einigermaßen ferndebuggen;
Hardware eher schlecht.
Schwaches Leuchten einer LED kann verschiedene Ursachen haben.
Zu wenig Saft
Kann passieren, wenn der Vorwiderstand zu groß ist oder zum
Vorwiderstand andere Serienwiderstände hinzu kommen. Dieser Fall liegt
wohl nicht vor (Erfolgreicher Test mit LED-only Betrieb, wenn ansonsten
gleicher Aufbau UND Spannungsversorgung, d.h. fast leere Batterie)
Bei einem µC mit I/O Pins kann es auch daran liegen, dass die LED durch
einem Input-Pin versorgt wird statt mit einem Output-Pin. Ein Input-Pin
als Stromsenke ist hochohmig, d.h. es kann nur wenig Strom abgeleitet
werden. Der Input-Pin als Stromquelle setzt einen Pull-Up voraus. Die
sind i.a. auch hochohmig, d.h. nur wenig Strom steht zur Verfügung.
Diesen Fall kann ich mir auch nicht vorstellen, wenn du obiges Programm
benutzt hast.
Es gibt LEDs mit unterschiedlichem Durchlassstrom. Verwechselungen
passieren - Der Teufel ist ein Eichhörnchen und eine "normale" LED
braucht 10x mehr Saft als eine Low-Current-LED. Dieser Fall liegt wohl
nicht vor (Erfolgreicher Test mit LED-only Betrieb, wenn gleiche LED
getestet).
Zu selten Saft
Das kann der Fall sein, wenn die LED nicht statisch mit Strom versorgt
wird sondern mit einem periodischen AN/AUS Mechanismus. Je nach Dauer
der AN/AUS Phase ist das dann heller oder dunkeler. Diesen Fall kann ich
mir auch nicht vorstellen, wenn du obiges Programm benutzt hast und das
Serienmuster mit (annähernd) gleicher Taktfrequenz wie der Prototyp
läuft.
Bei dem Taster ist die Frage, ob der INT0-Eingang bei offenem Taster
auf einem LOW Pegel liegt (schlecht) oder ob ein sauberer HIGH Pegel
anliegt (gut). LOW heisst nicht gleich GND Potential (Datenblatt)!
Bastler schrieb:
> Zum LED-Bat das blinkt wenn meine Batterie sich leert. Ich bemerke schon> dass das Lämpchen blinkt aber es ist so schwach wie nochmal was.
Vermutlich schaltet Dein Programm schnell ein und aus.
Bewege mal die Platine mit der LED ganz schnell im dunklen Raum hin und
her, damit sieht man das Flackern (bis mehrere kHz).
> Er geht aber> nicht in den Schlafmodus. Ich glaube nicht dass das an der Entprellung> liegt weil alleine vom Zufallsprinzip müßte es hin und wieder gehen.
Ich kann nur wiederholen, mach erstmal die Funktion, d.h. die Taste
schaltet die LEDs ein/aus, ohne den CPU-Mode zu ändern!
Und erst, wenn das einwandfrei geht, kommt das Powerdown hinzu.
Zu versuchen, Powerdown und Funktion gleichzeitig zu programmieren,
bringt selbst nen Profi zum Schwitzen.
Peter