(another) arduino sequencer thread.

Hi guys.

this is my first project - quite a simple one. it's an 8-step sequencer project you can see on beavis audio research

you can get the code from the link above - but if needed, i can post it here.

I'm using and Arduino Uno. I did the wiring correctly, but unfortunately i have to keep pressing the start/stop button to hear it while i'd like to push it one time to start it and one time to stop it. here's the piece of code i think it's related to my problem:

// misc housekeeping
int duration = 50;
int pitchval = 1;
int fPlayMode = true;
int lastPushedStep = -1;

// Initialize the tempo
int tempo = 100;

void setup()
{ 
  // setup pin modes (Digital pins are input by default, but
  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);                
  pinMode (DigitalInStartStop, INPUT);
  pinMode (DigitalOutSignal, OUTPUT);  
  pinMode (DigitalOutLED, OUTPUT);

void loop() 
{
  // Main sequence loop  
  for (int i=0; i<8; i++)
  {   
    // Are we playing or stopping?
    fPlayMode = digitalRead (DigitalInStartStop);
    digitalWrite (DigitalOutLED, HIGH);

    // Check the Hardware
     readSwitches();
     readPots();

    // Make the noise
    if (fPlayMode)
    {
      freqout (steps[i], duration);
    }
    digitalWrite (DigitalOutLED, LOW);

    // Pause between steps
    delay (tempo);       
  }
}

...and that's all for now.
thanks in advance!

Max

At the moment you're simply reading whether the button is down to start the replay sequence:

fPlayMode = digitalRead (DigitalInStartStop);

What you're trying to do needs you to detect when the button state changes from unpressed to pressed; each time that happens, toggle the state of fPlayMode. To detect button state changes you need to remember the previous state and see whether the current state is different; afterwards, save the current state as the new previous state ready for next time.

at least now I have a trace, but I don't have any clue about how to code it. any help?

It looks like you should move the code to read the switch state out of the for loop. Of course, the fact that you aren't detecting edges, as PeterH points out, is also a problem.

  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);

Actually declaring and valuing, and using, these variables would also be a good idea.

I think that the code is quite old, right? for instance, when i check the code it keeps telling me that "BYTE" is no more used.

I think that the code is quite old, right?

What code? The incomplete code you posted in the original message? What does it matter how old the code is, if it works.

when i check the code it keeps telling me that "BYTE" is no more used.

There are documented fixes for the issue.

I've found something, googling around... now it stays silen until i press the button, but for some reason pressing it again won't deactivate the pin 13 (called DigitalInPippo).

here's the code i'e found and adapted:

{
  if(digitalRead(10) == HIGH) { //If Pin 10 is high (At 5 Volts)
    Button = 1 - Button; //If Button is set as 0 then Button = 1 - 0 (=1) and if Button is 1 then Button=1 - 1 (=0)
  }
  
  if(Button == 1 && OldButton == 0) { //If Button is 1 and OldButton is 0 (This means basically means "If the button was just pressed"
     digitalWrite (DigitalInPippo, HIGH);//Put what you want to happen when the "Switch" is on here
     delay(500); //Delay for half a second
  }
  
  if(Button == 0 && OldButton == 1) {
    digitalWrite (DigitalInPippo, LOW);//Put what you want to happen when the "Switch" is off here
    delay(500); //Delay for half a second
  }

  OldButton = Button; //The data is now old
}

    fPlayMode = digitalRead (DigitalInPippo); //this should activate/deactivate the sounds

any help?

also, an idea that came into my mind but it's incorrect and i can't understand why:

// Are we playing or stopping?
    {
  if(digitalRead(10, HIGH)  //If Pin 10 is high i press the control button, then check:
    if (digitalRead((13) == LOW) //if the pin13 is LOW
    {
    digitalWrite(13, HIGH) //then make it HIGH (button pressed)
    }
    if (digitalRead((13) == HIGH) //if the pin13 is HIGH
    {
    digitalWrite(13, LOW) //then release it
    }
    fPlayMode = digitalRead (13);

thanks again!

I'm quite out of ideas here.

I've corrected the "grammar" of the code, but it's not behaving like I would like.

with the original code, the function "fPlayMode" work only if i keep the start/stop button pressed.

code is here: beavis audio research

with this coding, it starts automatically, some seconds after power up the arduino:

/* ======================================================================
 Arduino Punk Console
 A simple programmable 8 step tone sequencer 
 by dano/beavisaudio.com
 Revs
 -----------------------------------
 15 Sept  djh  initial version
======================================================================*/
// Map all the input and output pins
#define AnalogInFrequency 1
#define AnalogInTempo 2
#define AnalogInDuration 0
#define DigitalOutSignal 11
#define DigitalInSwitch0 2
#define DigitalInSwitch1 3
#define DigitalInSwitch2 4
#define DigitalInSwitch3 5
#define DigitalInSwitch4 6
#define DigitalInSwitch5 7
#define DigitalInSwitch6 8
#define DigitalInSwitch7 9 
#define DigitalInStartStop 10
#define DigitalInPippo 12
#define DigitalOutLED 13
// Set up the array for each step
int steps[] = {100,120,140,160,180,200,220,240};
// misc housekeeping
int duration = 50;
int pitchval = 1;
int fPlayMode = true;
int lastPushedStep = -1;
// Initialize the tempo
int tempo = 100;
void setup()
{ 
  // setup pin modes (Digital pins are input by default, but
  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);                
  pinMode (DigitalInStartStop, INPUT);
  pinMode (DigitalOutSignal, OUTPUT);  
  pinMode (DigitalOutLED, OUTPUT);
  // setup comms for the LCD display
  Serial.begin(9600);

  StartupMessage();
} 
void StartupMessage()
{
  clearLCD();
  Serial.print ("BEAVIS: Arduino");
  delay(300);
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("Punk Console!");
  delay (2000);
  clearLCD();
  Serial.print ("Beavis: APC");
}

void clearLCD()
{
  Serial.print(254, BYTE);
  Serial.print(1, BYTE);
}

void loop() 
{
  // Main sequence loop  
  for (int i=0; i<8; i++)
  {  
    // Are we playing or stopping?
    if (digitalRead ((DigitalInStartStop) == HIGH))
    {
      if (digitalRead((DigitalInPippo) == LOW))
      {
        digitalWrite(DigitalInPippo, HIGH);
      }
      else
      {
        digitalWrite(DigitalInPippo, LOW);
      }
    }
    fPlayMode = digitalRead (DigitalInPippo);
    digitalWrite (DigitalOutLED, HIGH);
    // Check the Hardware
     readSwitches();
     readPots();

    // update the display
    updateDisplay();

    // Make the noise
    if (fPlayMode)
    {
      freqout (steps[i], duration);
    }
    digitalWrite (DigitalOutLED, LOW);

    // Pause between steps
    delay (tempo);       
  }
} 

void updateDisplay()
{
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("T:");
  Serial.print (tempo);
  Serial.print (" d:");
  Serial.print (duration);
 if (lastPushedStep != -1)
 {
    Serial.print ("*");
    Serial.print (lastPushedStep);
 }
}
// Read the current values of the pots, called from the loop.
void readPots ()
{
    tempo = (analogRead (AnalogInTempo) * 1.9);
    duration = (analogRead (AnalogInDuration));      
}
// Read the current values of the switches and
// if pressed, replace the switch's slot frequency
// by reading the frequency pot.
void readSwitches()
{
  // reset last pushed button number
  lastPushedStep = -1;

  // check switch 0, if pressed, get the current freq into step 0, etc. etc.
  if (digitalRead (DigitalInSwitch0) == HIGH)
  {
    steps[0] = analogRead(AnalogInFrequency);
    lastPushedStep = 1;
  }

  else if (digitalRead (DigitalInSwitch1) == HIGH)
  {
    steps[1] = analogRead(AnalogInFrequency);
    lastPushedStep = 2;
  }

  else if (digitalRead (DigitalInSwitch2) == HIGH)
  {
    steps[2] = analogRead(AnalogInFrequency);
    lastPushedStep = 3;
  }
  else if (digitalRead (DigitalInSwitch3) == HIGH)
  {
    steps[3] = analogRead(AnalogInFrequency);
    lastPushedStep = 4;
  }
  else if (digitalRead (DigitalInSwitch4) == HIGH)
  {
    steps[4] = analogRead(AnalogInFrequency);
    lastPushedStep = 5;
  }
  else if (digitalRead (DigitalInSwitch5) == HIGH)
  {
    steps[5] = analogRead(AnalogInFrequency);
    lastPushedStep = 6;
  }
  else if (digitalRead (DigitalInSwitch6) == HIGH)
  {
    steps[6] = analogRead(AnalogInFrequency);
    lastPushedStep = 7;
  }
  else if (digitalRead (DigitalInSwitch7) == HIGH)
  { 
    steps[7] = analogRead(AnalogInFrequency);
    lastPushedStep = 8;
  }
}


//freqout code by Paul Badger 
// freq - frequency value
// t - time duration of tone
void freqout(int freq, int t) 
{ 
  int hperiod;     //calculate 1/2 period in us 
  long cycles, i; 

  // subtract 7 us to make up for digitalWrite overhead - determined empirically 
  hperiod = (500000 / ((freq - 7) * pitchval));             

  // calculate cycles 
  cycles = ((long)freq * (long)t) / 1000;    // calculate cycles 
  for (i=0; i<= cycles; i++)
  {              // play note for t ms  
    digitalWrite(DigitalOutSignal, HIGH);  
    delayMicroseconds(hperiod); 
    digitalWrite(DigitalOutSignal, LOW);  
    delayMicroseconds(hperiod - 1);     // - 1 to make up for fractional microsecond in digitaWrite overhead 
  } 
}

and all the clever ideas out there to make a on/off toggle seems not to adapt to my case.
I'd really grateful is someone could help me figuring out to make this thing work, so that i can close the case and move on another project. after all, it's just the very last button that doesn't work...

any help?

Use nested loops:

  if(Button != OldButton)
  {
     // A transition occurred. But, which one?
     if(Button == HIGH)
     {
     }
     else
     {
     }
  }
  OldButton = Button;

Use meaningful names. Button is a lousy name. Is that supposed to be the name of a pin or the state of the pin? A good name would make that clear.

Separate the "implement the change" code from the "decide what change to make" code. The switch state code should only decide what the LED state should be. It should NOT implement that change.

That happens regardless of whether the switch was pressed or not.

Finally, when you post code that compiles, it works. That is, it does something. You want it to do something. When you say "it doesn't work" all we can tell is that what it does is not what you want. We can't tell what it does or what you want or how what it does differs from what you want. Provide those details if you really expect help.

well... now it works :smiley:

i've inserted a code i've found "near here" to make the button act as switch:

/* ======================================================================
 Arduino Punk Console
 A simple programmable 8 step tone sequencer 
 by dano/beavisaudio.com
 Revs
 -----------------------------------
 15 Sept  djh  initial version
======================================================================*/
// Map all the input and output pins
#define AnalogInFrequency 1
#define AnalogInTempo 2
#define AnalogInDuration 0
#define DigitalOutSignal 11
#define DigitalInSwitch0 2
#define DigitalInSwitch1 3
#define DigitalInSwitch2 4
#define DigitalInSwitch3 5
#define DigitalInSwitch4 6
#define DigitalInSwitch5 7
#define DigitalInSwitch6 8
#define DigitalInSwitch7 9
#define DigitalOutLED 1
// Set up the array for each step
int steps[] = {100,120,140,160,180,200,220,240};
// misc housekeeping
int duration = 50;
int pitchval = 1;
int fPlayMode = true;
int lastPushedStep = -1;
int Button = 0; //This is the default "Button Off" and 1 is "Button On"
int OldButton = 0; //I'll explain later
// Initialize the tempo
int tempo = 100;

/* switch
 * 
 * Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 * press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 * a minimum delay between toggles to debounce the circuit (i.e. to ignore
 * noise).  
 *
 * David A. Mellis
 * 21 November 2006
 */

int inPin = 10;         // the number of the input pin
int outPin = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers



void setup()

{ 
  // setup pin modes (Digital pins are input by default, but
  // I like to set 'em explicitly just so the code is clear.
  pinMode (DigitalInSwitch0, INPUT);
  pinMode (DigitalInSwitch1, INPUT);
  pinMode (DigitalInSwitch2, INPUT);
  pinMode (DigitalInSwitch3, INPUT);
  pinMode (DigitalInSwitch4, INPUT);
  pinMode (DigitalInSwitch5, INPUT);
  pinMode (DigitalInSwitch6, INPUT);
  pinMode (DigitalInSwitch7, INPUT);
  pinMode (DigitalOutSignal, OUTPUT);  
  pinMode (DigitalOutLED, OUTPUT);
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);
  // setup comms for the LCD display
  Serial.begin(9600);
  StartupMessage();
}

void StartupMessage()
{
  clearLCD();
  Serial.print ("BEAVIS: Arduino");
  delay(300);
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("Punk Console!");
  delay (2000);
  clearLCD();
  Serial.print ("Beavis: APC");
}

void clearLCD()
{
  Serial.print(254, BYTE);
  Serial.print(1, BYTE);
}

void loop() 
{
  // Main sequence loop  
  for (int i=0; i<8; i++)
  {   
    // Are we playing or stopping?
   {
  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce)
  {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();    
  }

  digitalWrite(outPin, state);

  previous = reading;
}
    
    fPlayMode = digitalRead (13);
    digitalWrite (DigitalOutLED, HIGH);
    // Check the Hardware
     readSwitches();
     readPots();

    // update the display
    updateDisplay();

    // Make the noise
    if (fPlayMode)
    {
      freqout (steps[i], duration);
    }
    digitalWrite (DigitalOutLED, LOW);

    // Pause between steps
    delay (tempo);       
  }
} 

void updateDisplay()
{
  Serial.print (254, BYTE);
  Serial.print (192, BYTE);
  Serial.print ("T:");
  Serial.print (tempo);
  Serial.print (" d:");
  Serial.print (duration);
 if (lastPushedStep != -1)
 {
    Serial.print ("*");
    Serial.print (lastPushedStep);
 }
}
// Read the current values of the pots, called from the loop.
void readPots ()
{
    tempo = (analogRead (AnalogInTempo) * 1.9);
    duration = (analogRead (AnalogInDuration));      
}
// Read the current values of the switches and
// if pressed, replace the switch's slot frequency
// by reading the frequency pot.
void readSwitches()
{
  // reset last pushed button number
  lastPushedStep = -1;

  // check switch 0, if pressed, get the current freq into step 0, etc. etc.
  if (digitalRead (DigitalInSwitch0) == HIGH)
  {
    steps[0] = analogRead(AnalogInFrequency);
    lastPushedStep = 1;
  }

  else if (digitalRead (DigitalInSwitch1) == HIGH)
  {
    steps[1] = analogRead(AnalogInFrequency);
    lastPushedStep = 2;
  }

  else if (digitalRead (DigitalInSwitch2) == HIGH)
  {
    steps[2] = analogRead(AnalogInFrequency);
    lastPushedStep = 3;
  }
  else if (digitalRead (DigitalInSwitch3) == HIGH)
  {
    steps[3] = analogRead(AnalogInFrequency);
    lastPushedStep = 4;
  }
  else if (digitalRead (DigitalInSwitch4) == HIGH)
  {
    steps[4] = analogRead(AnalogInFrequency);
    lastPushedStep = 5;
  }
  else if (digitalRead (DigitalInSwitch5) == HIGH)
  {
    steps[5] = analogRead(AnalogInFrequency);
    lastPushedStep = 6;
  }
  else if (digitalRead (DigitalInSwitch6) == HIGH)
  {
    steps[6] = analogRead(AnalogInFrequency);
    lastPushedStep = 7;
  }
  else if (digitalRead (DigitalInSwitch7) == HIGH)
  { 
    steps[7] = analogRead(AnalogInFrequency);
    lastPushedStep = 8;
  }
}


//freqout code by Paul Badger 
// freq - frequency value
// t - time duration of tone
void freqout(int freq, int t) 
{ 
  int hperiod;     //calculate 1/2 period in us 
  long cycles, i; 

  // subtract 7 us to make up for digitalWrite overhead - determined empirically 
  hperiod = (500000 / ((freq - 7) * pitchval));             

  // calculate cycles 
  cycles = ((long)freq * (long)t) / 1000;    // calculate cycles 
  for (i=0; i<= cycles; i++)
  {              // play note for t ms  
    digitalWrite(DigitalOutSignal, HIGH);  
    delayMicroseconds(hperiod); 
    digitalWrite(DigitalOutSignal, LOW);  
    delayMicroseconds(hperiod - 1);     // - 1 to make up for fractional microsecond in digitaWrite overhead 
  } 
}

now works :slight_smile:

thanks for the hints!