Go Down

Topic: Anfänger: Loop-Changer-Pedal m. Arduino Uno / Probleme mit Variable (Read 148 times) previous topic - next topic

janlieb89

Guten Morgen Gemeinde,

ich verfolge schon längere Zeit die Posts in diesem Forum und muss mich nun auch einmal mit einem Problem an euch wenden. Ich habe mir einen 3 Channel-Looper für mein Gitarren-Pedalboard gebaut mit Arduino Uno und einem 8-Relaise-Modul.

zur Funktion:
Der Channel-Looper hat 3 Taster (Bypass, And, Or) und 6 LEDs (Bypass, And, Or, Loop 1, Loop 2, Loop 3). Eingeteilt in 7 Modi.

zum Problem:
Der angehängte Code funktioniert perfekt, solange meine Variable debug = 1.
Diese soll die serielle Schnittstelle und Serial Monitor Ausgabe aktivieren, was ich ja im Betrieb nicht brauche. Deshalb hätte ich im Betrieb dann debug = 0 hart gesetzt.
Wenn ich allerdings debug = 0 setze, funktioniert plötzlich der Code nicht mehr, wie er soll. Z.B. springt dann einfach der Bypass beim wechseln der Modi raus oder es schalten bei deaktiviertem Bypass beim Wechseln der Modi die Relaise nicht mehr um, oder die Modi kommen bei Tasterdruck in einer willkürlichen Reihenfolge. Alles dann halt recht willkürlich.

Ich hoffe ich habe alle Informationen gegeben und es findet sich jemand, der helfen kann. Vielen Dank vorab!

(Code kommt wegen 9000 Zeichen in der nächsten Message)

janlieb89

Code: [Select]

//GANWORKS CHANNEL LOOPER V6 2019-10-21

//mode = 1: Loop 1
//mode = 2: Loop 2
//mode = 3: Loop 3
//mode = 4: Loop 1+2
//mode = 5: Loop 1+3
//mode = 6: Loop 2+3
//mode = 7: Loop 1+2+3

#include <EEPROM.h>

//Inputs
byte pbbypass = 10;
byte pband = 11;
byte pbor = 12;

//Outputs
byte relais1 = 2;
byte relais2 = 3;
byte relais3 = 4;
byte relais4 = 5;
byte relais5 = 6;
byte relais6 = 7;
byte relais7 = 8;
byte relais8 = 9;
byte ledbypass = 14;
byte ledloop1 = 15;
byte ledloop2 = 16;
byte ledloop3 = 17;
byte ledand = 18;
byte ledor = 19;

//Variables
byte modebypass = EEPROM.read(0); //Start Pedal at defined bypass-mode
byte mode = EEPROM.read(1); //Start Pedal at defined mode
byte lastandmode = EEPROM.read(2); //Start or-mode at defined or-mode
byte lastormode = EEPROM.read(3); //Start and-mode at defined and-mode
byte debug = 1; //Set 1 for Serial Monitor Debug

void setup() {
  //Set valid values if necessary
  if (modebypass > 1) modebypass = 1;
  if ((mode == 0) || (mode > 7)) mode = 7;
  if (lastandmode < 4) lastandmode = 7;
  if ((lastormode == 0) || (lastormode > 3)) lastormode = 1;
  
  //Set Inputs
  pinMode(pbbypass, INPUT_PULLUP);
  pinMode(pband, INPUT_PULLUP);
  pinMode(pbor, INPUT_PULLUP);
  
  //Set Output Relaise
  pinMode(relais1, OUTPUT);
  pinMode(relais2, OUTPUT);
  pinMode(relais3, OUTPUT);
  pinMode(relais4, OUTPUT);
  pinMode(relais5, OUTPUT);
  pinMode(relais6, OUTPUT);
  pinMode(relais7, OUTPUT);
  pinMode(relais8, OUTPUT);

  //Set Output LEDs
  pinMode(ledbypass, OUTPUT);
  pinMode(ledloop1, OUTPUT);
  pinMode(ledloop2, OUTPUT);
  pinMode(ledloop3, OUTPUT);
  pinMode(ledand, OUTPUT);
  pinMode(ledor, OUTPUT);

  if (debug == 1) Serial.begin(9600);

  //Run Start-Mode defined above
  if (modebypass == 1) bypass();
  setMode();
}

void loop() {
  //Pushbutton Bypass
  if (digitalRead(pbbypass) == 1){
    switch(modebypass){
      case 0:
        modebypass = 1;
        bypass();
        break;
      case 1:
        modebypass = 0;
        break;
    }
    eepromupdate();
    while (digitalRead(pbbypass) == 1) {
        setMode();
    }
  }

  //Pushbuttor Or
  if (digitalRead(pbor) == 1){
    switch(mode) {
      case 1:
      case 2:
        mode++; //increase mode
        break;
      case 3:
        mode = 1; //switch from highest to lowest or-mode
        break;
      case 4:
      case 5:
      case 6:
      case 7:
        lastandmode = mode; //safe last and-mode
        mode = lastormode;  //switch to last or-mode
        break;
    }
    eepromupdate();
    while (digitalRead(pbor) == 1) {
      setMode();
    }
  }
  
  //Pushbutton and
  if (digitalRead(pband) == 1){
    switch(mode) {
      case 1:
      case 2:
      case 3:
        lastormode = mode; //safe last or-mode
        mode = lastandmode; //switch to last and-mode
        break;
      case 4:
      case 5:
      case 6:
        mode++; //increase mode
        break;
      case 7:
        mode = 4; //switch from highest to lowest and-mode
        break;
    }
    eepromupdate();
    while (digitalRead(pband) == 1) {
      setMode();
    }
  }
}

void setMode() {
  switch(mode) {
    case 1:
      mode1();
      break;
    case 2:
      mode2();
      break;
    case 3:
      mode3();
      break;
    case 4:
      mode4();
      break;
    case 5:
      mode5();
      break;
    case 6:
      mode6();
      break;
    case 7:
      mode7();
      break;
  }
  if (debug == 1) serialmonitor();
}

void bypass() { //Bypass
    digitalWrite(ledbypass, HIGH);
    digitalWrite(relais1, LOW);
    digitalWrite(relais2, LOW);
    digitalWrite(relais3, LOW);
    digitalWrite(relais4, LOW);
    digitalWrite(relais5, LOW);
    digitalWrite(relais6, LOW);
}

void mode1() { //Loop 1
    digitalWrite(ledloop1, HIGH);
    digitalWrite(ledloop2, LOW);
    digitalWrite(ledloop3, LOW);
    digitalWrite(ledand, LOW);
    digitalWrite(ledor, HIGH);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, HIGH);
      digitalWrite(relais2, HIGH);
      digitalWrite(relais3, LOW);
      digitalWrite(relais4, LOW);
      digitalWrite(relais5, LOW);
      digitalWrite(relais6, LOW);
    }
}
  
void mode2() { //Loop 2
    digitalWrite(ledloop1, LOW);
    digitalWrite(ledloop2, HIGH);
    digitalWrite(ledloop3, LOW);
    digitalWrite(ledand, LOW);
    digitalWrite(ledor, HIGH);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, LOW);
      digitalWrite(relais2, LOW);
      digitalWrite(relais3, HIGH);
      digitalWrite(relais4, HIGH);
      digitalWrite(relais5, LOW);
      digitalWrite(relais6, LOW);
    }
}
  
void mode3() { //Loop 3
    digitalWrite(ledloop1, LOW);
    digitalWrite(ledloop2, LOW);
    digitalWrite(ledloop3, HIGH);
    digitalWrite(ledand, LOW);
    digitalWrite(ledor, HIGH);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, LOW);
      digitalWrite(relais2, LOW);
      digitalWrite(relais3, LOW);
      digitalWrite(relais4, LOW);
      digitalWrite(relais5, HIGH);
      digitalWrite(relais6, HIGH);
    }
}
  
void mode4() { //Loop 1+2
    digitalWrite(ledloop1, HIGH);
    digitalWrite(ledloop2, HIGH);
    digitalWrite(ledloop3, LOW);
    digitalWrite(ledand, HIGH);
    digitalWrite(ledor, LOW);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, HIGH);
      digitalWrite(relais2, HIGH);
      digitalWrite(relais3, HIGH);
      digitalWrite(relais4, HIGH);
      digitalWrite(relais5, LOW);
      digitalWrite(relais6, LOW);
    }
}
  
void mode5() { //Loop 1+3
    digitalWrite(ledloop1, HIGH);
    digitalWrite(ledloop2, LOW);
    digitalWrite(ledloop3, HIGH);
    digitalWrite(ledand, HIGH);
    digitalWrite(ledor, LOW);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, HIGH);
      digitalWrite(relais2, HIGH);
      digitalWrite(relais3, LOW);
      digitalWrite(relais4, LOW);
      digitalWrite(relais5, HIGH);
      digitalWrite(relais6, HIGH);
    }
}
  
void mode6() { //Loop 2+3
    digitalWrite(ledloop1, LOW);
    digitalWrite(ledloop2, HIGH);
    digitalWrite(ledloop3, HIGH);
    digitalWrite(ledand, HIGH);
    digitalWrite(ledor, LOW);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, LOW);
      digitalWrite(relais2, LOW);
      digitalWrite(relais3, HIGH);
      digitalWrite(relais4, HIGH);
      digitalWrite(relais5, HIGH);
      digitalWrite(relais6, HIGH);
    }
}
  
void mode7() { //Loop 1+2+3
    digitalWrite(ledloop1, HIGH);
    digitalWrite(ledloop2, HIGH);
    digitalWrite(ledloop3, HIGH);
    digitalWrite(ledand, HIGH);
    digitalWrite(ledor, LOW);
    if (modebypass == 0){
      digitalWrite(ledbypass, LOW);
      digitalWrite(relais1, HIGH);
      digitalWrite(relais2, HIGH);
      digitalWrite(relais3, HIGH);
      digitalWrite(relais4, HIGH);
      digitalWrite(relais5, HIGH);
      digitalWrite(relais6, HIGH);
    }
}

void eepromupdate() {
    EEPROM.update(0, modebypass);
    EEPROM.update(1, mode);
    EEPROM.update(2, lastandmode);
    EEPROM.update(3, lastormode);
}

void serialmonitor() { //Serial Monitor Debug
    //hier sind diverse Serial.print (gelöscht wegen 9000 Zeichen Limit)
}

noiasca


a) tritt das Problem auch auf, mit dem Sketch den du gepostet hast?
b) mach ein ZIP mit deinem echten Sktech. Du kannst ZIP Dateien anhängen.
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

combie

Mir scheint, dass deine Tastenentprellung überarbeitet werden sollte.


Was mir nicht gefällt?
Ich mag solche Durchnummerierungen nicht sonderlich.
Meist sind Arrays das Mittel der Wahl.
Auch kann man Blöcke mit Codewiederholungen oft zusammenfassen.




Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

noiasca

der combie wird wieder mal recht haben.

Holzhammer zum gegentesten:
Code: [Select]

if (debug == 1) serialmonitor() else delay(42);
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

uwefed

Den interessantesten Teil im
Code: [Select]
void serialmonitor() { //Serial Monitor Debug
    //hier sind diverse Serial.print (gelöscht wegen 9000 Zeichen Limit)
}

verheimlichst Du uns.
Darum können wir den Fehler nicht nachspielen weil wir den Sketch zum Kompilieren nicht haben. Außerdem wären die bei Dir auftretenden Fehlermeldungen auch interessant.
Den Sketch kannst Du in diesem Fall als Anlage mitschicken.

Meine Annahme: Du hast eine Funktion
Code: [Select]
void serialmonitor() { //Serial Monitor Debug
    //hier sind diverse Serial.print (gelöscht wegen 9000 Zeichen Limit)
}

die Serial.print macht. Diese, wegen der fehlenden Fehlermeldungen, glaube ich, geben Dir die Fehlermeldungen weil Du Serial.begin bedingt ausführst.

Mach die Debugausgaben mit "#ifdef". Dadurch wird der Sketch mit oder ohne Debugcode kompiliert.
zB
Code: [Select]

//Enable debug mode
#define debug
...
setup(){
#ifdef debug
  Serial.begin(9600);
#endif
...
}

loop()
{
...
#ifdef debug
  Serial.print("text"); ....
#endif
...
}


Zum Ausschalten der Debugausgaben setzt Du "#define debug" einfach als Komentar (mit "//").

So wird bei nichtgewollten Debug der Sketch ohne das Debugzeugs kompiliert und somit auch kleiner.

Grüße Uwe

janlieb89

Hi, danke schon jetzt für die zahlreichen, schnellen, ausführlichen Antworten und Vorschläge. Da ich gerade auf Arbeit bin, kann ich leider nicht probieren, aber immerhin den Sketch anhängen.

Hier der Sketch

Tommy56

Du kannst auch noch ein anderes Problem bekommen:

Du schreibst regelmäßig ins EEPROM. Das kann nur ca. 100.000 Schreibzyklen.
Wie oft Du Deine Taster betätigst, kannst nur Du wissen.

Ist das persistente Speichern über das Ausschalten hinaus überhaupt notwendig?
Evtl. solltest Du über einen FRAM nachdenken.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

janlieb89

Quote
Außerdem wären die bei Dir auftretenden Fehlermeldungen auch interessant.
ach ja, es treten keine Fehlermeldungen auf. Lediglich ist das Verhalten des Gerätes bei debug = 1 wie erwartet und gewünscht und bei debug = 0 relativ willkürlich, wie oben beschrieben.

bei debug = 0 ist mir vorhin noch aufgefallen, dass beispielsweise (weiss nicht in welcher Abhängigkeit) der bypass nicht mehr toggelt, sondern nur während des Tasterdrucks aktiv ist.

Ich kann nur betonen, dass das mysteriöse an der Geschichte ist, dass bei debug = 1 alles läuft.... :(

Quote
Mach die Debugausgaben mit "#ifdef". Dadurch wird der Sketch mit oder ohne Debugcode kompiliert.
Quote
Mir scheint, dass deine Tastenentprellung überarbeitet werden sollte.
Vorschläge werden heute abend getestet, danke schonmal :)

Quote
Du kannst auch noch ein anderes Problem bekommen:

Du schreibst regelmäßig ins EEPROM. Das kann nur ca. 100.000 Schreibzyklen.
Wie oft Du Deine Taster betätigst, kannst nur Du wissen.

Ist das persistente Speichern über das Ausschalten hinaus überhaupt notwendig?
Ja die Info hatte ich auch schon - Wäre halt ganz nett um den Modus zu behalten und mit wenigen Tastendrücken das Pedalboard in Betrieb zu bekommen. Müsste man mal probieren wie lange das gut geht...

combie

Quote
Wäre halt ganz nett um den Modus zu behalten und mit wenigen Tastendrücken das Pedalboard in Betrieb zu bekommen.
Naja....

So wie ich "Künstler" kenne, wird der Kram eingeschaltet, wenn sie in den Raum kommen, und abgeschaltet, wenn sie gehen.


Da könnte es doch reichen, alle 1/4H zu speichern.

Unveränderte Einstellungen zu speichern, ist kein Problem,
EEPROM.update() und damit auch EEPROM.put() wissen das abzuhandeln.

Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

uwefed

Was passiert wenn Du
debug = 0; setzt
UND
die Funktion "void serialmonitor()" total auskommentierst?
Grüße Uwe

janlieb89

Quote
Was passiert wenn Du
debug = 0; setzt
UND
die Funktion "void serialmonitor()" total auskommentierst?
Grüße Uwe
Das gleiche wirre Verhalten...

janlieb89

Hallo Leute,

vielen Dank für eure Hilfe!!!

Der Sketch läuft jetzt wie gewünscht.

Die Lösung war das entprellen der Tasten über delay(50) in der while Schleife und die #ifdef Sache. Daher besonderer Dank an combie und uwefed  :-*

Anbei der funktionierende Sketch, falls jemand noch Verbesserungen hat, gerne willkommen!

Ist das was ich im Sketch mit delay(50) gemacht hab richtig zum Tasten entprellen? (hab echt noch keinen Plan wie man das macht) - auf schnelle aufeinanderfolgende Tastendrücke reagiert das Programm nicht immer, aber ist nicht sooo schlimm.

DANKE DANKE DANKE

combie

Quote
Ist das was ich im Sketch mit delay(50) gemacht hab richtig zum Tasten entprellen?
Es war einfach nur ein Schnelltest, ob da das Problem steckt.
Wer seine Meinung nie zurückzieht, liebt sich selbst mehr als die Wahrheit.

Quelle: Joseph Joubert

uwefed

Ein kleines delay() kann als Entprellen funktionieren. Auch nur 5 bis 10mS.
Das Serial.print ist selbst blockierend und verlangsamt dadurch den Sketch und hat darum ungewollt und unbewußt den Taster entprellt.
Grüße Uwe


Go Up