简体   繁体   中英

Can you run a function multiple times at the same time with Arduino Uno (c code)?

I have eight LEDs, four red ones and four yellow ones. There is one button for both rows. When you push a button, a row of LEDs gets a pulse. That means they light up in a row in 0.1 second intervals. My question is now: Can I send a pulse while another one is still being processed? At the moment a function is called in which a for loop sets the state of the LEDs to HIGH and low, but I can not run it again, before it is finished.

void setup()
{
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  Serial.begin(9600);
}
boolean wait(unsigned int j, unsigned int time) <-- test if 0.1 seconds have passed
{ 
  if (millis()>=time+j){
    return true;
  }
  else return false;
}
void pulse(int start)
{
    for(int j = start;j < start + 4;j++)
    {
      digitalWrite(j, HIGH);
      unsigned int time = millis();
     while(wait(100, time)==false){};
     digitalWrite(j, LOW);
    }
}
void loop()
{
  if (digitalRead(12) == HIGH)
  {
    Serial.println("yellow");
    pulse(2);                   <-- I have to wait for this function
  }
  if (digitalRead(11) == HIGH)
  {
    Serial.println("red");
    pulse(6);                   <-- I have to wait for this function
  }
}

You need to use an event loop. The problem is that you get stuck in the wait() and pulse() loops without checking for the condition that would reset the state to "pulsing for x seconds".

This involves breaking each thing you want to do down into smaller chunks so that you can interleave them together. It requires you to remember where you were in a particular sub-process so that you can return to it later. In a way you need to emulate co-routines by using state to say where in a particular function you should start running.

Also, google "debouncing". You're going to see a lot of weird behaviour if you don't debounce the button presses. I would actually recommend putting this project on hold until you can reliably debounce a button press to appear as a single press (as it's a more fundamental issue).

Don't give up so easy. This is absolutely possible. This challenge is tantilising and fun. I wish I had time to write you some code but I'm heading on a big and very important trip tomorrow and I don't have a chance.

At least try my idea. Your loop is what is killing the concept, you are relying on stopping and counting in code when you are already using the best counting tool available to you: millis()

Create a loop that turns goes through your LEDs and has them in a default state of off unless triggered by timings that are based on: millis() + "time after pushing the switch"

Each led has an on and off offset beyond either redButtonPush or yellowButtonPush (these are ints that store the millis() when the corresponding button was pushed)

For example pin4 (or yellow led number 3) is on from yellowButtonPush + 200 to yellowButtonPush + 299

Each loop check for your button push somehow then cycle through each Led to see whether you should either turn it on, turn it off, keep it on or keep it off based on its offset

Happy coding!

Thank's everyone. This is my final code.

unsigned long redButtonPress = 0;
unsigned long yellowButtonPress = 0;

void setup()
{
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
}

void loop()
{
  if (digitalRead(12) == HIGH && yellowButtonPress+399 < millis())
  {
    yellowButtonPress = millis();
  }
  if (digitalRead(11) == HIGH && redButtonPress+399 < millis())
  {
    redButtonPress = millis();
  }


  if (millis() <= yellowButtonPress+99 && millis() >= yellowButtonPress+2)
  {
    digitalWrite(2, HIGH);
  }else{digitalWrite (2, LOW);}

  if (millis() <= redButtonPress+99 && millis() >= redButtonPress+2)
  {
    digitalWrite(6, HIGH);
  }else{digitalWrite (6, LOW);}

  if (millis() >= yellowButtonPress+100 && millis() <= yellowButtonPress+199)
  {
    digitalWrite(3, HIGH);
  }else{digitalWrite (3, LOW);}

  if (millis() >= redButtonPress+100 && millis() <= redButtonPress+199)
  {
    digitalWrite(7, HIGH);
  }else{digitalWrite (7, LOW);}

  if (millis() >= yellowButtonPress+200 && millis() <= yellowButtonPress+299)
  {
    digitalWrite(4, HIGH);
  }else{digitalWrite (4, LOW);}

    if (millis() >= redButtonPress+200 && millis() <= redButtonPress+299)
  {
    digitalWrite(8, HIGH);
  }else{digitalWrite (8, LOW);}

  if (millis() >= yellowButtonPress+300 && millis() <= yellowButtonPress+399)
  {
    digitalWrite(5, HIGH);
  }else{digitalWrite (5, LOW);}

  if (millis() >= redButtonPress+300 && millis() <= redButtonPress+399)
  {
    digitalWrite(9, HIGH);
  }else{digitalWrite (9, LOW);}
}

This is how I would write the code for this project.

unsigned long yellowButtonPress = 0;
unsigned long yellowTimeElapsed = 0;
int yellowLED = 2

unsigned long redButtonPress = 0;
unsigned long redTimeElapsed = 0;
int redLED = 6

unsigned long MAX_Time = 400;

void setup(){
  //Setup the INPUT and OUTPUT pins
  for (int x=2; x<10; x++){
    pinMode(x, OUTPUT);
  }
    pinMode(12, INPUT);  //Yellow Button
    pinMode(13, INPUT);  //Red Button
}

void loop{
  yellowTimeElapsed = millis() - yellowButtonPress;
  redTimeElapsed = millis() - redButtonPress;

  //Check if yellow button has been pressed
  if(digitalRead(12) == HIGH && yellowTimeElapsed > MAX_Time){
    yellowButtonPress = millis();
  }

  //Check if red button has been pressed
  if(digitalRead(13) == HIGH && redTimeElapsed > MAX_Time){
    redButtonPress = millis();
  }

  //Identify which yellow LED needs to be on at this time
  if (yellowTimeElapsed > Max_Time){
    yellowLED=0; //This will turn off all yellow LEDs
  } else {
    yellowLED = map(yellowTimeElapsed, 0, MAX_Time, 2,5);
  }

  //Identify which red LED needs to be on at this time
  if (redTimeElapsed > Max_Time){
    redLED=0;  //This will turn off all red LEDs
  } else {
    redLED = map(redTimeElapsed, 0, MAX_Time, 6,9);
  }

  //Turn the yellow and/or red LEDs on and off
  for (int i = 2; i<10; i++){
    if (i == yellowLED || i == redLED){
      digitalWrite(i,HIGH);
    } else {
      digitalWrite(i,LOW);
    }
  }
}

I don't want to say "no, you can't," so let me just say the microprocessor can only process one calculation at a time.

You either need more than one microprocessor--you could use arduino nanos

--or you need to learn much more than I or anyone does about some very deep electronics to calculate how long it takes between when the processor tells an output to put out and when that actually happens, and then you'd have to do some truly remarkable acrobatics to include that knowledge into your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM