Anfängerproblem Hilfe bei der Fehlersuche 2 Kanal Goethe-Schädel

Hallo alle.

Ich bin ein Anfänger in Sachen coding und habe nach einigen Blink und Servospielereien nun ein etwas größeres Projekt, bei dem ich Hilfe benötige. Es sind zwei "Jawduinos", allerdings mit vereinfachter Abfrage und Winkelberechnung. Die beiden sollen mal Goethes Faust, die Offenbarungsszene aufführen.
Konzept ist ähnlich wie beim Klassischen Jawduino. Ich benutze aber eine andere Augenmechanik, weil ich oben, mitte, unten haben will. Im Code gehe ich oben in der Beschreibung und in den Kommentaren darauf näher ein. (noch nicht fertig implementiert)
Jeder Schädel hat sein eigenes Levelmeter. Die Tonspur ist so bearbeitet, dass Faust und Mephisto jeweils getrennte Kanäle nutzen und so jeweils der richtige Schädel spricht. Dazu werden die mittleren 3 LEDs abgefragt. Die erste und letzte triggern die Beleuchtung mit der selben Val Methode (nicht im Code bisher)

Schön wäre es, konkrete Hilfe zu erhalten und nicht erst Hinweise auf andere Tutorials zu bekommen. Ich bin ADHSler und lerne daher etwas anders. Ich lerne viele Dinge gleichzeitig, oder in mehr oder weniger kurzen Zeitabständen hintereinander. Ähnlich wie ein Arduino. Das macht es für mich etwas kompliziert. Für andere leider auch :wink: Dafür entschuldige ich mich mal vorher.
Ich brauche Hilfe bei den Fehlermeldungen.
Speziell geht es mir um den Aufruf der Subroutinen. Das funktioniert nicht, und ich sehe nicht warum. Ich ahne, dass das mit der Declaration mit {} zusammenhängt. Aber ich bin grad zu blöd iwie.
THX. Wird zwar leider nix mehr bis Halloween, aber als Gag für ne Vitrine oder als Alexaspeaker ist es auch lustig. Ambitioniert, das in paar Tagen realisieren zu wollen...
Und ich hab noch nicht mal den Pudel^^

Im angehängten Code ist daher viel kommentiert, was diese Zeilen bezwecken -sollen-, wenn ich fertig bin. Im Moment läuft er noch NICHT ! Ich versuche noch zwei weitere Codes anzuhängen, die jeder für sich funktionieren, aber auf Grund von benutzten Delays leider nicht tauglich sind um sie beide in einen Sketch zu basteln.

Hier mein "Fantasiecode" der so leider noch nicht funktioniert!

//Projekt Goethes Faust / Studierzimmer Offenbarungsszene
//Dargestellt von zwei sprechenden Schädeln
//Benutzt werden zwei Levelmeterbausteine mit jeweils 5 LEDs, von denen jeweils die mittleren drei analog
//abgefragt werden, um sie in Servosignale zu verwandeln. Die ersten sollen zukünftig zum Einschalten der Augenhintergrundbeleuchtung dienen.
//Für die Augen wird eine Zahnradmechanik zur verdoppelung des Drehwinkels verwendet um beide Augen gleichzeitig zu positionieren
//und die als Augen verwendeten Tischtennisbälle mit jeweils 3 Pupillen mit jeweils 60° des 180° Servos für nach oben, mittig, und nach unten
//zu schauen.
//Einzelcodes funktionieren (mit delays)
//Hier sollen die Codes für Augen und Kiefer zusammengeführt werden und das Timing über Timer gesteuert werden, um alle noch zu
//implementierenden Funktionen der Schädel (electric Boga über Gasventil und Zündung, Relais, LED zeitlich steuern zu können.

#include <MobaTools.h> (Erweiterte Servobibliothek wegen Speedsetting)

MoToServo mephistoL;
MoToServo faustusR;
MoToServo mephistoLAugen;
MoToServo faustusRAugen;
#define mephistoL_PIN 2     //  Arduino PIN für KieferServo Mephisto linker Kanal
#define faustusR_PIN 3     //  Arduino PIN für KieferServo Faustus rechter Kanal
#define mephistoLAugen_PIN 4 // Arduino PIN für AugenServo Faustus linker Kanal
#define faustusRAugen_PIN 5 // Arduino PIN für AugenServo Faustus rechter Kanal

//Timingblock
unsigned long previousMillis = 0; // speichert den Zeitpunkt an dem zuletzt geschalten wurde
const long interval_1 = 10; // Länge der Pause in ms //Interval Kiefer mephistoL_PIN 2
const long interval_2 = 10; // Länge der Pause in ms //Interval Kiefer faustusR_PIN 3
const long interval_3 = 4000; // Länge der Pause in ms //Interval mephistoLAugen_PIN 4
const long interval_4 = 4000; // Länge der Pause in ms //Interval faustusRAugen_PIN 5
//const long interval_5 = 1000; // Länge der Pause in ms 
//const long interval_6 = 1000; // Länge der Pause in ms
//const long interval_7 = 1000; // Länge der Pause in ms

// Servo auf 0 Stellung
int servom_pos = 100;
int servof_pos = 100;

// Variablen für die analogen "Sprech"werte
int val1;               //  Floating value 1
int val2;               //  Floating value 2
int val3;               //  Floating value 3
int val4;               //  Floating value 4
int val5;               //  Floating value 5
int val6;               //  Floating value 6

char smon[30];           //  Serial monitor buffer

void setup() {
  mephistoL.attach(mephistoL_PIN);
  mephistoL.setSpeed( 0 );    // Verfahrgeschwindigkeit einstellen
  faustusR.attach(faustusR_PIN);
  faustusR.setSpeed( 0 );    // Verfahrgeschwindigkeit einstellen
  mephistoLAugen.attach(mephistoLAugen_PIN);
  mephistoLAugen.setSpeed( 4 );    // Verfahrgeschwindigkeit einstellen
  faustusRAugen.attach(faustusRAugen_PIN);
  faustusRAugen.setSpeed( 4 );    // Verfahrgeschwindigkeit einstellen
  Serial.begin(9600);
}

void loop() {
  //  Anfängliche Servopositionen:
  servom_pos = 100; // fast Nullposition, Kiefer geschlossen
  servof_pos = 100; // fast Nullposition, Kiefer geschlossen
  //  Hier lese ich die LED Werte
  val1 = analogRead(A0);
  val2 = analogRead(A1);
  val3 = analogRead(A2);
  val4 = analogRead(A3);
  val5 = analogRead(A4);
  val6 = analogRead(A5);
// Timerblocks
  // in den Timerblöcken soll mit Hilfe der getakteten Abfrage eine gewisser "Mittelwert" beim sprechen erzeugt werden, den ich variieren kann.
unsigned long currentMillis = millis(); // Aktuelle Zeit wird in currentMillis gespeichert
  if (currentMillis - previousMillis >= interval_1) { // Falls mehr als 10 ms vergangen sind
     previousMillis = currentMillis; // Zeitpunkt der letzten Schaltung wird festgehalten 
  sprechenM(); // Kiefer von Mephisto wird bewegt
  }

  if (currentMillis - previousMillis >= interval_2) { // Falls mehr als 10 ms vergangen sind
     previousMillis = currentMillis; // Zeitpunkt der letzten Schaltung wird festgehalten 
  sprechenF(); // Kiefer von Faustus wird bewegt
  }
}

void sprechenM(); // Hier werden die Winkel berechnet und vom 100° Nullwert abgezogen
{
  if(val1 < 341) servom_pos -= 10;
  if(val2 < 341) servom_pos -= 10;
  if(val3 < 341) servom_pos -= 10;
  Babbl_Los(); // Startet die Ausführung
}

void sprechenF(); 
{ 
  if(val4 < 341) servof_pos -= 10;
  if(val5 < 341) servof_pos -= 10;
  if(val6 < 341) servof_pos -= 10;
  Babbl_Los();
}

void Babbl_Los(); // Actionloop: Hier sollen alle Servos ihre Bewegung ausführen
{
  //  Servomapping,falls nötig:
  // val1 = map(val1, 0, 1023, 0, 190);  
  mephistoL.write(servom_pos); 
  faustusR.write(servof_pos);
  //  Debugging:  IDE SERIAL MONITOR DATENCHECK
  sprintf(smon, "A1:%4d A2:%4d A3:%4d Pos:%4d", val1, val2, val3, servom_pos,  val4, val5, val6, servof_pos);
  Serial.println(smon);
  
  //  Bissl delay:  //Falls nötig für timing, sollte nicht weil Wertabfrage durch Interval
  // delay(15);
}

Fehlermeldungen:

Arduino: 1.8.16 (Windows Store 1.8.51.0) (Windows 10), Board: "Arduino Nano, ATmega328P (Old Bootloader)"

C:\Users\Titanium\Documents\Arduino\easyjawduino\easyjawduino.ino: In function 'void loop()':

easyjawduino:75:3: error: 'sprechenM' was not declared in this scope

sprechenM(); // Kiefer von Mephisto wird bewegt

^~~~~~~~~

easyjawduino:80:3: error: 'sprechenF' was not declared in this scope

sprechenF(); // Kiefer von Faustus wird bewegt

^~~~~~~~~

C:\Users\Titanium\Documents\Arduino\easyjawduino\easyjawduino.ino: At global scope:

easyjawduino:85:1: error: expected unqualified-id before '{' token

{

^

easyjawduino:93:1: error: expected unqualified-id before '{' token

{

^

easyjawduino:101:1: error: expected unqualified-id before '{' token

{

^

exit status 1

'sprechenM' was not declared in this scope

Und hier ein paar Bilder der ersten Prototypphase. Hab noch 4 Ersatzschädel^^

1635286878358|225x500

Du hast bei den Funktionsdefinitionen überall ein falsches ';' eingebaut,
was sie zu Deklarationen macht mit einem folgenden frei fliegenden { } Block.

1 Like

Echt ? Mist. Ich liege schon. Muss ich morgen machen.
Und nochmal nachlesen. Das ; sagt doch "Ausführen". Wie beim Bund. Nicht ?
Danke schonmal. Und gute Nacht^^

Nee, ; sagt eher Ende Gelände, was für eine Definition falsch ist.
Das ist echt die erste Funktion, die du selbst schreibst?

Ahaaaa. Ich mag die Art wie du das erklärst. Wir sind kompatibel denke ich. In der Größe ?Ja. Hatte schon bissel mit LEDs rumgeblinkt, um das mit dem Delayvermeiden zu kapieren. Aber ich bin erst seit so 4 Wochen dran zu lernen.

Überflüssige ';' sind ein klassischer Anfängerfehler, besonders beliebt bei if

if (umsonstGetestet);

Ich bin klassischer Anfänger. Verdammt. Ich will immer alles sofort. Konnte mich nur sehr schwer trennen vorher. Ich machte so 5-6 Beispiele am Tag bisher. Fortschritt ist ok soweit. Aber diese Flüchtigkeitsfehler..... Und manches ist eben doch noch nicht so klar^^

Eine Einführung in C und C++ ist sicher sinnvoll, unabhängig vom Arduino Kram.

Ich kann dir keine gute empfehlen, ich habe das alles noch aus Büchern gelernt,
vor langer langer Zeit.

Datentypen, Kontrollstrukturen, Arrays, struct, union, class sollte man besser kennen,
ehe man wirklich sinnvoll arbeiten kann.

joa. Schon. Aber da ballert mein ADHS dann quer. Schwer zu erklären. Es ist mir nur möglich, mich auf Dinge zu konzentrieren, die mein Interesse halten. Nicht nur wecken. Bei reiner Theorie werde ich schnell aufgeben, bzw, mein Hirn findet andere Interessen. Ich kann nur lernen, eine Maschine zu bauen, in dem ich sie baue und alles was dafür nötig ist simultan lerne. Die klassische Lernreihenfolge ist mir nicht möglich. Schwer zu erklären. Dafür lerne ich sehr schnell und vieles gleichzeitig. Die Struktur ist anders. Obwohl du natürlich recht hast. Gerade bei Kontrollstrukturen.

Prototyp. Nicht erschrecken^^

Sieht doch gut und solide aus.
Wo geht das Ethernet hin? Zu einem Raspi?

Ich bringe auch viele Dinge nicht zu Ende, bin leicht ablenkbar,
verliere schnell das Interesse an Dingen wenn sie mich nicht ansprechen, faszinieren
oder herausfordern, aber ich habe keine Ausrede dafür.
Na ja, vielleicht zunehmender Seniorenindividualismus. :wink:

Grundlagenwissen wird in der Arduinowelt eher kleingeschrieben.

Programmieren wird aber viel einfacher, wenn man weiß,
was man, und wie man etwas (in C++) machen kann.
Eher geht es dabei sogar um Kodieren,
also das Ausdrücken eines Algorithmus in einer
speziellen Programmiersprache, auf und für ein spezielles System.
Programmieren an sich ist - für mich - eher die Fähigkeit aus einer Problemstellung
einen Algorithmus zu entwickeln.


Mephisto und Faust. Pudel fehlt noch. Wird wohl über einen Stepper nach oben gezogen und zündet über Relais eine kleine Rauchpatrone oder so.

Das Ethkabel geht nur zu den Schädeln. ESP und oder Raspi ist erst das nächste Projekt. Auf der rechten Seite in der Box ist ein MP3 Karaokeplayer mit Bluetooth und USB. Der liefert den Sound und den Input. Und die Mikrofonverstärkung, sollte ich sie nutzen. Oben ist noch ein Akku für den MP3 Player. Der Arduino und die Servos nebst LEDMeter werden von einem 2. Akkupack versorgt.

Pyrotechnik ist schlecht wiederverwendbar, gibt es nicht kleine elektrische Dampfgeneratoren aus dem Modellbau (Dampflokomotive)?

Sowas vielleicht:
https://www.themt.de/el-1140-smoke-49.html

Bin Pyrotechniker^^ Hab genug von dem Zeug und nutze nur kleine Mengen mit einem E-Brückenzünder (T1) um den "Pudel" ganz am anfang in einer Rauch Blitzwolke Richtung Off zu befördern. Dann übernimmt im Script eh Mephisto mit "Was soll der Lärm ?" usw...
Eventuel zündet auch eine kleine electric Boga auf Basis eines CremeBrulee Brenners. So ne art Weinbergböller in klein.

Dagegen sind die Öldampfer natürlich lame. :grinning:

geht. Mit Nebelmaschine und relais würde es auch gehen. Aber meine Nebelmaschine ist putt. Also... Und weils so schön stinkt...Roter Rauch und so ein Kinderfeuerwerksblitzdings

Zu deinem Sketch:

Du steuerst die Bewegungen mit unabhängigen Timern (an sich ok, millis und so),
aber eigentlich sind das doch Schritte eines Ablaufs, also eine klassische Statemachine,
oder in Deutsch auch hochtrabend endlicher Automat.
(Auf gaaaaaanz lange Sicht können die Timer auch auseinanderlaufen,
aber das ist bei deiner Anwendung sicher nicht relevant.)

Eine Menge von Zuständen, und die Übergänge zwischen diesen,
lassen sich damit sehr gut kontrollieren, der Kode wird übersichtlich,
besser wartbar, und einfach zu erweitern.
Neue Übergänge oder ein neuer Zustand sind schnell eingebaut,
alles läuft über einen zentralen Verteiler.

Joa. Verdammt, da hast mir jetzt einen bösen Virus gesetzt^^
Es arbeitet hart. Ich habe mir das bisher so nicht zugetraut mit der Statemachine. Hab zwar die Beispiele gemacht, aber mich nicht weiter damit beschäftigt.
Nach deiner Antwort habe ich mir nochmal das Ampelbeispiel von so nem Schweizer auf Youtube angeschaut. Würde ich hinkriegen glaub ich. Nur wohl nicht so kurzfristig. Aber, stay tuned. Heute Abend schaue ich mir erst mal an, was der Code in der Realität macht.
50% sind blind geschrieben, ohne Arduino^^

State-Machines sind eigentlich simpler, weil alles besser strukturiert ist.

Ich mag es, die Zustände mit einem enum zu definieren und die eigentlichen
Aktionen dann über einen switch zu verteilen.
Der Kompiler sagt dir, wenn du einen Zustand vergessen hast,
allein das ist - bei einem Projekt in Entwicklung - sehr angenehm.

Viel Erfolg beim Lernen. :grinning: