conflicting delay times

hello

sorry if this is mega obvious, but i cannot figure it out and could not find an appropriate answer in the archives even though i suspect similar questions may have been posted in the past, often.

my loop contains 2 separate parts:

  • one reading from analogRead(0) connected to a pot
  • the other sending midi notes.

i want the pot to be constantly read, so i put a delay(10) after it, but this is ignored – well, not ignored, but overruled because the midi part contains a delay too, in between note ons and note offs.

i am sure there’s a better way to do this :slight_smile:
thanks

void loop()                     
{

{
  val = analogRead(0);
}

  if (val < 510) {
  Serial.print("low: "); Serial.print(val); delay(50);
} else {
   Serial.print("HIGHHH: "); Serial.print(val); delay(50);
}
  
 delay(10); 

  int i;
  int length = 8;
  for (i = 0; i < length; i = i + 1) {
 
  
  usbMIDI.sendNoteOn(newarray[i], velocities[i], 1);
  
    Serial.print(newarray[i]);
    Serial.print("   ");
    
delay(timelist[random(0, 2)]);

  
  usbMIDI.sendNoteOff(newarray[i], 0, 1);
  
  }

It isn't ignored or overruled. Your code runs line by line from top to bottom. Then it repeats. So it reads the analog pin, then it compares, then it waits 10ms, then it sends the midi note then it delays again and then it turns the midi note off and then it starts over with reading the analog pin again.

You need to write non-blocking code so that one thing doesn't block the other. See the famous Blink Without Delay example and any of the thousands of great tutorials on that topic for more on how.

See this link

And this one too

thanks, Delta_G. there’s still something that i don’t get, though (my mistake, i’m sure!).

i put the 2 parts in different functions, and i’m printing on the serial monitor from both, but the overall speed of reading seems to depend on the analogRead value. that is, when the pot is at 1, or near that, it prints loads of stuff, but as it gets higher delays between new lines are more and more. i do realise i am using “val”, which i assigned to the value coming from “analogRead(0)”, in my midi function as well, but i don’t understand why the “pot” function is not printing constantly regardless of the “sequencer” one.

THANKS!

void loop()     
{
 pot();
 sequencer();
 }                

//======================================

 int val;

void pot()
{
 val = analogRead(0);


 if (val < 510) {
 Serial.print("low: "); Serial.print(val); Serial.println(); delay(10);
} else {
  Serial.print("HIGH: "); Serial.print(val); Serial.println(); delay(10);
}
 
delay(5); 
 
}

//======================================

void sequencer()
{
 int i;
 int length = 8;
 for (i = 0; i < length; i = i + 1) {
 
usbMIDI.sendNoteOn(newarray[i], velocities[i], 1);
   Serial.print(newarray[i]);
   Serial.print("   ");
   Serial.println();
delay(val + 100);
usbMIDI.sendNoteOff(newarray[i], 0, 1);
   } 
 }

the overall speed of reading seems to depend on the analogRead value.

Of course it does. You programmed it that way, using this line:

delay(val + 100);

The computer does nothing else during a delay(), which is why we recommend not using delay() if at all possible.

Again, those two functions aren't running at the same time. It runs everything in the pot() function and then it runs everything in the sequencer() function. And the stuff in the pot() function has to wait until the sequencer() function is finished and the loop repeats. So there's the 5ms delay in pot() and then the delay in sequencer() that depends on val before pot() gets called again.

When you do this right, there won't be a single delay call in your code. Read the links I gave you. Actually take some time and read. They explain how to do this.

If you want a complete answer, it would better if posted your complete code. What you've shown so far is missing a setup() function, #include directive(s), and global variable definitions. It won't compile, so obviously it's incomplete.

As stated, 'val' appears to be a global variable (once you post a complete program, we'll know for sure) and you're basing the delay() value in the sequencer() on it. So, of course the delay() will last longer as 'val' becomes larger.

here is the whole code, sorry.
trying to wrap my head around millis(), but struggling…

 #include <MIDI.h>
 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
 
 const int channel = 1; // MIDI channel
 int newarray[8] = {35, 37, 37, 37, 35, 37, 37, 37 };
 int velocities[8] = {127, 0, 0, 0, 127, 0, 0, 0 };
 
void setup()
{                
 Serial.begin(38400);
 MIDI.begin();

 
 randomSeed(analogRead(1));

 newarray[1] = random(36, 42);
 newarray[2] = random(36, 42);
 newarray[3] = random(36, 42);  
 newarray[5] = random(36, 42);
 newarray[6] = random(36, 42);
 newarray[7] = random(36, 42);

 velocities[1] = random(0, 2) * 127;
 velocities[2] = random(0, 2) * 127;
 velocities[3] = random(0, 2) * 127;
 velocities[5] = random(0, 2) * 127;
 velocities[6] = random(0, 2) * 127;
 velocities[7] = random(0, 2) * 127;

}



void loop()     
{
 pot();
 sequencer();

 
 
 }                

//======================================

 int val;

void pot()
{
 val = analogRead(0);


 if (val < 510) {
 Serial.print("low: "); Serial.print(val); Serial.println(); delay(20);
} else {
  Serial.print("HIGHHH: "); Serial.print(val); Serial.println(); delay(20);
}
 
delay(5); 
 
}

//======================================

void sequencer()
{
 int i;
 int length = 8;
 for (i = 0; i < length; i = i + 1) {
 
usbMIDI.sendNoteOn(newarray[i], velocities[i], 1);
   Serial.print(newarray[i]);
   Serial.print("   ");
   Serial.println();
delay(val + 100);
usbMIDI.sendNoteOff(newarray[i], 0, 1);
   } 
 }

//======================================

rrrrrrr:
here is the whole code, sorry.
trying to wrap my head around millis(), but struggling...

The thing you need to wrap your head around is that the code gets executed line by line like a list of instructions. It doesn't get some magic code and suddenly know what to do. It just does one thing then the next thing then the next. Once you understand that millis is easy.

All it is is reading a clock. Can you use a clock? If is is 2:10 now and I tell you to meet me in 30 minutes, could you pull that off? If so then you have everything you need to use millis for timing. It's just a clock. You look at the time now, and then every time through the loop function you compare to the new time to see how long it has been.

i can use a clock, sometimes. what i am trying to wrap my head around, i guess, and sorry if this was not well explained, is how to use millis to tell my program to wait/delay/hold the number of milliseconds coming from analogRead(0) (offset by 100 ms) between usbMIDI.sendNoteOn and usbMIDI.sendNoteOff.

while i get that the millis approach helps me keep the analogRead function looping regularly by specifying a number of milliseconds as an interval to check elapsed time, i fail to see how i can use that value form analogRead() in the millis approach to scheduling things. (sorry if this is extremely obvious).

the code below is wrong, i know, but i’m posting it just to show where i got stuck. please note i’m not expecting this to work magically, nor do i claim this to be right –– i’m not complaining that it does not work, just showing where i’m struggling:

 #include <MIDI.h>
 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
 
 const int channel = 1; // MIDI channel
 int newarray[8] = {35, 37, 37, 37, 35, 37, 37, 37 };
 int velocities[8] = {127, 0, 0, 0, 127, 0, 0, 0 };
 int timelist[3] = {100, 200, 190 };
int period = 100;
unsigned long time_now = 0;

int val;

void setup() {
   Serial.begin(115200);
     MIDI.begin();

 
 randomSeed(analogRead(1));

 newarray[1] = random(36, 42);
 newarray[2] = random(36, 42);
 newarray[3] = random(36, 42);  
 newarray[5] = random(36, 42);
 newarray[6] = random(36, 42);
 newarray[7] = random(36, 42);

 velocities[1] = random(0, 2) * 127;
 velocities[2] = random(0, 2) * 127;
 velocities[3] = random(0, 2) * 127;
 velocities[5] = random(0, 2) * 127;
 velocities[6] = random(0, 2) * 127;
 velocities[7] = random(0, 2) * 127;
 
}
void loop() {
   if(millis() > time_now + period){
       time_now = millis();
       Serial.println("Hello");

 int i;
 int length = 8;
 for (i = 0; i < length; i = i + 1) {
 
usbMIDI.sendNoteOn(newarray[i], velocities[i], 1);
   Serial.print(newarray[i]);
   Serial.print("   ");
   Serial.println();
   }} else {

int i;
usbMIDI.sendNoteOff(newarray[i], 0, 1);
   } 

}

how to use millis to tell my program to wait/delay/hold

You're still looking at it wrong. Don't think interms of waiting. In my clock scenario, would you have to stop everything else and stare at the clock for thirty minutes?

No, think in terms of constantly checking to see if it is time to take the next step. Don't think in terms of stop and wait here. You can use your pot value to set the interval that you compare millis to.

if(millis() - startTime >= someValueSetByPot)