Guten Tag, ich bin wie viele hier noch relativ grün hinter den Ohren was die Microcontrollerprogrammierung angeht, deshalb hoffe ich ihr könnt mir helfen. Mein momentanes vorhaben ist eine "Useless Box" zu bauen. Vielleicht sagt das dem ein oder anderen etwas. Auf Youtube gibt es die unterschiedlichsten Versionen. Nachdem ich mich für einen entschieden hatte habe ich gleich mal den Ersteller des Videos angeschrieben wegen Bildern, Schaltplänen usw.. Die hatt er mir dann auch zu genüge geschickt und was mich am meisten überrascht hat, auch das Programm welches er nach eigenen angaben in Arduino programmiert hatte. So viel zu der Hintergrundgeschichte. Nun zum eigentlichen Problem. Ich habe das oben genannte Programm so wie von ihm geschickt in Arduino übertragen doch bei der Überprüfung treten einige Fehler auf mit denen ich nicht so recht klar kommen. Ich habe einen Screenshot im Anhang der hoffentlich zeigt was ich meine. Es wäre super wenn ihr mir helfen könntet und ich bedanke mich schon einmal für eure Mühen.
:
Verschoben durch User
Hallo Ohne die ganze Ausgabe der Konsole unten ist es geraten, aber meine Glaskugel sagt mir das dir die vom Programm benötigte Servo Library fehlt oder nicht gefunden wird. da1l6
Peter Wagner schrieb: > Es wäre super wenn ihr mir helfen könntet und ich bedanke mich schon > einmal für eure Mühen. Die Zahlen vor ": error:" sind Zeilennummern. Da sollte man einen Blick riskieren.
Das mit der Servo Library könnte durchaus einige Probleme beheben. Danke schon mal. Deine Glaskugel scheint echt weise zu sein ;). Und ebenfalls danke für den Tipp mit den Zeilen das ist mit Sicherheit auch noch hilfreich.
Anbei habe ich noch ein Bild aller aufgelisteten Fehler. Das mit dem Semikolon war aufjedenfall einer davon. Danke Markus. Anscheinend hat er noch irgendwie Schwierigkeiten mit den Interrupt Befehlen von EICRA und EIMSK
Hi >Anscheinend hat er >noch irgendwie Schwierigkeiten mit den Interrupt Befehlen von EICRA und >EIMSK Wahrscheinlich fehlen generell dir Definitionen für die Controllerregister. Gibt es in C dafür nicht das #include <avr/io.h> MfG Spess
spess53 schrieb: > Gibt es in C dafür nicht das > > #include <avr/io.h> Bei Arduino ist sowas nicht nötig, die IDE hängt da automatisch noch Includes mit rein. Arduino ist (wie man hier wieder sehr toll sieht) nicht für Programmierer oder Leute, die mehr wollen, als die IDE ermöglicht, geeignet, da das notwendige Hintergrundverständnis absolut garnicht aufgebaut wird. Im konkreten Fall sehe ich das Problem unten im Tray: Da ist ein Mega8 ausgewählt - der hat kein EICRA Register. Sicher, dass das der im Original verwendete Controller ist?
Matthias Larisch schrieb: > Im konkreten Fall sehe ich das Problem unten im Tray: Da ist ein Mega8 > ausgewählt - der hat kein EICRA Register. Sicher, dass das der im > Original verwendete Controller ist? Ist mir gar nicht aufgefallen. Nein der im original verwendete Controller ist ein atmega328. Allerdings ändert sich auch nichts wenn ich das im Programm umstelle.
Wie wärs mit dem kompletten Source-Code? Dann könnte man mehr sehen, als nur mit so Screenshot-Schnipsel.
ich hoffe das sprengt jetzt nicht den rahmen aber hier: #include <Servo.h> #include <avr/sleep.h> Servo myservo2; //erstellt ein servoobjekt um einen servo zu kontrollieren Servo myservo1; int pos = 0; //variable um die servoposition zu speichern int boxoff = 1; // vordefinierte positionen für einen speziellen servo int S1fra = 1400; //von S1=Servo 1 int S1mid = 1800; //Mitte int S1mid2 = 1580; int S1mid3 = 1640; int S1til = 2050; int S2fra = 1784; //von S2=Servo 2 int S2mid = 1200; int S2mid2 = 1000; //fast an Schalter int S2til = 770; int seq = 0; void setup() { myservo2.attach(13); // servo an pin 13 zum servoobejekt(PB5) myservo1.attach(12); // servo an pin 12 zum servoobejekt(PB4) pinMode(8, OUTPUT); // für den MOSFET pinMode(2, INPUT); // Schalterunterbrechung digitalWrite(2, HIGH); myservo2.write(S2fra); myservo1.write(S1fra); delay(600); digitalWrite(8, HIGH); delay(300); digitalWrite(8, LOW); //alle unbenutzen Pins auf high setzten um energie zu sparen pinMode(3, INPUT); digitalWrite(3, HIGH); pinMode(4, INPUT); digitalWrite(4, HIGH); pinMode(5, INPUT); digitalWrite(5, HIGH); pinMode(6, INPUT); digitalWrite(6, HIGH); pinMode(7, INPUT); digitalWrite(7, HIGH); pinMode(8, INPUT); digitalWrite(8, HIGH); pinMode(9, INPUT); digitalWrite(9, HIGH); pinMode(10, INPUT); digitalWrite(10, HIGH); pinMode(11, INPUT); digitalWrite(11, HIGH); DDRC = 0; //Analogeingang 1/6 (Port C) ebenfalls auf high setzten PORTC = 63; //Externe Unterbrechung INT0 EICRA = 0; // das low signal von INT0 generiert eine Unterbrechungsanfrage EIMSK = 1; // externe Unterbrechung benötigt 0 freigabe } void loop() { if boxoff { delay(500); digitalWrite(8, HIGH); //seq = int(random(0,10); //falls random erwünscht if(seq == 0)Sequense3(); if(seq == 1)Sequense1(); if(seq == 2)Sequense3(); if(seq == 3)Sequense9(); if(seq == 4)Sequense3(); if(seq == 5)Sequense5(); if(seq == 6)Sequense3(); if(seq == 7)Sequense7(); if(seq == 8)Sequense3(); if(seq == 9)Sequense2(); if(seq == 10)Sequense3(); if(seq == 11)Sequense10(); if(seq == 12)Sequense3(); if(seq == 13)Sequense8(); if(seq == 14)Sequense3(); if(seq == 15)Sequense6(); if(seq == 16)Sequense3(); if(seq == 17)Sequense4(); seq++; if(seq>17) seq=0; delay(100); digitalWrite(8, LOW); boxoff=digitalRead(2); } else { //Aktiviert Schlafmodus, schaltet den MOSFET und die Servos ab set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); pinMode(12, INPUT); digitalWrite(12, HIGH); pinMode(13, INPUT); digitalWrite(13, HIGH); PRR=255; MCUCR|=(1<<BODS)|(1<<BODSE); MCUCR&=~(1<<BODSE); EIMSK=1; sleep_mode(); //Zzzzz sleep_disable(); //wieder aufwachen PRR=0; pinMode(12, OUTPUT); pinMode(13, OUTPUT); } boxoff=digitalRead(2); //Pin 2 ist LOW, Box ist ein and Boxoff=false } ISR(INT0_vect); //Schritt steigende Flanke unterbrochen. schalter getauscht { EIMSK=0; //Ausschaltunterbrechung boxoff=digitalRead(2); //Fragt den Schalter öfters ab um böse Überraschungen zu vermeiden boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); boxoff=digitalRead(2); } void Sequense1(); { delay(700) Sweep(1, S1fra, S1mid, 3000); delay(1000); Sweep(1, S1mid, S1fra, 500); delay(1000); Sweep(1, S1fra, S1til, 1000); Sweep(2, S2fra, S2mid, 1800); Sweep(2, S2mid, S2til, 500); delay(100) Sweep(2, S2til, S2fra, 500); Sweep(1, S1til, S1fra, 500); } void Sequense2() { delay(800) Sweep(1, S1fra, S1mid, 3000); Sweep(1, S1mid2, S1mid3, 1); delay(120); Sweep(1, S1mid3, S1mid2, 1); delay(120) Sweep(1, S1mid2, S1mid3, 1); delay(120) Sweep(1, S1mid3, S1mid2, 1); delay(120); Sweep(1, S1mid2, S1mid3, 1); delay(120); Sweep(1, S1mid3, S1mid2, 1); delay(120); Sweep(1, S1mid2, S1fra, 3000); Sweep(1, S1fra, S1mid, 3000); delay(1000); Sweep(1, S1mid, S1til, 1000); Sweep(2, S2fra, S2mid, 1800); Sweep(2, S2mid, S2til, 500); delay(100); Sweep(2, S2til, S2fra, 500); Sweep(1, S1til, S1fra, 500); } void Sequense3() { delay(50); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense4() { delay(500); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2mid, 1); delay(450); Sweep(2, S2mid2, S2til, 3000); delay(1); Sweep(2, S2til, S2fra, 1); // Fra=From(Von), Til=To(Zu) void Sweep(int srv, int fra, int til, int usec) { if(srv == 1) { if(fra <= til) for(pos = fra; pos < til; pos += 1) { myservo1.writeMicroseconds(pos); delayMicroseconds(usec); } else { for(pos = fra; pos >= til; pos -=1) { myservo1.writeMicroseconds(pos); delayMicroseconds(usec); } } } if(srv == 2) { if(fra <= til) for(pos = fra; pos < til; pos += 1) { myservo2.writeMicroseconds(pos); delayMicroseconds(usec); } else { for(pos = fra; pos >=til; pos -=1) { myservo2.writeMicroseconds(pos); delayMicroseconds(usec); } } } } delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense5() { delay(1000); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(2, S2til, S2mid2, 1); delay(110); Sweep(2, S2mid2, S2til, 1); delay(110); Sweep(2, S2til, S2mid2, 1); delay(110); Sweep(2, S2mid2, S2til, 1); delay(110); Sweep(2, S2til, S2mid2, 1); delay(110); Sweep(2, S2mid2, S2til, 1); delay(110); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense6() { delay(1500); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(1, S1til, S1fra, 1000); delay(2000); Sweep(1, S1fra, S1til, 1000); delay(2000); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense7() { delay(500); Sweep(1, S1fra, S1mid, 1); delay(200); Sweep(1, S1mid, S1mid2, 1); delay(100); Sweep(1, S1mid2, S1mid, 1); delay(100); Sweep(1, S1mid, S1mid2, 1); delay(100); Sweep(1, S1mid2, S1 mid, 1); delay(100); Sweep(1, S1mid, S1fra, 1); delay(200); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense8() { delay(200); Sweep(1, S1fra, S1mid, 1); delay(200); Sweep(1, S1mid, S1mid2, 1); delay(100); Sweep(1, S1mid2, S1mid, 1); delay(100); Sweep(1, S1mid, S1mid2, 1); delay(100); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1fra, 1); delay(200); Sweep(1, S1fra, S1til, 1); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense9() { delay(1000); Sweep(1, S1fra, S1mid, 2000); delay(500); Sweep(1, S1mid, S1mid2, 1000); delay(1); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid2, S1mid3, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(50); Sweep(1, S1mid3, S1mid2, 1); delay(500); Sweep(1, S1mid2, S1mid, 5000); delay(1); Sweep(1, S1mid, S1til, 1000); delay(1); Sweep(2, S2fra, S2til, 1); delay(450); Sweep(2, S2til, S2fra, 1); delay(200); Sweep(1, S1til, S1fra, 1); delay(400); } void Sequense10() { delay(800); Sweep(1, S1fra, S1til, 30000); delay(1); Sweep(2, S2fra, S2til, 3000); delay(1); Sweep(2, S2til, S2fra, 3000); delay(1); Sweep(1, S1til, S1mid, 30000); delay(1); Sweep(1, S1mid, S1fra, 1); delay(300); }
Peter Wagner schrieb: > Nein der im original verwendete > Controller ist ein atmega328. Allerdings ändert sich auch nichts wenn > ich das im Programm umstelle. Durch das Umstellen auf das richtig Board lässt sich zumindest diese Fehlerquelle ausschließen. Peter Wagner schrieb: > void Sequense1(); Dort muss das Semikolon entfernt werden.
Peter Wagner schrieb: > ich hoffe das sprengt jetzt nicht den rahmen aber hier: Es gäbe auch noch die Möglichkeit den Code als Anhang anzuhängen, wenn er so lang ist. Die entscheidenden kurzen Ausschnitte kannst schon hier posten, aber so wird es unübersichtlich. Bei den Fehlermeldungen solltest die Zeilen immer von oben nach unten abarbeiten. Als nächstes ist falsch:
1 | if boxoff |
Peter Wagner schrieb: > Da muss das boxoff in Klammer stehen oder? Ja mindestens. Was sagt http://arduino.cc/de/Reference/If ? Im Ernst, es bringt dir nichts, wenn dir hier alles genau vorgekaut wird. Überlege, schaue in der Referenz nach, korrigere es, kompiliere erneut (das ist immer noch kostenlos). Step by Step.
Markus schrieb: > Im Ernst, es bringt dir nichts, wenn dir hier alles genau vorgekaut > wird. Das ist mir schon klar. Das Problem ist einfach das mir die "Fehlermeldungen" vom Programm nicht wirklich etwas sagen und entsprechende Erklärungen habe ich bisher auch nicht wirklich gefunden
Vor allem den Sweep Befehl kennt das Programm wohl nicht und auch Google findet nicht wirklich etwas dazu
Peter Wagner schrieb: > Das Problem ist einfach das mir die > "Fehlermeldungen" vom Programm nicht wirklich etwas sagen und > entsprechende Erklärungen habe ich bisher auch nicht wirklich gefunden Das von Dir gepostete Programm enthält diverse syntaktische Fehler und ist alleine schon deshalb nicht kompilierbar. Außerdem sehen Teile des Quellcodes anderweitig verhackstückt aus, z.B. ist die Funktion "void Sweep(int srv, int fra, int til, int usec)" in den Code einer anderen Funktion hinein verschachtelt, was nicht sein darf. Ist das der Originalcode, den Du genau so erhalten hast? Oder hast Du daran selbst irgendwas durcheinander gequirlt? So wie von Dir gepostet, kann der Code jedenfalls nicht kompiliert werden, für kein Arduino-Board.
Nein das ist der original code den ich so erhalten habe. deshalb wundert es mich das dieser code so viele probleme bereitet den ich denke der typ der diese box gebaut und programmiert hat muss doch etwas anhung in der materie haben?
Peter Wagner schrieb: > Nein das ist der original code den ich so erhalten habe. deshalb wundert > es mich das dieser code so viele probleme bereitet den ich denke der typ > der diese box gebaut und programmiert hat muss doch etwas anhung in der > materie haben? Wie Jürgen S. schon schrieb, konnte der Code sicher nie funktionieren. Der ist das ja echt grauselig. Wurde der Code etwa abgetippt? Nach ein paar weiteren Korrekturen von Syntaxfehlern sowie dem Freistellen der Funktion Sweep() lässt er sich nun zumindest kompilieren. Hab aber keine Ahnung, ob das auch funktionell hinhaut.
Ganz herzlichen Dank für deine Mühen und natürlich auch für die Hilfe und Beiträge der anderen. Hätte nie gedacht das in diesem eigentlich fertigen Code so viele Fehler waren. Ich berichte gerne ob das Programm dann funktioniert wenn die "hardware" aufgebaut ist. Allerdings rein aus Interesse was hat es mit dem von dir beschriebenen "Freistellen" der Funktion Sweep auf sich?
Peter Wagner schrieb: > was hat es mit dem von dir beschriebenen "Freistellen" der > Funktion Sweep auf sich? Die Funktion "void Sweep(int srv, int fra, int til, int usec)" war innerhalb der Funktion "void Sequense4()" versteckt (verschachtelt). Darum war Sweep() auch nicht auffindbar beim kompilieren. Jetzt ist sie eigenständig. Ich würde mir das aber zweimal gut überlegen, ob du das ganze Projekt auf dieser Codebasis aufbauen willst. Oder ob du nicht besser eine andere, bessere Quelle nimmst. Oder du beginnst es gleich selber von Anfang an neu zu schreiben. Denn mit all diesen Fehlern aus dieser Quelle, ist leider fast anzunehmen, dass auch funktional noch einiges im Argen liegt. Nur, dass du gewarnt bist, wenn es dann nicht läuft.
Ok danke für die Erklärung. Macht durchaus Sinn. Eine andere Quelle gibt es so mit sicherheit nicht, allerdings funktionierte das Programm in seinem Video ansonsten wäre ich gar nicht darauf gekommen. Mal schauen was daraus wird. Für die Sache mit dem selber schreiben bin ich wohl noch etwas zu grün hinter den ohren obwohl ich mich schon etwas in dir Thematik eingelesen habe. Und wie gesagt nochmals vielen Dank für eure Hilfe.
Peter Wagner schrieb: > Ok danke für die Erklärung. Macht durchaus Sinn. Eine andere Quelle gibt > es so mit sicherheit nicht, allerdings funktionierte das Programm in > seinem Video ansonsten wäre ich gar nicht darauf gekommen. Video ist geduldig. > Mal schauen > was daraus wird. Für die Sache mit dem selber schreiben bin ich wohl > noch etwas zu grün hinter den ohren Dann solltest du noch einfacher anfangen. Recht viel mehr als ein Servo durch die Gegend fahren und einen Schalter abfragen ist das nicht. Die Servoansteuerung ist in den Arduino Libs fertig. Darum brauchst du dich nicht wirklich kümmern. Du hättest mehr davon und du würdest was dabei lernen, wenn du das selbst programmieren würdest. So eine Useless Box ist ja nicht wirklch Raketentechnik. Lass dich nicht vom scheinbaren Umfang deines Vorlagecodes beeindrucken. Das meiste davon ist ziemlicher Unsinn und zeibt eigentlich nur, dass der Autor auch nicht programmieren konnte. So gesehen bist du ein Blinder, der von einem mit 10% Sehfähigkeit zu lernen versucht. Das hat wenig Sinn.
:
Bearbeitet durch User
Nein Raketentechnik ist es bei weitem nicht^^ aber wie du gesagt hast ich war schon ziemlich Platt von dem riesen Code. Mal schauen ob ich das ganze dann doch selbst Versuche. Der Lerneffekt wäre natürlich deutlich größer, da gebe ich dir vollkommen recht.
Hallo, ich wollte mich nochmal mit einer Frage melden. Das Grundprogramm um welches es bisher ging läuft soweit. Nun will ich noch eine kleine Veränderung daran vornehmen und zwar das wenn ich einen Taster ein Schalte meine verschiedenen Programmschritte "Random" abgearbeitet werden oder wenn der Taster aus ist die Programmschritte in einer bestimmten Reihenfolge ablaufen. Eigentlich ein Kinderspiel. Dachte ich mir. Nun habe ich etwas herumprobiert allerdings funktioniert das ganze noch nicht so wie gewünscht. Vielleicht schaffe ich es ja mit eurer Hilfe. Ich hoffe das mit dem Code klappt dieses mal besser.
Peter Wagner schrieb: > Nun will ich noch eine kleine Veränderung daran vornehmen und zwar das > wenn ich einen Taster ein Schalte meine verschiedenen Programmschritte > "Random" abgearbeitet werden oder wenn der Taster aus ist die > Programmschritte in einer bestimmten Reihenfolge ablaufen. Kannst du dein Anliegen vielleicht mal in einen vernünftig strukturierten Satz verpacken?
eine Sequenz heißt im englischen "sequence", und nicht "sequens". Hilft dir auch nicht weiter, macht mich aber glücklich
:
Bearbeitet durch User
Ich weis es hört sich komisch an aber bis auf den ein oder anderen Rechtschreibfehler ist es eigentlich genauso formuliert wie ich es meine. Aber es ist mir durchaus klar das es schwer verständlich ist wenn man das Programm und den Hintergrund nicht genau kennt. Also nochmal von vorn. Das Programm gehört zu einem Projekt das sich "Useless Box" nennt. Der ein oder andere hat vielleicht schon einmal davon gehört. Im Prinzip macht diese Box nichts anderes als sich mithilfe von Servos wieder auszuschalten wenn man sie einschaltet. Wenn sich jemand nicht darunter vorstellen gibt es ja noch Google. So viel zur Vorgeschichte. Nun nochmal zu meinem Anliegen. Das Programm für die Box hat verschiedene "Funktionen" welche die Servos unterschiedlich ansteuern. Zum Beispiel das der Servo der den Schalter ausschaltet ganz langsam und ein andermal wieder schnell fährt. Von diesen Schritten gibt es in meinem ursprünglichen Programm 10 verschiedene die in einer festen Reihenfolge ablaufen. Nun habe ich das Programm aber zuerst so geändert das die Schritte nicht in einer festen Reihenfolge ablaufen sondern eben in einem "Random" Modus also zufällig. So viel dazu. Nun würde ich jedoch gerne wie oben beschrieben zwischen diesen zwei "Modi" hin und her schalten. Das bedeutet wenn der Schalter am Eingang x aktiv ist soll die Box die verschiedenen "Funktionen" im "Random" Modus abarbeiten und wenn er nicht aktiv ist soll die Box die verschiedenen Funktionen in der festgelegten Reihenfolge abarbeiten. Quasi die Kombination aus den beiden vorher beschriebenen Szenarien. Viel Text aber ich hoffe so ist es etwas verständlicher erklärt.
Also hier mal ganz grob hingerotzt, der Part mit dem Fkts-Zeigerarray ist sicher syntaktisch falsch, verwende ich zu selten. -> selber nachschlagen, Stichwort Zeiger auf Funktionen, Zeiger als Array. Du fragst in deiner loop() den Schalter ab. Ist er HIGH wechselst du in den Zufallsmodus, ist er Low gehst in den strukturierten Modus.
1 | // Hilfsfunktion zum Abfragen des Status vom Schalter.
|
2 | // kann auch in die Loop gepackt werden, vor den switch-part braucht dann eine Hilfsvariable
|
3 | int statusSchalter() { // Rückgabe anpassen je nachdem wie HIGH LOW |
4 | // definiert ist, schätze mal es ist int
|
5 | //abfragen mit entprellen
|
6 | }
|
7 | |
8 | |
9 | // deine Einzelschritte sind alle in Funktionen ausgelagert
|
10 | void machWas() { ... } |
11 | void machWasAnderes() { ... } |
12 | ....
|
13 | |
14 | // Auf jede dieser machWas Funktionen legst du einen Zeiger und
|
15 | // speicherst diesen in einem Array.
|
16 | void *fktZeigerArray[] = .... |
17 | |
18 | |
19 | void loop () { |
20 | |
21 | //Schalter ständig abfragen und entspr. handeln
|
22 | switch ( statusSchalter() ) { |
23 | case HIGH: //Zufallsmodus |
24 | |
25 | //Zufallswert i zwischen 0 und sizeof fktZeigerArray-1 auswürfeln
|
26 | int i = random ...; // siehe Arduinodoku wie man Zahlen auswürfelt. |
27 | |
28 | fktZeigerArray[i]; //entspr. Funkt wird aufgerufen |
29 | //soll das mehrmals passieren, in eine for-schleife
|
30 | //verpacken
|
31 | break; |
32 | |
33 | case LOW: // strukturierter Modus |
34 | machtWas(); //immer gleiche Reihenfolge |
35 | machWasAnderes(); // Funktionsaufrufe nacheinander wie man sie haben will |
36 | ....
|
37 | }
|
38 | |
39 | }
|
:
Bearbeitet durch User
Bitte jag ihn nicht in Funktionszeiger rein. Erklär ihm lieber was ein Array ist und wie man es zb benutzen kann, um seine ganzen ausprogrammierten Sequenzen in eine einfache Programmschleife und ein paar Datenarrays zu unterteilen. Die ganze Programmierung ist doch Murks, so wie das gemacht ist. Sequenzen programmiert man doch nicht aus, sondern man überlegt sich, wie man das datengesteuert machen kann. Jede Sequenz besteht aus Schritten. Jeder Schritt besteht aus einem Sweep * eines Servos (Servonr) * von einer bestimmten Position * zu einer bestimmten Position * in einer bestimmten Zeit * einer darauf folgenden Wartezeit D.h. mit diesen 5 Werten ist jeder einzelne Schritt einer Sequenz definiert. Eine Sequenz ist einfach nur eine Abfolge von Schritten. Das bedeutet aber auch, dass man EINE Funktion schreiben kann, der man eine derartige Sequenz vor gibt und die diese Sequenz abarbeitet. UNterschiedliche 'Seuqenzprogramme' sind dann einfach nur unterschiedliche Daten, die in diese eine Funktion reingehen. IN einem Programm ist so etwas, wie es ca. nach 40% deines Codes beginnt, einfach nur ein grober UNfug und zeigt eigentlich nur, dass der Programmierer die einfachsten Dinge nicht beherrscht, weil er es nicht für notwendig erachtet hat, erst mal sich einen Grundstock an C anzueignen, ehe er anfängt ein reales Problem zu bearbeiten. Es ist wie ein Chirurg, der gerade mal gelernt hat ein Pflaster aufzukleben, der aber eine Blinddarm-Op machen will. Da helfen auch Funktinospointer nichts. Der ganze Programmaufbau ist mies. Und das fängt bereits bei den ganzen delays an. Auf die Art wirst du niemals ein einigermassen vernünftiges Programm hinkriegen, das halbwegs zeitnah auf Tasterbetätigungen reagiert.
:
Bearbeitet durch User
@Karl Heinz (kbuchegg) Stimmt so geht das auch, ganz ohne Funktionszeiger ist auch noch dazu flexibler und viel kompakter, wenn man das weiter abstrahiert hat wie du. Anpassungen im Ablauf kann er dann rein über die Daten schnell ändern, Codeanpassungen fallen weg. Aber ob das der Ursprungsposter auch hinbekommt? Mit solchen Maximalabstrahierungen, so nenne ich das mal, haben Anfänger eher Probleme, für die ist ein geschwätziges Programm mit viel Redundanz oft lesbarer. Naja soll er mal machen ... so haben wir alle mal angefangen. Aus solchen Fehlern lernt man am meisten.
technikerausbildung auf dem neuesten Stand schrieb: > Aber ob das der Ursprungsposter auch hinbekommt? Auf lange Sicht wird er nicht allzuviele andere Möglichkeiten haben. Arrays und Strukturen sind nach den Strings, unabdingbare Voraussetzungen, wenn man halbwegs ernsthaft etwas machen will. > Mit solchen > Maximalabstrahierungen, so nenne ich das mal, haben Anfänger eher > Probleme, für die ist ein geschwätziges Programm mit viel Redundanz oft > lesbarer. Ist soweit ok und auch verständlich. Das mindeste was er in seinem Programm erst mal machen muss ist, den ganzen Auswahlteil von 'Sequenznummer' zu 'auzurufender Funktion' selbst wieder in eine Funktion zu packen. Die beiden Verteilerleisten getrennt zu halten sind schon mal ein Wartungs-Albtraum. Das kann man natürlich mit Funktionspointern in einem Array machen, schon richtig. Aber wenn er mit Arrays sowieso schon auf Kriegsfuss steht, dann sind Funktionspointer noch abstrakter. So gesehen ist dieser if-Verteiler ok - sofern er in einer Funktion gekapselt wird. > Naja soll er mal machen ... so haben wir alle mal angefangen. Aus > solchen Fehlern lernt man am meisten. Natürlich. Kein Meister ist vom Himmel gefallen. Das Problem ist halt einfach nur, dass es einen gewissen unteren Level gibt, unter dem es keinen Sinn macht, mit realen Programmen anzufangen. Das ist im übrigen in allen Berufen und Hobbies so.
Erstmal danke für die ganzen Hinweise. Nun zum kurzen zwischenstand mein oben beschriebenes Problem habe ich gelöst allerdings gebe ich Karl Heinz recht das das Programm wohl ziemlicher "murks" ist habe ich schon öfter gehört. Allerdings ist es zu meiner Verteidigung auch nicht von mir. Vielleicht werde ich mich nach dem kleinen Erfolgserlebniss dann doch nochmal an das Programm setzten und es wie von euch beschrieben versuchen. Allein schon kürzere Reaktionszeiten wären toll. Hört sich trotz einlesen in die Materie aber doch etwas schwer an. Ohne zuviel verlangen zu wollen aber könnte villeicht jemand ein einfachs Beispielprogramm für die oben gennate Thematik der Servoansteuerung erstellen. Ich finde soetwas hilft ungemein. Und ja ich weis zur Servoansteuerung gibt es schon genügend Beispiele im Internet aber irgendwie macht das auch jeder anders und es ist natürlich nicht gerade auf mein vorhaben bezogen. Und bevor jetzt wieder leute schreien mach es selber und lass es nicht andere leute für dich machen. Es geht mir nur um ein Beispielprogramm nicht um ein komplettes funktionierendes Programm. Danke schonmal
Schau. Sagen wir mal du willst eine Sequenzt an einem Pin ausgeben. Der Pin soll wahlweise 1 oder 0 sein, wobei der Pin jeweils eine bestimmte Zeit diesen Zustand haben soll. Du machst das momentan so
1 | void loop() |
2 | {
|
3 | digitalWrite( 5, HIGH ); |
4 | delay( 500 ); |
5 | digitalWrite( 5, LOW ); |
6 | delay( 300 ); |
7 | digitalWrite( 5, HIGH ); |
8 | delay( 400 ); |
9 | digitalWrite( 5, LOW ); |
10 | delay( 200 ); |
11 | }
|
gut. das sieht erst mal einfach aus und ist es auch. Aber du siehst in deinem Programm wohin das führt. Unmengen von Code, der im Grunde immer gleich ist, kaum zu warten ist und dessen Funktion nicht leicht zu ändern ist. Ich adressiere jetzt absichtlich erst mal das delay 'Problem' noch nicht. Aber abgesehen davon, wie könnte man das ändern? Diese Squenz besteht aus Schritten. Konkret sind das 4 Schritte, wobei jeder Schritt aus einem Status (HIGH oder LOW) und einer Zeitdauer besteht. d.h. man könnte sich das mal definieren, dass es derartige Schritte gibt.
1 | struct Schritt |
2 | {
|
3 | unsigned char Status; |
4 | unsigned int Dauer; |
5 | };
|
da haben wirs: die Beschreibung, wie so ein Schritt aufgebaut ist. Nach haben wir keine Schritte. NOch haben wir nur die Beschreibung, wie ein Schritt grundsätzlich aussieht (sozusagen 'der Bauplan'). Das ändern wir gleich mal. Wir erzeugen ein Array von Schritten, welches die geforderte Sequenz von oben enthält
1 | struct Schritt |
2 | {
|
3 | unsigned char Status; |
4 | unsigned int Dauer; |
5 | };
|
6 | |
7 | Schritt Sequence[4] = |
8 | {
|
9 | { HIGH, 500 }, |
10 | { LOW, 300 }, |
11 | { HIGH, 400 }, |
12 | { LOW, 200 } |
13 | };
|
14 | |
15 | unsigned int actSchritt; |
soweit so gut. Die Variable actSchritt wird in weiterer Folge einfach die 'Schrittnummer' enthalten, des Schrittes der als nächster drann ist. loop() kann jetzt ganz einfach geschrieben werden. Bei jedem Aufruf von loop() (der ja immer wieder erfolgt), wird einfach der nächste Schritt durchgeführt und der Schrittzähler um 1 weiter gestellt (wenn das geht), bzw. auf 0 zurück gestellt wenn alle Schritte abgearbeitet wurden.
1 | struct Schritt |
2 | {
|
3 | unsigned char Status; |
4 | unsigned int Dauer; |
5 | };
|
6 | |
7 | Schritt Sequence[4] = |
8 | {
|
9 | { HIGH, 500 }, |
10 | { LOW, 300 }, |
11 | { HIGH, 400 }, |
12 | { LOW, 200 } |
13 | };
|
14 | |
15 | unsigned int actSchritt; |
16 | |
17 | void loop() |
18 | {
|
19 | // ---- Position A
|
20 | |
21 | digitalWrite( 5, Sequence[actSchritt].Status ); |
22 | delay( Sequence[actSchritt].Dauer ); |
23 | |
24 | actSchritt++; |
25 | if( actSchritt == 4 ) |
26 | actSchritt = 0; |
27 | |
28 | // ---- Position B
|
29 | }
|
Dadurch haben wir jetzt erst mal 2 Fliegen mit einer Klappe geschlagen. Alles an Code, was an den im Code markierten Positionen A bzw. B steht, wird nach bzw. vor JEDEM Schritt ausgeführt! Zum Beispiel könnte da eine Überprüfung von diversen Schalterstellungen stehen, die damit nach/vor jedem einzelnen Schritt geprüft wird. Zum anderen könenn wir noch ein bischen Makro-Magie machen:
1 | struct Schritt |
2 | {
|
3 | unsigned char Status; |
4 | unsigned int Dauer; |
5 | };
|
6 | |
7 | Schritt Sequence[] = |
8 | {
|
9 | { HIGH, 500 }, |
10 | { LOW, 300 }, |
11 | { HIGH, 400 }, |
12 | { LOW, 200 } |
13 | };
|
14 | |
15 | unsigned int actSchritt; |
16 | |
17 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
|
18 | |
19 | void loop() |
20 | {
|
21 | // ---- Position A
|
22 | |
23 | digitalWrite( 5, Sequence[actSchritt].Status ); |
24 | delay( Sequence[actSchritt].Dauer ); |
25 | |
26 | actSchritt++; |
27 | if( actSchritt == ARRAY_SIZE(Sequence) ) |
28 | actSchritt = 0; |
29 | |
30 | // ---- Position B
|
31 | }
|
und so die Abarbeitung der Sequence soweit verallgemeinern (wegen der 4 - welches die Array-Größe darstellte), dass sich das von selber anpasst. Wenn die Sequence vergößert werden soll
1 | Schritt Sequence[] = |
2 | {
|
3 | { HIGH, 500 }, |
4 | { LOW, 300 }, |
5 | { HIGH, 400 }, |
6 | { LOW, 200 }, |
7 | { HIGH, 800 }, |
8 | { LOW, 100 } |
9 | };
|
dann mache ich das genau an dieser Stelle, bei der 'Definition' der Sequenz. Dort wo ich gut sehen kann, was ich eigentlich tue. Denn hier muss ich mir die Sequenze nicht aus dem Code erst mühsam extrahieren, sondern ich hab sie an einer Stelle zusammen gefasst. Was hier geschehen ist, ist also nichts anderes als das Extrahieren der relevanten Information einer Sequenz in eine Datenstruktur. Zusammen mit Programmcode, die in der Lage ist, diese Datenstruktur abzuarbeiten. Denn jetzt geht die Sache weiter. Niemand sagt, dass die Funktionalität des Abarbeitens in loop() stecken muss. Die kann genausogut auch in einer eigenen Funktion stecken. Und niemand sagt, dass ich dieser Funktion immer das gleiche Array 'zum Frass vorwerfen' muss. Das kann genausogut eines aus einer Auswahl von zb 20 verschiedenen Arrays sein. D.h. mit obigem ist die Reise zu einem vernünftigen Code noch lange nicht zu Ende. Sie beginnt erst. Aber - und das ist die Kehrseite der Medaille - man muss dazu sein Handwerkszeug, die Programmiersprache, kennen. Kennt man von der Sprache nur 10% der Möglichkeiten, dann kann man keine vernünftigen Programme schreiben. In einem gewissen Sinne ist das wie: ich will 4 mal 5 ausrechnen, indem ich rechne 5 + 5 + 5 + 5. Klar kommt da das richtige raus. Aber rechne mit dieser Technik mal 123*478 aus. Da bricht dann diese scheinbar einfache Lösungs-Strategie wie ein Kartenhaus zusammen. Da bleibt nichts anderes übrig, als zu lernen, wie man händisch multipliziert. Selbst wenn dieses Wissen für 4*5 nicht notwendig war, weil es auch so, durch Addieren, ging. Je komplexer Programme werden, desto mehr ist es notwendig, dass ich mein Werkzeug kenne und in der Hand habe, damit mich die Komplexität nicht überläuft und umbringt. Als Programmierer muss ich mich selber organisieren und Ordnung rein bringen. Der Compiler tut das nicht für mich. Und das bedeutet lernen. Du kannst mit dem 0-er Pinsel aus dem Wasserfarbenkasten ein Ei bemalen. Aber du kannst damit kein Auto neu lackieren. Das heißt - du kannst schon. Aber das Ergebnis ist dann auch dementsprechend. Die Lösung lautet dann nicht, mit dem Pinsel virtuoser zu werden, sondern den Umgang mit der Spritzpistole zu lernen (eine ganz andere Technik).
:
Bearbeitet durch User
Ok also ersteinmal danke für die Erklärung. Das man sein Handwerkzeug kennen muss ist mir klar und da hilft vermutlich nur ausprobieren und üben. Die Materie des Programmierens ist mir zwar nicht komplett fremd da ich in meiner Ausbildung auch viel damit zu tun habe allerdings funktioniert natürlich jede Programmiersprache bzw. jedes Programm anders. Allerdings ist mir bei deinem Beispiel gleich aufgefallen das ich meine Funktionen ja Schritt fùr Schritt abarbeite je nachdem welcher wert gerade im array steht. Und das ganze dann eben wieder von vorne beginnt. Allerdings funktioniert das wenn ich einen Zufallsgenerator will ja nicht mehr oder liege ich falsch?
Peter Wagner schrieb: > Ok also ersteinmal danke für die Erklärung. Das man sein Handwerkzeug > kennen muss ist mir klar und da hilft vermutlich nur ausprobieren und > üben. Auch. Aber vor allen Dingen hilft da eines: Ein Lehrbuch lesen und durcharbeiten! Beim Durcharbeiten erlangt man dann schon ein wenig Übung und dann geht es am praktischen Objekt weiter. Aber erst mal heißt es: ich muss wissen, was es eigentlich gibt und wie das zusammenhängt. Und das steht nun mal in den Büchern drinnen. Viel steht da drinnen. Eine Menge INformation.
Peter Wagner schrieb: > ich meine Funktionen ja Schritt fùr Schritt abarbeite je nachdem welcher > wert gerade im array steht. Und das ganze dann eben wieder von vorne > beginnt. Allerdings funktioniert das wenn ich einen Zufallsgenerator > will ja nicht mehr oder liege ich falsch? Ich hab absichtlich das Problem soweit vereinfacht, dass ich nicht Unmengen an Code schreiben muss, um ein Prinzip zu verdeutlichen. Nämlich das Prinzip der Trennung von Code und Steuerdaten. Diese angerissene Lösung ist die Präsentation einer Idee. Wie du diese Idee dann auf deinen konkreten Fall anwenden willst, das ist dir überlassen. Ich will und werde da jetzt keine fertige Lösung für dich präsentieren, weil ich das Gefühl habe, du hast schon genug Zeugs einfach abgeschrieben ohne es zu verstehen. Und das ist nicht Sinn der Sache.
Ahja. Ich wollte eigentlich auch nur wissen ob es so ist oder nicht. Und bis auf deine Erklärung und der Erkenntnis das ich mich eben logischerweise einarbeiten muss habe ich seit ich dieses Thema erstellt habe absolut keine Programme/Programmabschnitte bekommen von denen ich überhaupt etwas hätte abschreiben können. Es ist ja nicht so das ich eure Hilfe nicht schätze, allerdings lasse ich mir auch nicht gerne Dinge unterstellen die schlicht und ergreifend einfach nicht stimmen. Nur so viel zu dem Thema. Und bevor jetzt jemand schreibt das es weiter oben ein geändertes Programm gibt, der sollte sich im klaren darüber sein das es nicht funktioniert hat und ich nur über den langen E mail verkehr mit dem ursprünglichen ersteller ein lauffähiges Programm zusammengebracht habe. Und ja ich weis das es murks ist aber wenigstens lief es dann mal.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.