Forum: Compiler & IDEs Promgrammfehler in Arduino


von Peter W. (laber_90)


Angehängte Dateien:

Lesenswert?

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
von da1l6 (Gast)


Lesenswert?

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

von Michael (Gast)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

Zumindest fehlt mal ein Semikolon fehlt bei Zeile

int seq = 0

von hmm.. ? (Gast)


Lesenswert?

"Promgrammfehler" ?

von Peter W. (laber_90)


Angehängte Dateien:

Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von Matthias Larisch (Gast)


Lesenswert?

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?

von Peter W. (laber_90)


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

Wie wärs mit dem kompletten Source-Code?
Dann könnte man mehr sehen, als nur mit so Screenshot-Schnipsel.

von Peter W. (laber_90)


Lesenswert?

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);

}

von Chris M. (yoblid) Benutzerseite


Lesenswert?

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.

von Markus (Gast)


Lesenswert?

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

von Peter W. (laber_90)


Lesenswert?

Markus schrieb:
> Als nächstes ist falsch:if boxoff

Da muss das boxoff in Klammer stehen oder?

von Markus (Gast)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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

von Peter W. (laber_90)


Lesenswert?

Vor allem den Sweep Befehl kennt das Programm wohl nicht und auch Google 
findet nicht wirklich etwas dazu

von Jürgen S. (jurs)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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?

von Markus (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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?

von Markus (Gast)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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
von Peter W. (laber_90)


Lesenswert?

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.

von Peter W. (laber_90)


Angehängte Dateien:

Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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?

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

eine Sequenz heißt im englischen "sequence", und nicht "sequens". Hilft 
dir auch nicht weiter, macht mich aber glücklich

: Bearbeitet durch User
von Peter W. (laber_90)


Lesenswert?

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.

von technikerausbildung auf dem neuesten Stand (Gast)


Lesenswert?

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
von Karl H. (kbuchegg)


Lesenswert?

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
von technikerausbildung auf dem neuesten Stand (Gast)


Lesenswert?

@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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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
von Peter W. (laber_90)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter W. (laber_90)


Lesenswert?

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
Noch kein Account? Hier anmelden.