Hallo zusammen, ich bin ganz neu hier und auch blutiger Anfänger in C. Habe mir lange überlegt ob ich eure Hilfe in Anspruch nehme... Bitte zerreißt mich nicht gleich in der Luft ;-) Ich habe gegooglet, mir div. Tutorial angeschaut, ein teures Buch gekauft aber ich komme einfach nicht weiter. Die Aufgaben und Beispiele sind alle zu aufwendig und ich möchte doch nur etwas einfaches realisieren und vor allem verstehen. Ich habe ein aTeVaL (Microchip AVR Evaluationsboard) von ehajo Ich arbeite mit Atmel Studio 7 Im Board habe ich z.Zt. einen ATtiny2313A Wie in der Überschrift schon angedeutet habe ich mir ein (vermeintlich) einfaches Projekt für den Anfang vorgenommen: Es soll ein Modellleuchtturm beleuchtet werden. Modell: Westerhever Sand Was soll leuchten? Leuchtfeuer mit original Kennung 10 sek an, 1 sek aus, 1 sek an, 1 sek aus, 1 sek an, 1 sek aus Es gibt zwei Leuchtturmwärter Häuschen dort sollen jeweils zwei LEDs verbaut werden. Wohnzimmer und Bad Das Leuchtfeuer soll dauernd vor sich hin leuchten und die vier anderen LEDs sollen ein belebtes Haus simulieren. Wohnzimmer Licht an, ab und zu Licht im Bad an und wieder aus, dann Licht im Wohnzimmer auch aus. Das Leuchtfeuer habe ich zum Blinken gebracht habe aber keine Ahnung wie ich die anderen LEDs ansteuern soll, da ich eine Endlosschleife habe die nie endet. Wie löst man so etwas? Mit einem Timer? Wenn ja wie? Andere Lösungsansätze für mich? Bin für jede Hilfe dankbar! Viele Grüße Christian Hier mein bisheriger Code: /* * LED mit Kennung Westerhever Sand * 10 sek an 1 sek aus 1 sek an 1 sek aus 1 sek an 1 sek aus * AtmelStudio 7.0 * ATtiny2313A */ # #ifndef F_CPU #define F_CPU 1000000UL #endif #include <avr/io.h> #include <util/delay.h> //////////////////////////////////////////////////////////////////////// /////////////////////////// int main(void) { DDRD |= (1 << 6); // Port D Pin PC6 als Ausgang while (1) { // Beginn Schleife PORTD ^= (1 << 6); // flip state _delay_ms(10000); // delay 10 Sekunden an PORTD ^= (1 << 6); // flip state _delay_ms(1000); // delay 1 Sekunde aus PORTD ^= (1 << 6); // flip state _delay_ms(1000); // delay 1 Sekunde an PORTD ^= (1 << 6); // flip state _delay_ms(1000); // delay 1 Sekunde aus PORTD ^= (1 << 6); // flip state _delay_ms(1000); // delay 1 Sekunde an PORTD ^= (1 << 6); // flip state _delay_ms(1000); // delay 1 Sekunde aus } return(0); }
Gast
#5172969
> Wie löst man so etwas? Du willst im Grunde genommen mehrere Leuchtmuster parallel abarbeiten. Ein für µC gangiger Lösungsansatz dazu ist der Zustandsautomat. Lies mal die ersten Absätze von http://stefanfrings.de/net_io/protosockets.html dann siehst du, was ich damit meine. In meinem Buch http://stefanfrings.de/mikrocontroller_buch/index.html Band 3 findest du ein paar konkrete Anwendungsbeispiele. Achte dabei mal darauf, wie ich Enumerations für die switch() Anweisungen verwendet habe.
Danke für die schnelle Antwort! Noch mehr zu lesen für mich ;-) Sieht aber für mich als Anfänger auf den ersten Blick sehr aufwendig aus und ich verstehe nur Bahnhof... Werde das mal alles durcharbeiten und auf mich wirken lassen. Wenn jemand noch einen Beispiel-Code für mich hat, wie so etwas aussehen könnte, wäre ich nicht abgeneigt. Mit einem Beispiel fällt mir das Verstehen leichter. Ich dachte man arbeitet in Blöcken: LED1 soll dies machen LED2 soll das machen.... Oder mit mehreren Dateien. Dem ist wohl nicht so :-/
Christian S. schrieb: > habe aber keine Ahnung wie ich die anderen LEDs ansteuern soll, > da ich eine Endlosschleife habe die nie endet. Offenkundig ist _delay die falsche Wahl. Eine Schleife, die die Sekunden zählt
1 | |
2 | |
3 | |
4 | |
kann bei jedem Durchlauf das ein- oder ausschalten, was als nächstes kommt:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
da Zimmerbeluchtungen eher minutenweise gehen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
Gast
#5173001
> Ich dachte man arbeitet in Blöcken: Ja eben. Für jede LED schreibst du einen Zustandsautomaten (also ein switch() Konstrukt). In der Hauptschleife führst du dann beide quasi parallel aus. > Dem ist wohl nicht so :-/ Doch.
Hast du ein Bild von deinem Leuchtturm?
Gast
#5173005
Ich finde den völlig anderen Lösungsansatz von Michael Bertrandt interessant. Da hat er praktisch eine mehrkanalige Zeitschaltuhr (https://www.bauhaus.info/zeitschaltuhren/voltomat-tages-zeitschaltuhr-/p/12149433?) konstruiert. Das ist schön einfach.
Gast
#5173009
Michaels Ansatz kann man nehmen, aber es wäre 'professioneller', das Delay durch einen Timer zu ersetzen. Im Interrupt setzt du ein Flag und wartest in der Hauptschleife, bis das Flag gesetzt ist. Etwa so
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
In dem Beispiel ist das kein großer Unterschied, aber wenn der Code länger wird, wird mit Delay auch die Zeit zwischen den Durchläufen länger. Mit dem Timer hast du immer das gleiche Intervall.
Also erst mal vielen lieben Dank für eure Hilfe! :-) Bilder gibts leider noch nicht... Habe jetzt mal probiert das zusammen zu bekommen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
Geht leider nicht. Was habe ich falsch gemacht? Fehlermeldungen siehe screenshot PS der Code wird nicht länger werden und wenn es geht auch in einen tiny13A passen
Gast
#5173022
Bei DDRD |= LED_Bad | LED2_WZ | LED3_LT fehlt das ; DDRD |= LED_Bad | LED2_WZ | LED3_LT;
Gast
#5173031
Christian S. schrieb: > Fehler_Code.jpg Der Fehler ist (fast) immer bei der niedrigsten Zeilennummer. Der angezeigte Fehlertext ist doch eindeutig! Selbst besser schauen. Gruss
Geht! Nur noch zwei Warnungen. Vielen, vielen Dank! :-) Ich werde jetzt mal selbst weiter testen und probieren und mich wieder melden.
Christian S. schrieb: > PS der Code wird nicht länger werden und wenn es geht auch in einen > tiny13A passen Der Code schon, aber nicht die Daten. Allein die 3 Arrays sind schon 80 Byte, die du irgendwie in 64 Byte RAM stapeln musst. Sieh dir im Tutorial an, wie man Konstanten im Flash ablegt und wie man darauf zugreift. Ob alles in die 1K reinpasst, ist eine andere Frage. Die Tiny 25/45/85 sind pinkompatibel zum Tiny 13. Mit denen hättest du wesentlich meht Luft nach oben.
Danke Thomas. An diese Dinge hatte ich gar nicht gedacht. Bin eben noch ganz am Anfang. Habe heute von euch mehr, für dieses Projekt, gelernt als in der letzen Woche in der ich Bücher gelesen und Tutorial angeschaut und gelesen habe.
So da bin ich schon wieder... Dachte es geht alles habe aber festgestellt dass etwas nicht stimmt mit PD4 und 5. Also habe ich den Code angepasst und nun sollten PD4 und 5 abwechselt an und aus sein... Aber PD5 ist immer an und PD4 nach 3x an und 2x aus also 5 Minuten dauernd an. Oh eben ist PD5 nach 10 Minuten doch mal aus gegangen. Jetzt leuchten wieder PD4 und 5 dauerhaft. PD6 blinkt wie es soll. Also irgendwo ist da noch der Wurm drin!? Außerdem ist 1 Minute keine Minute sondern eher 44 Sekunden. Takt Controller? Wo korrigieren?
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
Christian S. schrieb: > festgestellt dass etwas nicht stimmt Sagte schon Thomas, der Speicher reicht wohl nicht, weil die an/aus bits recht grosszügig deklariert wurden.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
Gast
#5173185
... jetzt noch die erste Zeile in main ändern in
1 | |
und der Compiler ist völlig zufrieden.
Gast
#5173240
Christian S. schrieb: > Modell: Westerhever Sand > Was soll leuchten? > Leuchtfeuer mit original Kennung 10 sek an, 1 sek aus, 1 sek an, 1 sek > aus, 1 sek an, 1 sek aus Die originale Kennung des Leuchtfeuers Westerhever Sand lautet: Oc(3) WRG 15s [(1)+2+(1)+2(1)+8 s]
Gast
#5173272
light_house schrieb: > Oc(3) WRG 15s [(1)+2+(1)+2(1)+8 s] Vielleicht könntest du das auch für eine Landratte und einen Nicht-Funkamteur in eine verständliche Form bringen?
Danke light_house das stimmt natürlich. Weiß nicht was ich da gedacht hatte. Ist wohl alles ein bisschen viel auf einmal ;-) Danke für den Hinweis. 1 Sek dunkel 2 Sek hell 1 Sek dunkel 2 Sek hell 1 Sek dunkel 8 Sek hell = 15 Sekunden
Gast
#5173292
> Vielleicht könntest du das auch für eine Landratte und einen > Nicht-Funkamteur in eine verständliche Form bringen? > Oc(3) WRG 15s [(1)+2+(1)+2(1)+8 s] Licht: 1s(aus) - 2s(ein) - 1s(aus) - 2s(ein) - 1s(aus) - 8s(ein) NB Info für Nicht-Funkamateure: dies ist kein Morsecode
Noch ein Ergebnis für heute: Ich habe PD4 und 5 getauscht und jetzt scheint alles so abzulaufen wie gewünscht. Erklärungen für dieses Phänomen? Vorher (LEDs schalten willkürlich bzw. mir nicht erklärbar):
1 | |
2 | |
3 | |
Nachher (LEDs schalten wie gewünscht):
1 | |
2 | |
3 | |
Noch etwas ist mir aufgefallen: Vorher Speicher zu 68% belegt. Nachher zu 59% belegt. ????????Komisch????????
Gast
#5173418
@ light_house: Danke!
Christian S. schrieb: > Vorher Speicher zu 68% belegt. Hier denkt der Compiler beim Optimieren, ok Bad und Wohnzimmer sind getrennt > Nachher zu 59% belegt. Hier denkt er ah ich kann optimieren und ein Wohn-Klo draus machen :-D > > ????????Komisch???????? Lass' Dich von meinem Spaß nicht verwirren, kann es auch nicht erklären
Hi Hatte vorhin, beim überfliegen der ersten Posts, den Gedanken, ob man ein Array nicht auch als boolean (statt byte/int/char/whatever) erzeugen kann - dann müsste der Compiler halt 8 dieser Werte zu einen Byte zusammen schustern und irgendwo in den Tiefen des RAM/Flash unter bringen. (im Endeffekt das Gleiche, wie 'laberkopp' Es schon in Seinem Code angepasst hatte) Wobei man ggf. auch einfach die 64 (bei Sekunden wohl nur 60) Bit als binäre Zahl angeben könnte - wobei hier dann das Auszählen wieder fehleranfällig wird. MfG
Gast
#5173615
Patrick J. schrieb: > Hatte vorhin, beim überfliegen der ersten Posts, den Gedanken, ob man > ein Array nicht auch als boolean (statt byte/int/char/whatever) erzeugen > kann - dann müsste der Compiler halt 8 dieser Werte zu einen Byte > zusammen schustern und irgendwo in den Tiefen des RAM/Flash unter > bringen. Man kann es auch als verkettete Liste mit Texten "Ein" und "Aus" ablegen. Einfacher wäre es aber wohl, das Muster einfach Bitweise in ein uint16_t zu packen. Die Kennung ist 15s lang und passt dort wunderbar rein, wenn jedes Bit 1s repräsentiert. Zusätzlich braucht man einen Zähler, der immer von 0 bis 14 zählt. HildeK schrieb: > Vielleicht könntest du das auch für eine Landratte und einen > Nicht-Funkamteur in eine verständliche Form bringen? Das hat mit Funken überhaupt nichts zu tun: Oc(3) heißt "Unterbrochen Gruppe 3" (oc (en) =occulted), d.h. 3 Unterbrechungen hintereinander. Die Zeiten in Klammern sind die Dunkelphasen, die Zeiten ohne Klammer die Hellphasen, also wie oben schon genannt Westerhever Sand
1 | |
2 | |
http://www.deutsche-leuchtfeuer.de/nordsee/westerheversand.html
LFV schrieb: > Zusätzlich braucht man einen Zähler, der immer von 0 bis 14 zählt Nein, dazu braucht man eine Maske. Die startet mit 1 und dieses Bit wird nach jeder Sekunde um 1 nach links geschoben. Die verknüpft man dann mit dem Ausgabemuster und schaltet den Pin entsprechend. Dann muß das Delay raus. Nicht, weil es sich so gehört, sondern damit die LED im Leuchtturm nicht hart blinkt, wie eine LED nun mal blinkt, sondern mit Fading, wie bei einem richtigen Leuchtturm. Und dafür braucht man einen Timer, der die PWM und das ganze Timing macht. Das soll natürlich auf einen Tiny13. Mal grob geschätzt: Passt locker.
Christian S. schrieb: > Vorher (LEDs schalten willkürlich bzw. mir nicht erklärbar):
1 | |
2 | |
3 | |
> Nachher (LEDs schalten wie gewünscht):1 | |
2 | |
3 | |
oder wie's eigentlich gedacht war
1 | |
2 | |
Gast
#5173675
>> Vielleicht könntest du das auch für eine Landratte und einen >> Nicht-Funkamteur in eine verständliche Form bringen? > Das hat mit Funken überhaupt nichts zu tun: Nur der Vollständigkeit halber: Eher selten strahlen Leuchtürme aber auch im Morse-Code ab. Eine typische Kennung lautet dann beispielsweise: Mo (V) Mo Hinweis auf Morse-Code V Buchstabe V (Punkt – Punkt – Punkt – Strich) Hierbei gilt für das jeweilige Morsezeichen: n Länge eines Punktes n Länge der Pause zwischen Punkt/Strich 3n Länge eines Striches Beim Leuchfeuer Westerhever Sand liegt schon deshalb kein Morse-Code vor, weil der Blinkrhythmus nicht nach diesem Zeitplan gestaltet ist.
Danke für eure Anregungen den Code weiter zu verbessern oder das mit dem fading klingt auch interessant. Ich bitte euch aber nicht zu vergessen, dass ich das Board erst seit einer Woche und ich somit wirklich noch null Ahnung habe. Wenn ihr Lust habt, könnt ihr euch ja gern daran austoben. Damit ich es aber verstehe und nachvollziehen kann wäre es nett wenn ihr mir dann den kompletten Code postet und etwas //kommentiert. Es muss übrigens nicht auf einen tiny passen ich hätte auch noch ATMega8A-PU da, der dürfte ausreichend sein ;-) Nur nicht noch größer, es handelt sich um ein Spur N Modell. Wenn das Projekt fertig ist möchte ich es auch hier im Forum mit Bildern posten und den Code natürlich für alle zugänglich machen... Noch mal vielen Dank für eure Unterstützung!
Gast
#5173822
Thomas E. schrieb: > Nein, dazu braucht man eine Maske. Die startet mit 1 und dieses Bit wird > nach jeder Sekunde um 1 nach links geschoben. Die verknüpft man dann mit > dem Ausgabemuster und schaltet den Pin entsprechend. Was heißt "nein"? Ob du nun deiner Maske auf die Finger guckst oder das ganze Pattern verschiebst und immer das unterste Bit beguckst ist nun ziemlich egal. Wenn man bei der Maskenmethode nicht mit 1 startet, sondern mit 2^14 und dann nicht nach links, sondern nach rechts schiebt, weiß man gleich, wann man wieder von vorne anfangen muss - nämlich wenn 0 in der Maske steht.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
