IDLE HANDS

Comments

RSS feed for comments on this post.

The URL to TrackBack this entry is: http://www.larsby.com/johan/wp-trackback.php?p=9

  1. Hi, I am very interesed to make this. Can you give a bit more detailed info about the :
    connections between lcd and arduino
    ?

    Thank you.

    Regards,
    /M.Q.

    Comment by Meng Qi — December 9, 2009 @ 3:58 am

  2. I just followed the tutorials on arduino.cc with the crystal library.

    Comment by Johan Larsby — December 9, 2009 @ 6:38 pm

  3. Cool, thank you for reply.
    I’ll go and have a check, if I have other questions I will come back and post here.

    Thank you for the help.

    Regards,
    /M.Q.

    Comment by Meng Qi — December 10, 2009 @ 7:17 am

  4. it power up.. but the encoder does nothing…i´ve uploaded all files and connect like your schematic..

    Comment by Leandro — March 18, 2010 @ 6:18 pm

  5. Hmmm, maybe you should dumb it down a bit so that it only takes the encoder data?

    Comment by Johan Larsby — March 18, 2010 @ 8:43 pm

  6. Done that too… and nothing.. only one line, but but the scond appear once but don´t know why.. i´m getting other display but keep trying.. Can you guive me a more detailed schematic? Thanks

    Comment by Leandro — March 19, 2010 @ 7:49 am

  7. Would you consider selling pre programed chips so all we need to do is assemble the device? That and a simple schematic would enable a lot more of us to assemble it

    Comment by Don Preston Mothers — May 3, 2010 @ 9:38 am

  8. The chip is the arduino, and it is dead easy to program.

    the schematics could be improved, I concur.

    Comment by Johan Larsby — May 8, 2010 @ 5:45 pm

  9. is the tempo programmable in the current configuration, or is that just something you intend to do on a future project? I wwould love to build an arduino step sequencer like yours but tempo is very important to have control over for my music.

    Comment by Frank — September 14, 2010 @ 10:03 pm

  10. I have build this project succesfully but not after some changes due to a different lcd and some minor changes in the code to get it all working. I only think the red marked stripe in the schematic at the rotary encoder should be black (ground) If there are people intrested I would like to hear from you. I used an anag vision AV1624. This lcd needs an extra row of code lcd.begin(16, 2) to activate both rows, as some people seem to have problems with this issue.

    Comment by Magellan — October 10, 2010 @ 12:31 am

  11. How precise is your stepper?
    Mine drifts off. After 3,5 beats it is a 1/16th off already… compared to my DAW.

    Comment by Michael — October 10, 2010 @ 4:59 am

  12. My encoder I think you mean this by stepper is a ‘Alps stec12E07′ here you can see a picture of it. btw it’s available from more shops. http://shop.conrad.nl/componenten/schakelaars-toetsen/schakelaars-toetsen-overig/speciale-schakelaars/700701.html And as I mentioned I connected the wiper to the ground and the other two connections to pin 8 and 9 of the arduino due to my different layout of the lcd. And this works fine for me no drift at all.

    Comment by Magellan — October 10, 2010 @ 2:25 pm

  13. there could be drift depending on the type of arduino you’re using.
    what version of atmega are you utilizing?

    also, I’m so happy that there are ppl building this, I never thought that would happen!

    Comment by Johan Larsby — October 10, 2010 @ 2:40 pm

  14. I am using an Arduino Duemilanove. Oh and btw there are not so many projects out there that do realtime midi sequencing. Most of them sequence CV. And if you like I could make a better readable schematic. Let me know.

    Comment by Magellan — October 10, 2010 @ 3:10 pm

  15. The atmega on the board reads ‘atmel 1005
    atmega 328P PU’

    Comment by Magellan — October 10, 2010 @ 3:11 pm

  16. Magellan, a better schematic would be greatly appreciated by not only me I think. I’ll update my post to it and also a link to you if you want it.

    Comment by Johan Larsby — October 10, 2010 @ 8:39 pm

  17. I’ll work it out within a few days and I let you know when it’s finished. No problem at all.

    Comment by Magellan — October 10, 2010 @ 11:24 pm

  18. Good stuff, I’ll be eagerly awaiting :)

    Comment by Johan Larsby — October 11, 2010 @ 8:42 am

  19. The schematic is available on a temporay website where you can download it and if you like you can update it in your post. If there are some changes needed please let me know.
    https://sites.google.com/site/interactivesequencing/home

    Comment by Magellan — October 16, 2010 @ 1:37 am

  20. would it be possible to have two sequence lines on a 16×4 display. I have some problems using 2 encoders everytime i program a second one nothing happens when I turn one of the encoders only when one is connected it seems no problem. Do I need to include the library twice? Can somebody help to figure this out? Thanks

    Comment by Magellan — October 20, 2010 @ 10:48 pm

  21. It is possible yes.
    How do you initialize the second encoder?
    Could you paste that code?

    Comment by Johan Larsby — October 21, 2010 @ 7:46 am

  22. To be honest I am more into schematics and building things in the analog way. I know a bit of programming but this whole arduino thing is not completly new but I have to learn a lot I know that for sure. I simply added a line of code Rotaryencoder2 and set it on the free lines 6 and 10(in my case) then I did the same for everything else in the program like notes channels velocity step lenght etc. etc. Copied it added a number 2 to it and the program compiled actually perfectly without errors. But the encoders did not work anymore. I actually got to sequence lines on the display so I tought that everything was allright so far. I know that I have to initialize the second encoder but do not know how to do that to be honest. Maybe I am thinking a bit to easy about this but you have to start somewhere and since I got this project perfectly working as discribed on this website I thought that I could learn more from it.

    Comment by Magellan — October 21, 2010 @ 11:34 pm

  23. Magellan, your solutions should work fine.

    Just send it to me in an email and I’ll have a look at it!

    /Johan

    Comment by Johan Larsby — October 24, 2010 @ 1:06 pm

  24. Here’s the complete code as I tried it,
    it compiles without errors in Arduino 0021 but gives a fail 255 on the display for whatever that means. (the board I’m using is a dueminalove)

    /*

    Arduino Step Sequencer

    */

    #include
    #include “rotaryEncoder.h”

    /*
    make video

    upload
    PROFIT!

    */

    #define usesMidi 1 /*enable this if you want to send midi, doesent work at all together with Serial.print debugging */
    #define debugprint 0 /*this sends midi messages as text instead */

    LiquidCrystal lcd(12, 11, 7, 5, 4, 3, 2); /* Utilizing the liquidcrystal library for the screen, this is a setup-call*/

    RotaryEncoder rotary1(8, 9); /*sweet sweet library that solves a lot of problems, I made a few changes to the original one */
    RotaryEncoder rotary2(10, 13);

    /*defines for the buttons */
    #define menuButton 14
    #define onOffButton 15
    #define lengthButton 16
    #define velocityButton 17
    #define playPuaseButton 18
    #define noteButton 19

    /*booleans to tell me if the buttons are pressed or not */
    byte menuButtonIsPressed =0;
    byte onOffButtonIsPressed =0;
    byte lengthButtonIsPressed =0;
    byte velocityButtonIsPressed =0;
    byte playPuaseButtonIsPressed =0;
    byte noteButtonIsPressed =0;

    /*useful state variables */
    byte currentlyPlaying1 =0;
    byte currentlyEditing1 =0;
    boolean isPlaying1=true;
    byte currentlyPlaying2 =0;
    byte currentlyEditing2 =0;
    boolean isPlaying2=true;

    /*channel and instrument are for the midi messages */
    byte channel1 = 0;
    byte instrument1 = 0;
    byte channel2 = 0;
    byte instrument2 = 0;

    byte tempo1=120; /* bmp of our sequence */
    long timeChange1=250; /*a variable for calculating how long we are going to wait*/
    byte tempo2=120; /* bmp of our sequence */
    long timeChange2=250; /*a variable for calculating how long we are going to wait*/

    /*a struct for our notes in our sequence*/
    struct data
    {
    byte velocity1;
    byte onOff1;
    byte length1;
    byte note1;
    byte velocity2;
    byte onOff2;
    byte length2;
    byte note2;
    };

    int numberofsteps1 = 8; /* at first we have 8 steps, this is pretty basic */
    #define maxNumberOfSteps1 17 /*that’s 16*/

    data myData1[maxNumberOfSteps1]; /*array for our notes*/

    int numberofsteps2 = 8; /* at first we have 8 steps, this is pretty basic */
    #define maxNumberOfSteps2 17 /*that’s 16*/

    data myData2[maxNumberOfSteps2]; /*array for our notes*/

    /*remembering the good old times*/
    long rememberMillis1=0;
    long rememberMillisDisplay1=0;
    long rememberMillis2=0;
    long rememberMillisDisplay2=0;

    /*we’d like to present notenames instead of midi numbers */
    char* noteNames1[] = {
    “C”, “C#”, “D”, “D#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “A#”, “B” };
    char* noteNames2[] = {
    “C”, “C#”, “D”, “D#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “A#”, “B” };

    void setup()
    { // set up the LCD’s number of columns and rows:
    lcd.begin(16, 4);
    // Print a message to the LCD.
    lcd.setCursor(4, 1);
    lcd.print(“Startup”);
    lcd.setCursor(-2, 2);
    lcd.print(“version 1.01″);
    delay(1000);
    lcd.clear();
    /*telling everybody we’re alive */
    lcd.setCursor(2, 1);
    lcd.print(“Arduino Step”);
    lcd.setCursor(-1, 2);
    lcd.print(“sequencer”);
    delay(1000);

    /*setting up the buttons */
    pinMode(menuButton,INPUT);
    pinMode(onOffButton,INPUT);
    pinMode(lengthButton,INPUT);
    pinMode(velocityButton,INPUT);
    pinMode(playPuaseButton,INPUT);
    pinMode(noteButton,INPUT);

    /*starting the builtin pullup-resistor!*/
    digitalWrite(menuButton,HIGH);
    digitalWrite(onOffButton,HIGH);
    digitalWrite(lengthButton,HIGH);
    digitalWrite(velocityButton,HIGH);
    digitalWrite(playPuaseButton,HIGH);
    digitalWrite(noteButton,HIGH);

    /*initialization of the encoder library */
    rotary1.position(0);
    rotary2.position(0);

    #if usesMidi
    Serial.begin(31250);
    #else
    Serial.begin(9600);
    #endif

    /*calculating the timeChange variable. milliseconds divided by
    tempo and 16th note, or something like that. I dont remember*/
    timeChange1=((60000/tempo1)/8);
    timeChange2=((60000/tempo1)/8);

    /*initializing the steps in the array */
    for(int i=0;i<maxNumberOfSteps1;i++)
    {
    myData1[i].note1=48+i;
    myData1[i].velocity1=120;
    myData1[i].onOff1=1;
    myData1[i].length1=4;
    myData2[i].note1=48+i;
    myData2[i].velocity1=120;
    myData2[i].onOff1=1;
    myData2[i].length1=4;
    }

    lcd.clear();

    /*what time is now*/

    rememberMillis1 = millis();
    rememberMillisDisplay1 = millis();
    rememberMillis2 = millis();
    rememberMillisDisplay2 = millis();
    }

    /* a little function to print the name of the note */
    void printNoteName(byte initialNote)
    {
    byte octave1 = (initialNote / 12) – 1;
    byte noteIndex1 = (initialNote % 12);
    byte octave2 = (initialNote / 12) – 1;
    byte noteIndex2 = (initialNote % 12);

    lcd.setCursor(0, 0);
    lcd.print(noteNames1[noteIndex1]);
    lcd.print(octave1,DEC);
    lcd.setCursor(-4, 2);
    lcd.print(noteNames2[noteIndex2]);
    lcd.print(octave2,DEC);

    }
    /* this functions prints what we have in the first "menu" part of the data
    tempo, channel and instrument*/
    void populateDisplayMenuButtonPressed()
    {

    lcd.setCursor(0, 0) ;

    lcd.print("t:");
    lcd.print(tempo1,DEC);
    lcd.print(" c:");
    lcd.print(channel1,DEC);
    lcd.print(" i:");
    lcd.print(instrument1,DEC);

    lcd.setCursor(-4, 2) ;

    lcd.print("t:");
    lcd.print(tempo2,DEC);
    lcd.print(" c:");
    lcd.print(channel2,DEC);
    lcd.print(" i:");
    lcd.print(instrument2,DEC);

    if (!isPlaying1)
    if (!isPlaying2)
    {
    lcd.setCursor(0, 1) ;
    lcd.print("PAUSED ");
    lcd.setCursor(-4, 2) ;
    lcd.print("PAUSED ");
    }
    else
    {
    lcd.setCursor(0, 1) ;
    for(int i=0;i<numberofsteps1;i++)
    {
    if(i==currentlyPlaying1 && i==currentlyEditing1 )
    lcd.print("+");
    else if(i==currentlyEditing1)
    lcd.print("-");
    else if(i==currentlyPlaying1)
    lcd.print("|");
    else
    lcd.print(".");

    }
    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */
    for(int i=numberofsteps1;i< maxNumberOfSteps1 ;i++)
    {
    lcd.print(" ");

    }
    }
    {
    lcd.setCursor(-4, 3) ;
    for(int i=0;i<numberofsteps2;i++)
    {
    if(i==currentlyPlaying2 && i==currentlyEditing2 )
    lcd.print("+");
    else if(i==currentlyEditing2)
    lcd.print("-");
    else if(i==currentlyPlaying2)
    lcd.print("|");
    else
    lcd.print(".");

    }
    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */
    for(int i=numberofsteps2;i< maxNumberOfSteps2 ;i++)
    {
    lcd.print(" ");

    }
    }
    }

    /*this is the normal/regular display info printing routine */
    void populateDisplay()
    {

    lcd.setCursor(0, 0) ;
    if(isPlaying1)
    {
    printNoteName(myData1[currentlyEditing1].note1);
    lcd.print(" ");
    /*On if the note is On, Off it is Off, getting it? getting on or getting off, muhahahaha */
    if(myData1[currentlyEditing1].onOff1)
    lcd.print("On");
    else
    lcd.print("Off");

    lcd.print(" ");
    {
    /*what kind of note what we are dealing with */
    switch (myData1[currentlyEditing1].length1)
    {
    case 1:
    lcd.print("32nd");
    break;
    case 2:
    lcd.print("16th");
    break;
    case 3:
    lcd.print("8th");
    break;
    case 4:
    lcd.print("4th");
    break;
    case 5:
    lcd.print("2nd");
    break;
    case 6:
    lcd.print("whole");
    break;
    default:
    lcd.print("FAIL");
    break; /*we made bu bu*/
    }
    }
    lcd.print(" ");

    lcd.print(myData1[currentlyEditing1].velocity1,DEC);
    lcd.print(" ");

    lcd.setCursor(0, 1) ;
    for(int i=0;i<numberofsteps1;i++)
    {
    if(i==currentlyPlaying1 && i==currentlyEditing1 )
    lcd.print("+");
    else if(i==currentlyEditing1)
    lcd.print("-");
    else if(i==currentlyPlaying1)
    lcd.print("|");
    else
    lcd.print(".");
    }

    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */

    for(int i=numberofsteps1;i< maxNumberOfSteps1 ;i++)
    {
    lcd.print(" ");

    }

    }
    else
    {
    lcd.setCursor(0, 1) ;
    lcd.print("PAUSED ");
    }
    lcd.setCursor(-4, 2) ;
    if(isPlaying2)
    {
    printNoteName(myData2[currentlyEditing2].note2);
    lcd.print(" ");
    /*On if the note is On, Off it is Off, getting it? getting on or getting off, muhahahaha */
    if(myData2[currentlyEditing2].onOff2)
    lcd.print("On");
    else
    lcd.print("Off");

    lcd.print(" ");
    {
    /*what kind of note what we are dealing with */
    switch (myData2[currentlyEditing2].length2)
    {
    case 1:
    lcd.print("32nd");
    break;
    case 2:
    lcd.print("16th");
    break;
    case 3:
    lcd.print("8th");
    break;
    case 4:
    lcd.print("4th");
    break;
    case 5:
    lcd.print("2nd");
    break;
    case 6:
    lcd.print("whole");
    break;
    default:
    lcd.print("FAIL");
    break; /*we made bu bu*/
    }
    }
    lcd.print(" ");

    lcd.print(myData2[currentlyEditing2].velocity2,DEC);
    lcd.print(" ");

    lcd.setCursor(0, 1) ;
    for(int i=0;i<numberofsteps2;i++)
    {
    if(i==currentlyPlaying2 && i==currentlyEditing2 )
    lcd.print("+");
    else if(i==currentlyEditing2)
    lcd.print("-");
    else if(i==currentlyPlaying2)
    lcd.print("|");
    else
    lcd.print(".");
    }

    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */

    for(int i=numberofsteps2;i 100)
    if( millis()-rememberMillisDisplay2 > 100)
    {
    rememberMillisDisplay1=millis();
    checkButtons();
    if (!menuButtonIsPressed)
    populateDisplay();
    rememberMillisDisplay2=millis();
    checkButtons();
    if (!menuButtonIsPressed)
    populateDisplay();
    else
    populateDisplayMenuButtonPressed();
    }

    if(isPlaying1)
    if(isPlaying2)
    {

    if( millis()-rememberMillis1 > ((myData1[currentlyPlaying1].length1 * myData1[currentlyPlaying1].length1 )*(timeChange1)))
    if( millis()-rememberMillis2 > ((myData1[currentlyPlaying2].length2 * myData1[currentlyPlaying2].length2 )*(timeChange2)))
    {
    //fuck it, we always send off, most MIDI devices wont crap themselves.
    sendMidiMessage(0×80, myData1[currentlyPlaying1].note1,120); //off
    sendMidiMessage(0×80, myData2[currentlyPlaying2].note2,120);

    currentlyPlaying1++;
    if (currentlyPlaying1==numberofsteps1)
    currentlyPlaying1=0;
    currentlyPlaying2++;
    if (currentlyPlaying2==numberofsteps2)
    currentlyPlaying2=0;

    rememberMillis1=millis();
    rememberMillis2=millis();

    if( myData1[currentlyPlaying1].onOff1)
    sendMidiMessage(0×90, myData1[currentlyPlaying1].note1, 120); //on
    if( myData2[currentlyPlaying2].onOff1)
    sendMidiMessage(0×90, myData2[currentlyPlaying2].note2, 120);

    }
    }

    }

    /* This functions makes almost all our values be more correct.
    like, we dont want negative values or out of range values */
    void SanitizeValues()
    {

    myData1[currentlyEditing1].onOff1= myData1[currentlyEditing1].onOff1 % 2; //setting the current value to be inbetween 0 and 1
    myData1[currentlyEditing1].note1= myData1[currentlyEditing1].note1 % 128; //setting the current value to be inbetween 0 and 127
    myData1[currentlyEditing1].velocity1= myData1[currentlyEditing1].velocity1 % 128; //setting the current value to be inbetween 0 and 127
    currentlyEditing1=(currentlyEditing1 % (numberofsteps1));
    isPlaying1 = isPlaying1%2;

    myData1[currentlyEditing2].onOff2= myData2[currentlyEditing2].onOff2 % 2; //setting the current value to be inbetween 0 and 1
    myData1[currentlyEditing2].note2= myData2[currentlyEditing2].note2 % 128; //setting the current value to be inbetween 0 and 127
    myData1[currentlyEditing2].velocity2= myData2[currentlyEditing2].velocity2 % 128; //setting the current value to be inbetween 0 and 127
    currentlyEditing2=(currentlyEditing2 % (numberofsteps2));
    isPlaying2 = isPlaying2%2;

    if(numberofsteps1 > maxNumberOfSteps1)
    numberofsteps1=maxNumberOfSteps1;
    if(numberofsteps2 > maxNumberOfSteps2)
    numberofsteps2=maxNumberOfSteps2;

    if(numberofsteps1 < 0)
    numberofsteps1=0;
    if(numberofsteps2 6)
    myData1[currentlyEditing1].length1=6;
    if(myData1[currentlyEditing2].length2 > 6)
    myData2[currentlyEditing2].length2=6;

    if(myData1[currentlyEditing1].length1 < 1)
    myData1[currentlyEditing1].length1=1;
    if(myData2[currentlyEditing2].length2 < 1)
    myData2[currentlyEditing2].length2=1;

    }
    else if(velocityButtonIsPressed)
    myData1[currentlyEditing1].velocity1+=encoder0Pos1;
    else if(velocityButtonIsPressed)
    myData2[currentlyEditing2].velocity2+=encoder0Pos2;
    else if(playPuaseButtonIsPressed)
    isPlaying1+=encoder0Pos1;
    else if(playPuaseButtonIsPressed)
    isPlaying2+=encoder0Pos2;

    else
    currentlyEditing1+=encoder0Pos1;
    currentlyEditing2+=encoder0Pos2;
    }

    rotary1.position(0);
    rotary2.position(0);
    SanitizeValues();
    }

    void sendMidiMessage(char cmd, char data1, char data2)
    {

    #if debugprint
    Serial.print("Sending MIDI ");
    Serial.print(cmd,DEC);
    Serial.print(" ");
    Serial.print(data1,DEC);
    Serial.print(" ");
    Serial.println(daserial.pta2,DEC);
    #endif
    //not sending channel or instrument change yet…
    #if usesMidi
    Serial.print(cmd, BYTE);
    Serial.print(data1, BYTE);
    Serial.print(data2, BYTE);
    #endif
    }

    Comment by Magellan — October 25, 2010 @ 10:32 pm

  25. Hello,

    I am currently making this projet for my semester project in college. I tried compiling the code but I got an error that had to do something with the .cpp file:

    C:\Documents and Settings\ElectroCSL\Bureau\arduino-0021\libraries\rotaryEncoder\rotaryEncoder.cpp:11:10: error: #include expects “FILENAME” or
    C:\Documents and Settings\ElectroCSL\Bureau\arduino-0021\libraries\rotaryEncoder\rotaryEncoder.cpp:12:10: error: #include expects “FILENAME” or
    C:\Documents and Settings\ElectroCSL\Bureau\arduino-0021\libraries\rotaryEncoder\rotaryEncoder.cpp:66: error: expected constructor, destructor, or type conversion before ‘(‘ token

    Also, I don’t know if I was doing it wrong but from what I understand, I created new .h and .cpp files and copy pasted the code you provided. I put both files in the libraries folder in a new folder called rotaryEncoder. Is this the right way to use the .h and .cpp files?

    My versions of this sequencer will be made with the 4×4 sparkfun button pads and I got RGB LEDs to light up the buttons…it will be a pain in the bum to program the lights -_-

    Thanks!

    -Carlos

    Comment by Carlos — October 25, 2010 @ 10:42 pm

  26. @Carlos the encoder files should be in the same directory as the ass.pde file.

    @Magellan this was my fault, sorry, I should have rememberd. You cant make a new encoder like that. If you have a look into the encoder.cpp file you see that there is an interrupt at work. That can only be used once. My suggestion would be to change the library file to take in stuff for one more encoder. I could do that for you if you want.

    Comment by Johan Larsby — October 26, 2010 @ 7:36 am

  27. It would be great if it would not be to much work for you to change the library file so I can use a second encoder. Alltough I’m not sure how my final step sequencer would look like I actually added a midi clock to the code that works fine and I am trying to use the midi input to transpose the running sequence into the key depressed on a midi keyboard. I think that this must be possible. I’ll let you how I’m progressing.

    Comment by magellan — October 26, 2010 @ 9:47 pm

  28. Hmm after including both files in the ass.pde directory, I still get the

    rotaryEncoder.cpp:64: error: expected constructor, destructor, or type conversion before ‘(‘ token

    error which points me to

    ISR (TIMER2_OVF_vect)

    at the bottom of the .cpp file

    Comment by Carlos — October 27, 2010 @ 5:36 pm

  29. sorry I havent been around as much lately.

    did you get it to work carlos? or do you want a zip with the files that worked for me?

    if that is the case gimme you’re email.

    @magellan would you still like me to give that a shoot? making a dual encoder version?

    Comment by Johan Larsby — November 4, 2010 @ 1:43 pm

  30. I would really appreciate if you would like to give it a shoot. Two midi lines would be great to work with. Hopefully when I see the differnce between one encoder and two encoders I understand the working of the whole concept. I really don’t know where to start. So it would be great if you have some time to give it a shoot.
    - thanks

    maggelan

    Comment by magellan — November 8, 2010 @ 10:01 am

  31. Nah I did not get it to work. A zip file would be very appreciated!

    csanchez126@gmail.com

    Comment by Carlos — November 10, 2010 @ 2:39 am

  32. Would i be using normally closed pushbuttons or normally open Pushbuttons in this build? or would it matter?

    Comment by Frank — November 12, 2010 @ 8:13 pm

  33. the pushbuttons are normaly open.

    /magellan

    Comment by Magellan — November 13, 2010 @ 12:50 am

  34. is the 10k resistor on the schematic a potentiometer?

    Comment by Frank — November 16, 2010 @ 6:07 pm

  35. yes this is a potentiometer to adjust the contrast from the display.

    /magellan

    Comment by magellan — November 16, 2010 @ 9:51 pm

  36. Hello guys.. I am so glad i found this page. I just ordered a Arduino Mega 1280 and a LCD Shield. I want to build something similar to this. I am completely new to Arduino. I am very interested in sounds and did already built a fully modded x0xb0x and a midibox sid Mb-6582. Is there already a code that has implemented a midi clock where you could define the BPM ? I have to wait till i get my Arduino to start testing out what i see so far as my understanding is in the real early phase yet. I hope i can get hold of the logic behind arduino coding soon.
    Thank you guys

    Comment by izze — November 19, 2010 @ 7:29 pm

  37. as the analogue inputs on an arduino are translated to the microcontroller as a number between o and 1024 to create a tempo control set an algorythm to assign a value range of your usable tempos by saying integer tempo=(analogue in)/5) +45) (this gives you approximately 45-250)

    then apply that to the clock of your program by telling the program to do whatever in that time by an algorythm to your microcontroller by either a line of code that multiplies (microcontroller clock time in processes per second)times 60 (to give you a minute) and then divide each of these minutes by the tempo should give a loop repeating at a bpm timing for the program. I’m no good at actually writing in arduino language but that should be an algorythm that should work using any language

    Comment by Frank — November 21, 2010 @ 7:28 am

  38. Hey, Ive been trying to this together but have trouble in arduino with the library rotary.h . not really sure if I’m installing the library right?
    Is there anyway I could get a zip of this program too?

    Comment by Wilson — January 3, 2011 @ 3:42 am

  39. What is suppose to be going on with this code?

    for(int i=0;iif(i==currentlyPlaying && i==currentlyEditing )
    lcd.print(“+”);
    else if(i==currentlyEditing)
    lcd.print(“-”);
    else if(i==currentlyPlaying)
    lcd.print(“|”);
    else
    lcd.print(“.”);

    Comment by Wilson — January 8, 2011 @ 1:50 am

  40. Hello again,

    I’ve still been trying to get this sequencer work with more than one channel and now with one rotary encoder. What I tried is to write the data in to (to start with) two arrays. I don,t get any errors when I compile but it is not working on the hardware. Can anyone tell me if my ideas can work or that it is simply not possible.

    Thanks for any support.
    /magellan
    /*

    Arduino Step Sequencer

    */

    #include
    #include “rotaryEncoder.h”
    #include
    #include
    #include
    MidiClass Midi;

    /*
    make video

    upload
    PROFIT!

    */

    #define usesMidi 1 /*enable this if you want to send midi, doesent work at all together with Serial.print debugging */
    #define debugprint 0 /*this sends midi messages as text instead */

    LiquidCrystal lcd(12, 11, 7, 5, 4, 3, 2); /* Utilizing the liquidcrystal library for the screen, this is a setup-call*/

    RotaryEncoder rotary(8, 9); /*sweet sweet library that solves a lot of problems, I made a few changes to the original one */

    /*defines for the buttons */
    #define menuButton 14
    #define onOffButton 15
    #define lengthButton 16
    #define velocityButton 17
    #define playPauseButton 18
    #define noteButton 19
    int ledPin = 13;

    /*booleans to tell me if the buttons are pressed or not */
    byte menuButtonIsPressed =0;
    byte onOffButtonIsPressed =0;
    byte lengthButtonIsPressed =0;
    byte velocityButtonIsPressed =0;
    byte playPauseButtonIsPressed =0;
    byte noteButtonIsPressed =0;

    /*useful state variables */
    byte currentlyPlaying =0;
    byte currentlyEditing =0;
    boolean isPlaying=true;

    /*channel and instrument are for the midi messages */
    byte channel=0;
    byte instrument =0;

    byte tempo=120; /* bmp of our sequence */
    long timeChange=250; /*a variable for calculating how long we are going to wait*/

    /*a struct for our notes in our sequence*/
    struct data
    {
    byte velocity;
    byte onOff;
    byte length;
    byte note;
    };

    int numberofsteps = 8; /* at first we have 8 steps, this is pretty basic */
    #define maxNumberOfSteps 17 /*that’s 16*/

    data myData[maxNumberOfSteps];/*array for our notes*/
    data myData1[maxNumberOfSteps];/*array for our notes*/

    int track = 1;
    #define maxtrack 17

    data myData100[maxtrack];

    /*remembering the good old times*/
    long rememberMillis=0;
    long rememberMillisDisplay =0;

    /*we’d like to present notenames instead of midi numbers */
    char* noteNames[] = {
    “C”, “C#”, “D”, “D#”, “E”, “F”, “F#”, “G”, “G#”, “A”, “A#”, “B” };

    void setup()
    {

    pinMode(ledPin, OUTPUT);
    MidiUart.init();
    MidiClock.mode = MidiClock.INTERNAL_MIDI;
    MidiClock.setTempo(tempo);
    MidiClock.transmit = true;
    MidiClock.setOn16Callback(on16Callback);
    MidiClock.start();
    // set up the LCD’s number of columns and rows:
    lcd.begin(16, 2);
    // Print a message to the LCD.
    lcd.print(” Startup”);
    lcd.setCursor(0, 1);
    lcd.print(” version 1.01″);
    delay(1000);
    lcd.clear();
    /*telling everybody we’re alive */
    lcd.print(” Arduino Step”);
    lcd.setCursor(0, 1);
    lcd.print(” sequencer”);
    delay(1000);

    /*setting up the buttons */
    pinMode(menuButton,INPUT);
    pinMode(onOffButton,INPUT);
    pinMode(lengthButton,INPUT);
    pinMode(velocityButton,INPUT);
    pinMode(playPauseButton,INPUT);
    pinMode(noteButton,INPUT);

    /*starting the builtin pullup-resistor!*/
    digitalWrite(menuButton,HIGH);
    digitalWrite(onOffButton,HIGH);
    digitalWrite(lengthButton,HIGH);
    digitalWrite(velocityButton,HIGH);
    digitalWrite(playPauseButton,HIGH);
    digitalWrite(noteButton,HIGH);

    /*initialization of the encoder library */
    rotary.position(0);

    #if usesMidi
    Serial.begin(31250);
    #else
    Serial.begin(9600);
    #endif

    /*calculating the timeChange variable. milliseconds divided by
    tempo and 16th note, or something like that. I dont remember*/
    timeChange=((60000/tempo)/8);

    /*initializing the steps in the array */
    for(int i=0;i<maxNumberOfSteps;i++)
    {
    myData[i].note=48+i;
    myData[i].velocity=120;
    myData[i].onOff=1;
    myData[i].length=4;
    myData1[i].note=48+i;
    myData1[i].velocity=120;
    myData1[i].onOff=1;
    myData1[i].length=4;
    }

    lcd.clear();

    /*what time is now*/

    rememberMillis = millis();
    rememberMillisDisplay = millis();
    }

    void on16Callback() {
    if ((MidiClock.div16th_counter % 4) == 0) {
    digitalWrite(ledPin, HIGH);

    } else if ((MidiClock.div16th_counter % 4) == 2) {
    digitalWrite(ledPin, LOW);

    }
    }
    /* a little function to print the name of the note */
    void printNoteName(byte initialNote)
    {
    byte octave = (initialNote / 12) – 1;
    byte noteIndex = (initialNote % 12);

    lcd.print(noteNames[noteIndex]);
    lcd.print(octave,DEC);
    }

    /* this functions prints what we have in the first "menu" part of the data
    tempo, channel and instrument*/
    void populateDisplayMenuButtonPressed()
    {

    lcd.setCursor(0, 0) ;

    lcd.print("t");
    lcd.print(tempo,DEC);
    lcd.print("c");
    lcd.print(channel,DEC);
    lcd.print("i");
    lcd.print(instrument,DEC);
    lcd.print("tr");
    lcd.print(track,DEC);

    if (!isPlaying)
    {
    lcd.setCursor(0, 1) ;
    lcd.print("PAUSED ");
    }
    else
    {
    lcd.setCursor(0, 1) ;
    for(int i=0;i<numberofsteps;i++)
    {
    if(i==currentlyPlaying && i==currentlyEditing )
    lcd.print("+");
    else if(i==currentlyEditing)
    lcd.print("-");
    else if(i==currentlyPlaying)
    lcd.print("|");
    else
    lcd.print(".");
    }
    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */
    for(int i=numberofsteps;i< maxNumberOfSteps ;i++)
    {
    lcd.print(" ");

    }
    }
    }

    /*this is the normal/regular display info printing routine */
    void populateDisplay()
    {
    lcd.setCursor(0, 0) ;
    if(isPlaying)
    {
    printNoteName(myData[currentlyEditing].note);
    lcd.print(" ");
    /*On if the note is On, Off it is Off, getting it? getting on or getting off, muhahahaha */
    if(myData[currentlyEditing].onOff)
    lcd.print("On");
    else
    lcd.print("Off");

    lcd.print(" ");

    printNoteName(myData1[currentlyEditing].note);
    lcd.print(" ");
    /*On if the note is On, Off it is Off, getting it? getting on or getting off, muhahahaha */
    if(myData1[currentlyEditing].onOff)
    lcd.print("On");
    else
    lcd.print("Off");

    lcd.print(" ");
    {
    /*what kind of note what we are dealing with */
    switch (myData[currentlyEditing].length)
    switch (myData1[currentlyEditing].length)
    {
    case 1:
    lcd.print("32nd");
    break;
    case 2:
    lcd.print("16th");
    break;
    case 3:
    lcd.print("8th");
    break;
    case 4:
    lcd.print("4th");
    break;
    case 5:
    lcd.print("2nd");
    break;
    case 6:
    lcd.print("whole");
    break;
    default:
    lcd.print("FAIL");
    break; /*we made bu bu*/

    }
    }
    lcd.print(" ");

    lcd.print(myData[currentlyEditing].velocity,DEC);
    lcd.print(myData1[currentlyEditing].velocity,DEC);
    lcd.print(" ");

    lcd.setCursor(0, 1) ;
    for(int i=0;i<numberofsteps;i++)
    {
    if(i==currentlyPlaying && i==currentlyEditing )
    lcd.print("+");
    else if(i==currentlyEditing)
    lcd.print("-");
    else if(i==currentlyPlaying)
    lcd.print("|");
    else
    lcd.print(".");
    }

    /* prints spaces for the rest of the line, it is better then using a
    lcd.clear, atleast if you call lcd.clear fast/often */

    for(int i=numberofsteps;i 100)
    {
    rememberMillisDisplay=millis();
    checkButtons();
    if (!menuButtonIsPressed)
    populateDisplay();
    else
    populateDisplayMenuButtonPressed();
    }

    if(isPlaying)
    {

    if( millis()-rememberMillis > ((myData[currentlyPlaying].length * myData[currentlyPlaying].length )*(timeChange)))
    if( millis()-rememberMillis > ((myData1[currentlyPlaying].length * myData1[currentlyPlaying].length )*(timeChange)))
    {
    //fuck it, we always send off, most MIDI devices wont crap themselves.
    sendMidiMessage(0×80, myData[currentlyPlaying].note,120); //off
    sendMidiMessage(0×80, myData1[currentlyPlaying].note,120); //off

    currentlyPlaying++;
    if (currentlyPlaying==numberofsteps)
    currentlyPlaying=0;

    rememberMillis=millis();

    if( myData[currentlyPlaying].onOff)
    sendMidiMessage(0×90, myData[currentlyPlaying].note, 120); //on
    if( myData1[currentlyPlaying].onOff)
    sendMidiMessage(0×90, myData1[currentlyPlaying].note, 120); //on

    }
    }

    while (MidiUart.avail()) {
    Midi.handleByte(MidiUart.getc());
    }
    switch (track){
    case 1:
    myData;
    break;
    case 2:
    myData1;
    break;
    }
    }

    /* This functions makes almost all our values be more correct.
    like, we dont want negative values or out of range values */
    void SanitizeValues()
    {

    myData[currentlyEditing].onOff= myData[currentlyEditing].onOff % 2; //setting the current value to be inbetween 0 and 1
    myData[currentlyEditing].note= myData[currentlyEditing].note % 128; //setting the current value to be inbetween 0 and 127
    myData[currentlyEditing].velocity= myData[currentlyEditing].velocity % 128; //setting the current value to be inbetween 0 and 127
    myData1[currentlyEditing].onOff= myData[currentlyEditing].onOff % 2; //setting the current value to be inbetween 0 and 1
    myData1[currentlyEditing].note= myData[currentlyEditing].note % 128; //setting the current value to be inbetween 0 and 127
    myData1[currentlyEditing].velocity= myData[currentlyEditing].velocity % 128; //setting the current value to be inbetween 0 and 127
    currentlyEditing=(currentlyEditing % (numberofsteps));
    isPlaying = isPlaying%2;

    if(numberofsteps > maxNumberOfSteps)
    numberofsteps=maxNumberOfSteps;

    if(numberofsteps 6)
    myData[currentlyEditing].length=6;

    if(myData1[currentlyEditing].length > 6)
    myData1[currentlyEditing].length=6;

    myData1[currentlyEditing].length+=encoder0Pos;

    if(myData[currentlyEditing].length < 1)
    myData[currentlyEditing].length=1;

    if(myData1[currentlyEditing].length < 1)
    myData1[currentlyEditing].length=1;

    }
    else if(velocityButtonIsPressed)
    myData[currentlyEditing].velocity+=encoder0Pos;
    else if(velocityButtonIsPressed)
    myData1[currentlyEditing].velocity+=encoder0Pos;
    else if(playPauseButtonIsPressed)
    isPlaying+=encoder0Pos;

    else
    currentlyEditing+=encoder0Pos;
    }

    rotary.position(0);
    SanitizeValues();
    }

    void sendMidiMessage(char cmd, char data1, char data2)
    {

    #if debugprint
    Serial.print("Sending MIDI ");
    Serial.print(cmd,DEC);
    Serial.print(" ");
    Serial.print(data1,DEC);
    Serial.print(" ");
    Serial.println(daserial.pta2,DEC);
    #endif
    //not sending channel or instrument change yet…
    #if usesMidi
    Serial.print(cmd, BYTE);
    Serial.print(data1, BYTE);
    Serial.print(data2, BYTE);
    #endif
    }

    Comment by magellan — January 10, 2011 @ 12:37 am

  41. Magellan, what is not working on the hardware? could you describe the symptoms?

    /Johan

    Comment by Johan Larsby — January 10, 2011 @ 7:30 pm

  42. Wilson the encoder.h should be in the same directory.

    The second question you have has the answer of being the the print stuff on screen, you’ll recognize the characters when you watch the video!

    Comment by Johan Larsby — January 10, 2011 @ 7:33 pm

  43. Hello again,

    first of all I’ll explain what I want the soft/hardware to do. I want to play more than one track at once. Let’s say 4 or 8 tracks if the hardware is quick enough to check what is going on in every track. Each track must have its own lenght an of course different notes with velocity and lenght. I asume that every track is written into an array and that I have to copy some parts of the program. I copied in the program I posted the part called mydata but thinking of it now I probably need to to the same with the part called currentlyplaying and currentlyediting. The hardware showed on the screen nicely tr1 when pushing the menupressedbutton, but when I change the track to tr2 the notes, onoff, velocity, channel and lenght are exactly the same as in the first track. I want them to be different of course because I select a different track with different note information. All these events should be played at once. I hope this is possible in some way because in this way I should be able to avoid a second rotary encoder. The external midi sync is working good and the abbilaty to play 4 or more tracks at once could make this a very usefull sequencer. Thanks for any support.

    /Magellan

    Comment by magellan — January 10, 2011 @ 10:17 pm

  44. What value is the resistor that’s labeled “5,7″? I haven’t seen that notation before.

    Comment by Matt — March 10, 2011 @ 10:40 pm

  45. Apparently 5,7 = 5,700 Ohms.
    http://arduino.cc/forum/index.php/topic,55422.0.html

    Comment by Matt — March 15, 2011 @ 5:08 pm

  46. The value for the display I used should be 5,7 ohms according to the datasheet. It depends on the display you use.

    Comment by Magellan — March 20, 2011 @ 10:13 pm

  47. I compiled the firmware (with the changes in the schematics) with no errors and done the circuit but nothing is working :(
    I’m using Arduino 2009 and a Sparkfun display. What I can check guys?

    Comment by Xtaz — October 18, 2011 @ 4:32 pm

  48. batterie compaq presario cq71
    batterie compaq presario cq71

    Comment by CIDavid — January 22, 2013 @ 6:37 pm

  49. Comment by anaerCawfrurO — June 26, 2013 @ 9:38 am

  50. Hi, Neat post. There’s an issue with your website in web explorer, would check this IE still is the market leader and a huge section of other folks will miss your wonderful writing due to this problem. Calvin Klein http://www.abilitymagazine.org.uk/Images/Uploads/cavin8.html

    Comment by Calvin Klein — August 1, 2013 @ 4:36 pm

Leave a comment

Line and paragraph breaks automatic, e-mail address never displayed, HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Close this window.

0.551 Powered by WordPress