Can't exit a boucle for

Hi guys,

I’ve connected a solenoid and some servos to a MIDI software where when I receive specific notes, it calls a specific function that activate the solenoid and/or move the servos.

Here it is:

#include <VarSpeedServo.h> 


byte type = 0;

byte incomingByte;
byte note;
byte velocity;
int chan = 1;  //specify what MIDI channel we're listing to
byte boucle=0;   // pour boucle

int action=2; //0 =note off ; 1=note on ; 2= null
const int lowNote = 60; //what's the first note?  36 is C1 in Ableton

 

VarSpeedServo servoI1;   // create servo object to control a servo that inflate 1
VarSpeedServo servoD1;   // create servo object to control a servo that deflate 1

VarSpeedServo servoI2;   // create servo object to control a servo that Inflate 2
VarSpeedServo servoD2;   // create servo object to control a servo that Deflate 2

VarSpeedServo servoI3;   // create servo object to control a servo that Inflate 3
VarSpeedServo servoD3;   // create servo object to control a servo that Deflate 3

VarSpeedServo servoI4;   // create servo object to control a servo that Inflate 4
VarSpeedServo servoD4;   // create servo object to control a servo that Deflate 4


// the loop function runs over and over again forever

void setup(){
 Serial.begin(38400);
 
//setup our outputs

  pinMode(30, OUTPUT);
  digitalWrite (30, LOW);
  pinMode(31, OUTPUT);
  digitalWrite (31, LOW);
 
  servoI1.attach(22);   // Set I1 servo to digital pin 22
  servoD1.attach(23);  //  Set D1 servo to digital pin 23
  servoI2.attach(24);   // Set I2 servo to digital pin 24
  servoD2.attach(25);   // Set D2 servo to digital pin 25
  servoI3.attach(26);   // Set I1 servo to digital pin 26
  servoD3.attach(27);   // Set D2 servo to digital pin 27
  servoI4.attach(28);   // Set I2 servo to digital pin 28
  servoD4.attach(29);   // Set I2 servo to digital pin 29
}


void slow () {
        digitalWrite (31, LOW);
        digitalWrite (30, LOW);
   servoI1.write(90, 0);
   servoI2.write(90, 0);
   servoI3.write(90, 0);
   servoI4.write(90, 0, true);
   servoD1.write(52, 0);
   servoD2.write(52, 0);
   servoD3.write(52, 0);
   servoD4.write(52, 0, true);
   delay (15);
    
    for (boucle=0;boucle<10;boucle++)
        {
        boucle= 2;
         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
         if(Serial.available() > 0) {
    
         incomingByte = Serial.read();      
        if(incomingByte==127+chan)
           boucle=11;  
        }}
  delay (15);  
  digitalWrite (30, HIGH);
  servoI1.write(32, 0); 
  servoI2.write(32, 0);
  servoI3.write(32, 0);
  servoI4.write(32, 0, true);
  delay (200);
  digitalWrite (31, LOW);
  servoD1.write(32, 0); 
  servoD2.write(32, 0);
  servoD3.write(32, 0);
  servoD4.write(32, 0, true);
}

void loop () {
  
  servoI1.write(30);    // move to 32 degrees to close the in valve
  servoI2.write(30);    // move to 32 degrees to close the in valve
  servoI3.write(30);    // move to 32 degrees to close the in valve
  servoI4.write(30);    // move to 32 degrees to close the in valve
  
  servoD1.write(32);    // move to 32 degrees to close the out valve
  servoD2.write(32);    // move to 32 degrees to close the out valve
  servoD3.write(32);    // move to 32 degrees to close the out valve
  servoD4.write(32);    // move to 32 degrees to close the out valve

    
    if(Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.read();       

   // wait for as status-byte, channel 1, note on or off
    if (incomingByte== 143+chan){ // note on message starting starting
      action=1;
    }
    
    if (incomingByte== 127+chan){ // note off message starting
      action=0;
 
    }
    
    if ( (action==0)/*&&(note==0)*/ ){ // if we received a "note off", we wait for which note (databyte)
      note=incomingByte;
      velocity=0;
    } 
    
    if ( (action==1)/*&&(note==0)*/ ){ // if we received a "note on", we wait for the note (databyte)
      note=incomingByte;
      moveServo(note);
  
    }
    }
 
}

void moveServo(byte note){    //  call a function based on the note

    incomingByte = Serial.read(); 
    
switch (note){
  case lowNote: //if it's not 60
  slow ();
  break;
  case lowNote+1:
  deffast1234fin ();
  break;
}
  
}

Everything is working fine, I can call up my functions easily by changing notes (lowNote, lowNote+1 and so forth).

However for function slow, I can call up that function, and the solenoid is going to vibrate (LOW,HIGH and so forth) in a boucle. But the boucle doesn’t stop. It is supposed to stop once the note on the MIDI software is OFF.

Basically what I’m trying to achieve is:

  • once I get a lowNote (60) on garageband, it calls function slow.
  • Servos I1,I2,I3,I4, D1, D2, D3, D4 gets open.
  • The solenoid is going into a boucle for (vibrating) till lowNote is iff
  • Servos I1,I2,I3,I4, D1, D2, D3, D4 are closing.

End of the function.

Right now, it is calling the function, opening servos, vibrating the solenoid but even if the note is off, it is still vibrating. The only way to stop it is by reseting the arduino :s What am I doing wrong?

I assume it doesn’t receive the correct Note OFF information but

    if(Serial.available() > 0) {
    
         incomingByte = Serial.read();      
        if(incomingByte==127+chan)
           boucle=11;  
        }}

should be correct no?

Thanks in advance for your help.

Whats the point of having a for loop if it keeps assigning the same variable a number that you are trying to increment?

for (boucle=0;boucle<10;boucle++)
{
boucle= 2; // with each pass, it will continue to assign 2 to boucle and it will never increment thus it will never break out of the for loop.
digitalWrite (30, HIGH);
digitalWrite (31, HIGH);
delay(100);
digitalWrite (30, LOW);

What is a boucle?

Whats the point of having a for loop if it keeps assigning the same variable a number that you are trying to increment?

You’re right however my loop I don’t really want it to increment, I just want it to repeat again and again this loop till I tell him to stop with a MIDI note OFF message.

 if(Serial.available() > 0) {
    
         incomingByte = Serial.read();      
        if(incomingByte==127+chan)
           boucle=11;  
        }}

From what I understand, this read the MIDI message from the computer. If it receives 127+chan (channel 1) therefore 128 which means, in MIDI status code, Note OFF. Then it increment the boucle at 11.

If I’m incorrect, what is the right thing to do?

So use a while loop and have this inside it, otherwise it wont do anything.

if(Serial.available() > 0) {
    
         incomingByte = Serial.read();      
        if(incomingByte==127+chan)
           boucle=11;  
        }

Do something like this.

while( true )
{
 /* solenoid part here */
 if(Serial.available() > 0) 
 {
      incomingByte = Serial.read();      
       if(incomingByte==127+chan)
          break; // if incomingByte is equal to 127+chan then exit from while loop.
 } // end of if statement
} // end of while loop

It's interesting because this code was perfectly working with a PS2 remoter controller. Basically once the SELECT button was hit, the function was called and the solenoid was in boucle as long as the Select was hit again. So in a sense, it was working. I've replaced the PS2 remote controller by MIDI note and now instead of hitting SELECT I just want it to get the 127+chan or action=0 to stop the boucle but it is not working, and nothing else has really changed.

My guess is that it is not receiving a MIDI statut code OFF and that is why the boucle is not stopping. Changing it by a while loop would then get the same issue.

As I'm using the hairless MIDI to Serial software I can't debug and use the serial monitor to see what's happening ...

Do something like this.

Sorry I was already writing my answer when I saw your code.

Just tried it

void slow () {
        digitalWrite (31, LOW);
        digitalWrite (30, LOW);
   servoI1.write(90, 0);
   servoI2.write(90, 0);
   servoI3.write(90, 0);
   servoI4.write(90, 0, true);
   servoD1.write(52, 0);
   servoD2.write(52, 0);
   servoD3.write(52, 0);
   servoD4.write(52, 0, true);
   delay (15);
    
    while( true )
{


         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
         digitalWrite (30, HIGH); 
         digitalWrite (31, HIGH); 
         delay(100);
         digitalWrite (30, LOW); 
         digitalWrite (31, LOW); 
         delay(100);
      if(Serial.available() > 0) 
 {
      incomingByte = Serial.read();      
       if(incomingByte==127+chan)
          break; // if incomingByte is equal to 12
        }}
  delay (15);  
  digitalWrite (30, HIGH);
  servoI1.write(32, 0); 
  servoI2.write(32, 0);
  servoI3.write(32, 0);
  servoI4.write(32, 0, true);
  delay (200);
  digitalWrite (31, LOW);
  servoD1.write(32, 0); 
  servoD2.write(32, 0);
  servoD3.write(32, 0);
  servoD4.write(32, 0, true);
}

It is not working, the loop is still on and on. I'm pretty sure I am not receiving a Note OFF status code. I have no idea why but I'm gonna have to dig into that

Use this instead.

Please try to cut down on the delays as much as possible and take a look at the arduino example sketch “Blink Without Delay” to understand what I have done here.

void slow () {
  digitalWrite (31, LOW);
  digitalWrite (30, LOW);
  servoI1.write(90, 0);
  servoI2.write(90, 0);
  servoI3.write(90, 0);
  servoI4.write(90, 0, true);
  servoD1.write(52, 0);
  servoD2.write(52, 0);
  servoD3.write(52, 0);
  servoD4.write(52, 0, true);
  delay (15);

  while ( true )
  {
    static unsigned long previousTime = 0;
    
    currentTime = millis();
    if(currentTime - previousTime >= 100)
    {
      digitalWrite (30, !digitalRead(30)); // !digitalRead(...) will toggle the state HIGH -> LOW, LOW -> HIGH
      digitalWrite (31, !digitalRead(31));
      if(currentTime < previousTime) // check for rollover
        previousTime = 0;
        
      previousTime += 100; // increment previous time by delay factor "100"
    }
    
    if (Serial.available() > 0)
    {
      incomingByte = Serial.read();
      if (incomingByte == 127 + chan)
        break; // if incomingByte is equal to 12
    }
  }
  
  delay (15);
  digitalWrite (30, HIGH);
  servoI1.write(32, 0);
  servoI2.write(32, 0);
  servoI3.write(32, 0);
  servoI4.write(32, 0, true);
  delay (200);
  digitalWrite (31, LOW);
  servoD1.write(32, 0);
  servoD2.write(32, 0);
  servoD3.write(32, 0);
  servoD4.write(32, 0, true);
}

Use this instead.

Please try to cut down on the delays as much as possible and take a look at the arduino example sketch “Blink Without Delay” to understand what I have done here.

HazardsMind You’ve just made my whole week (+the week end).

1/ It’s working
2/ I always knew that delays wasn’t good for what I wanted to achieve and with your code applied to my application I have understood why to use it and how to use it.

A thousand thanks! Very grateful!

Your welcome.