Arduino Sequencer zu mehreren Entwickeln?

Hallo,

ich habe einen Hybrid aus 16step sequencer mit poti pro step und 8 track midi looper gebaut und
stoße bei einigen Programmieraufgaben an meine Grenzen.
Daher wär die Frage ob man solch ein Gerät nicht zu mehreren entwickeln kann.

Das Gerät steht soweit und die steps laufen durch, tempo lässt sich regeln usw.

Was ganz wichtig wäre das das teil zu einer mpc o.ä. synct, start/stop empfängt usw.

Da ich einen Computer job habe, ists mir doch zuviel am Wochenende auch noch n paar Stunden ins coden zu stecken.

Hat jemand Interesse daran?
 
habe gerade einen kompletten sequencer mit nem arduino mega gebaut, wenn ihr wollt kann ich mal ein video zeigen, und den code veröffentlichen
es ist ein 10 kanal trigger sequencer man kann die auflösung wechseln zwischen 32stel und 16tel, man kann 4 Takte programmieren und einstellen, zwischen welchen bars es im kreis läuft. dann kann man insgesamt 16 sequenzen mit jeweils 4 takten und 10 kanällen speichern, die dann auch wenn das gerät aus ist, gespeicher sind. und noch viel mehr so zeug wie z.b. takte kopieren und sequenzen kopieren. usw

edit: im endeffekt, kann man sich alle funktionen die man sich so vorstellen kann einfach dazu programmieren, es ist sozusagen ein kinderspiel.

ich hab auch einen clock eingang eingebaut, sodass man ihn synchron zu midi oder aderen systemen laufen lassen kann. außerdem kann man über usb komplette songstrukturen mit der software max arrangieren oder sich z.b. einen controller mit 16 fußtastern bauen, mit dem man auswählen kann welche von den 16 sequenzen laufen soll.. (für live performances auch als gitarrist oder so).

ich hatte keine ahnugn von digitalem, nur ein bisschen vom programmieren und es ist wirklich leicht. das schwierigste war die gehäusekonstruktion...

in verbindung mit shift registern und shcaltern kann man auch ganz leicht einen steuerspannungsequencer bauen. dessen takt von einem kanal des sequencers gesteuert wird.
 
wollte immer mal anfangen was mit arduino zu machen. hatte bis dato aber immer muffe .... wie schwer ist der einstig in s coden wirklich?
Gibt´s gute deutsche dokus dazu ? oder ist da auch alle auf englisch?
 
citric acid schrieb:
wollte immer mal anfangen was mit arduino zu machen. hatte bis dato aber immer muffe .... wie schwer ist der einstig in s coden wirklich?
Gibt´s gute deutsche dokus dazu ? oder ist da auch alle auf englisch?
Ardurino, also wenns wo massenhaft dokus gibt dann da, ist sozusagen die Kelly Family der Microcontroller-Umgebungen :mrgreen:
 
So, ich hatte mal wieder ein wenig Zeit und habe mir eine Frontplatte gebaut und alles verkabelt.
Gibt es hier jemanden der mir sagen kann ob meine Art den sequencer zu programmieren die passenden ist,
oder ist mein Ansatz schon falsch?

Der sequencer ist öfter instabil, scheint abzustürzen und die LED sind nicht immer im Sync zur gespielten Note.


Gruß
 

Anhänge

  • seq1.JPG
    seq1.JPG
    205,3 KB · Aufrufe: 238
  • seq2.JPG
    seq2.JPG
    123,4 KB · Aufrufe: 238
  • sequencer_2_8x.pde.zip
    1,8 KB · Aufrufe: 6
schreib hier mal den quelltext rein, habe auch einen mit dem arduino mega gebaut.
 
Die sourcen liegen in meine vorigen Beitrag.
Was ich mich ja frage ist wie ich die einzelnen Steps in eine Funktion packen dann,
dann muss ich nicht 8x 90% den selben code schreiben.

Ich habe gelesen das man für korrektes timing die function timer_start = millis(); nicht nehmen sollte,
habs aber nie geschaft das anders zu bauen,
 
Hi,
empfehle:
- Verwendung von Arrays um den Code zu komprimieren. Mit dem x in der loop() kannst Du indizieren, dann fällt der Overhead weg.
- das LED Ein/Ausschalten über einen TimerInterrupt zu steuern. Dazu gibts eine Lib auf der Arduino Homepage, MsTimer2.
Das verhindert, daß der gesamte Code angehalten wird, bloß um eine LED zu triggern. delay() ist Gift für den Programmablauf.

Beste Grüße
Burt
 
Hallo burt,

danke für den Tip mit den arrays, das hat den code sehr entschlackt.
Gibt es aber einen Grund warum die LEDs jetzt nur noch ganz schwach leuchten?
Das mit dem Interuppt muss ich mir noch anschauen.


EDIT:

sorry das mit den LEDs hat sich erldigt
 

Anhänge

  • sequencer_2_8x_array_func.pde.zip
    1,2 KB · Aufrufe: 6
also mach doch eine Variable "Timer" vom Typ long, der du bei jedem Step des Sequencers die aktuelle Zahl der vergangenen milli- oder microsekunden zuweist.
dann überprüfst du im loop ob, die differenz vom gespeichert wert und dem momentan Zustand an vergangenen Sekunden größer ist als dein gewünschtes zeitintervall.

das sieht dann ungefähr so aus:
Code:
unsigned long Timer = 0;
void loop() {
  if ((millis() - Timer) > 100) {
  //gib die spannungen oder die midi signale für step x aus...
    Timer = millis();
    if (step < 16) {  
      step++;
     } else {
      step = 0;
    }
  }
}
 
versteh ich noch nicht, schön wäre es ja mit richtigen BPM Werten arbeiten zu können, so das per default 120BPm gelten und ich dann
in Schritten rauf und runter gehen kann, da würde aber das delay für die LED noch stören.
 
Ich versuche gerade den Blink neu zu machen,
im beispiel werden die MStimer aufrufe in der function setup aufgerufen,
woher weiss ich denn dann welcher step gerade aktiv ist?
Wenn ich es in meine play function einbaue bekomme ich beim kompilieren einen Fehler:
Code:
sequencer_2_8x_array_func.cpp: In function »void playstep(int)«:
sequencer_2_8x_array_func.cpp:153: Fehler: falsche Benutzung eines void-Ausdruckes

wie gehts richtig?

Code:
void flash(int LED) {
  static boolean output = HIGH;
  
  digitalWrite(LEDpins[LED], output);
  output = !output;
}

void playstep(int stepnr) {

   if (currentSwitchState[stepnr] == 1) {
                AnalogValue = analogRead(stepnr);
                note = AnalogValue/8;
                noteOn(0xB0, 0x7B, 0x00);
                noteOn(0x90, note, 0x7F);
                
                MsTimer2::set(50, flash(stepnr)); // 500ms period
                MsTimer2::start();
//                digitalWrite(LEDpins[stepnr], HIGH);
//                delay(50);
//                digitalWrite(LEDpins[stepnr], LOW);
                delay(currentTime);
            } else {
              delay(currentTime);
            }

}
 
Nein, nein, freu dich an dem, was geht, und lass dir die Erfahrungen nicht entgehen! Ist immer besser als sie nicht zu machen. Und auch gemeinsames Werkeln ist wunderbar. Wollte nur die Ganzneulinge warnen, dass "Arduino geht einfach" (was sicher stimmt) nicht bedeutet, dass alles mit Arduino einfach geht.
Ohne-RTOS-Tip: Interrupts benutzen. Semaphoren, Queues und ähnliches Synchronisationszeug nach Bedarf selber bauen. Vielleicht reichts schon, also auch ohne Luxus wie Scheduler, Prioritäten, reentrante Speicherverwaltung. Erst wenn damit so gar nichts gleichzeitig zuverlässig UND tight werden will, wieder zu meinen Unkenrufen zurückblättern.
:peace:
 
Flub schrieb:
also mach doch eine Variable "Timer" vom Typ long, der du bei jedem Step des Sequencers die aktuelle Zahl der vergangenen milli- oder microsekunden zuweist.
dann überprüfst du im loop ob, die differenz vom gespeichert wert und dem momentan Zustand an vergangenen Sekunden größer ist als dein gewünschtes zeitintervall.

das sieht dann ungefähr so aus:
Code:
unsigned long Timer = 0;
void loop() {
  if ((millis() - Timer) > 100) {
  //gib die spannungen oder die midi signale für step x aus...
    Timer = millis();
    if (step < 16) {  
      step++;
     } else {
      step = 0;
    }
  }
}

rein logisch wird mir klar was du vorhast, aber mit dem umsetzen komm ich nicht klar.
Im grunde muss ich ja nur die 100 durch eine variable austauschen, das geht auch.
Nur macht der sequencer jetzt nach dem letzten step eine Pause, im moment habe ich 8 Steps.
Das anpassen der Variable currentTime geht auch noch nicht, das dürfte aber an der Verkabelung liegen.

Ich finds auch gut die for schleife los zu sein, macht mehr sinn so.

Code:
    if ((millis() - Timer) > currentTime) {
  
    Timer = millis();

    if (step < 8) {
       
       currentSwitchState[step] = digitalRead(switchPins[step]);
       playstep(step);  
       step++; 
     } else {
       step = 0;
    }
  }

dies ist der Code der die up/down Buttons abfragt:
Code:
 currentTimeState = digitalRead(timePin1);
      if (currentTimeState == 1) {
        currentTime = currentTime + 50;
      }

  currentTimeStateDown = digitalRead(timePin2);
      if (currentTimeStateDown == 1) {       
        if (currentTime <= 50) {
          currentTime = 100;
        } else {     
          currentTime = currentTime - 50;
        }
      }


Eine andere Frage ist ob ich den Bereich den der Poti abdeckt eingrenzen kann?
Wenn ich zu weit nach links oder rechts drehe kommt da nicht mehr viel, nur ein ultrahoher pitch oder das gegenteil.
 
Dein Code macht eine Pause, weil Du einen 'Leerdurchlauf' in der Schleife hast. Wenn Dein Zähler =8 ist und Du
auf 0 zurücksetzt, gibts kein playstep.

Die Potis beim Arduino gehen von 0-1023. Wenn Du den Bereich eingrenzen willst, dann dividiere
(oder schiebe rechts, ist wesentlich schneller) durch einen entsprechenden Skalierungsfaktor.
Beispiel: durch 4 dividieren (oder 2 nach rechts schieben), um auf Werte zwischen 0 und 256 zu kommen.
Um die kleinen Werte loszuwerden einen Offset dazuaddieren.
 
der macht mit diesem code immer noch eine pause :sad:
Code:
f (step < 8) {
       
       currentSwitchState[step] = digitalRead(switchPins[step]);
       playstep(step);  
       step++; 
     } else {
       currentSwitchState[step] = digitalRead(switchPins[step]);
       playstep(step);  
       step = 0;
    }
 
Ist zu erwarten, da Du jetzt einen 9ten step mit abspielst (index '8').
Stell Deinen Ablauf etwas um, so daß Du nach dem Hochzählen prüfst,
ob Deine Überlaufbedingung ( >= '8') eintritt, setze Deinen Zähler, falls
notwendig, auf 0.
 
mein vorgeschlagener code war anders aufgebaut.

vor der sache mit der bedingung für den step wird der aktuelle step verarbeitet, dann gibts auch keinen leerdurchlauf. ich habe in meinem code an der besagten stell kommentiert...
//gib die spannungen oder die midi signale für step x aus...
 
Flub schrieb:
mein vorgeschlagener code war anders aufgebaut.

vor der sache mit der bedingung für den step wird der aktuelle step verarbeitet, dann gibts auch keinen leerdurchlauf. ich habe in meinem code an der besagten stell kommentiert...
//gib die spannungen oder die midi signale für step x aus...


ah, das war damit gemeint, jetzt versteh ich das.
 
Hallo,
ich habe das programm jetzt delay frei(mit externer hilfe).
Nun wollte ich mich an daran setzen das timing einstellen zu können,
mein code lief schoneinmal, wenn ich jetzt aber den "up" button drücke bleibt der sequencer stehen
und schein abgestürzt.

Im grunde gibt es eine variable currentTime, diese will ich mit 2 up/down buttons regeln,
drückt man den up button werden 50ms hinzugefügt vice versa beim down button.
Sieht jemand hier warum das programm crasht?
Code:
void loop() {


//timing settings  
  currentTimeState = digitalRead(timePin1);
      if (currentTimeState == 1) {
        currentTime = currentTime + 50;
      }

  currentTimeStateDown = digitalRead(timePin2);
      if (currentTimeStateDown == 1) {       
        if (currentTime <= 50) {
          currentTime = 100;
        } else {     
          currentTime = currentTime - 50;
        }
      }
      
//play button action
  playState = digitalRead(playPin);
  
  if (playState != lastplayState) {
    
    // change the state of the led when someone pressed the button
    if (playState == 1) { 
      if(playing==1) {
        playing=0;
        noteOn(0xB0, 0x78, 0x00);
      } else { 
        playing=1;         
      }
    }
    // remember the current state of the button
    lastplayState = playState;
  }

//Main sequence
  if (playing == 1) {
    
  if ((millis() - Timer) > currentTime) {
  
    Timer = millis();
    currentSwitchState[step] = digitalRead(switchPins[step]);
    playstep(step); 
    if (step < 7) {
      step++; 
    } else {
      step = 0;
    }
  }
}   
    

}
 
ich denke mal du benutzt Drucktaster. Wenn ja solltest du sie wie folgt in der Setup Funktion vorbereiten um den internen pullup widerstand für die Taster zu benutzen.

pinMode(ButtonPin, INPUT);
digitalWrite(ButtonPin, HIGH);

Der Normalzustand am ButtonPin ist jetzt also HIGH, wenn du drückst ist der PIn LOW.

wenn du im loop jetzt überprüfst, ob der button gedrückt wurde oder nicht (if (digitalRead(ButtonPin) == LOW) {}) ), musst du bedenken, das die abläufe ja sehr schnell sind, bei 16Mhz macht der 16 Millionen Mal pro sekunde was, das heißt du würdest bei einem Tastendruck die Aktion, die eigentlich nur einmal für jeden Tastendruck geschehen soll, viel öfters als gewollt ausführen. Das heißt du brauchst noch eine Variable angibt, ob die taste zwischenzeitlich schon losgelassen wurde, sodass du nicht alles öfters ausführst.

also die variable definieren : z.b.

boolean button_ok = true;

im loop dann...:

if (digitalRead(ButtonPin)== LOW) {
(if (button_ok == true) {
mach was...
}
button_ok = false;
} else {
button_ok = true; // wenn digitalRead nicht LOW war
}

jetzt ist sozusagen fast alles schon und gut, dann muss der taster nur noch entprellt werden, weil du sonst ganz oft doppel oder dreifach trigger hast.
guck bei den arduino tutorials nach "debouncing"
 
mir fällt gerade auf das wenn ich nur die ersten 4 steps aktiviert habe das der sequencer dann für die nicht aktiven steps ne pause macht, kann
man das so einrichten das er diese steps dann überspringt?

Ich habe schon versucht currentSwitchState auf 1 zu püfen und wenn nicht dann soll er step++ machen, das hat aber nicht geholfen :sad:
Code:
 if (playing == 1) {
    
    if ((millis() - Timer) > currentTime) {
      Timer = millis();
      currentSwitchState[step] = digitalRead(switchPins[step]);
      playstep(step);
      
      if (step < 7) {
        step++; 
      } else {
        step = 0;
      }
    }
}
Code:
      if(currentSwitchState[step] == 0) {
        step++;
oder muss ich ich da dort ein break oder sowas einbauen?

EDIT:

Moment, eigentlich will ich die pausen ja haben, macht ja den groove ein wenig aus...
Einzig eine 2x8 option solls irgentwann geben
 
Welcher wertebereich für den pitch ist den Sinnvoll,
im Moment teile ich die 1024 durch 8, was aber mindestnes das erste und letzte viertel in
extreme Tonlagen bringt.
Ich habe auch schon durch 16 geteilt und den start auf 32 und mehr hochgesetzt,
ganz zufrieden war ich damit auch nicht.
Ist dieser Bereich bei allen synth gleich? also 0-128?

Code:
note[stepnr] = AnalogValue[stepnr]/8;
 
Dann wundert es mich das ich mit meine 128 schon so tief/hoch komme, 14bit wären ja 16.384.

Da ich jetzt in der Modularwelt angekommen bin frage ich mich ob ich in den arduino einen cv/gate einbauen soll oder
das einfach per Midi->CV Interface regeln kann, da fehlt mir die Erfahrung.
 


News

Zurück
Oben