0
votes

In my code I want to replace the effect of delay() with millis or any other method that allows the use of button inputs while the code still runs. I am making an obstacle-type game where the player has to dodge incoming LEDs.

int LEDrows[4][4] = {{9, 8, 7, 6}, {5, 4, 3, 2}};
int Button = 1;
int ButtonCheck = 0;
int playerPosition = 0;

void setup()
{
  pinMode(Button, INPUT);
  for(int p=0; p>=1; p++){
    for(int b=0; b>=3; b++){
      pinMode(LEDrows[p][b], OUTPUT);
    }
  }
}

void loop()
{
  ButtonCheck = digitalRead(Button);
  if(ButtonCheck != 0){
    playerPosition += 1;
    
    if (playerPosition == 1){
      digitalWrite(LEDrows[0][3], HIGH);
      digitalWrite(LEDrows[1][3], LOW);
    }
    if (playerPosition > 1){
      playerPosition = 0;
      digitalWrite(LEDrows[1][3], HIGH);
      digitalWrite(LEDrows[0][3], LOW);
    }
  }
  
  int i = random(0, 2);
  for (int j = 0; j <= 3; j++) {
    digitalWrite(LEDrows[i][j], HIGH);
    delay(250);
    digitalWrite(LEDrows[i][j], LOW);
    delay(250);
  }
  delay(500);
}

I have two rows of 4 LEDS, stored in a nested list which i am iterating through. The LEDs will light up in a random row. I want to make the LED light up, wait 250ms, then make it disappear again, and wait 250ms. If this delay()-like effect can be achieved without using the delay function, then i would be pleased to learn how to do so.

2
This sketch from the Arduino website shows how to use millis() in a loop to delay without blocking interrupts. - JohnFilleau
Your code is not that easy to follow - and clearly does not do what you want. It would be better to specify what it is you require rather that (or as well as) presenting the code that fails to meet the requirements. Also better naming would help - perhaps column and row rather than i' and j` - if indeed that is what the y represent - it is not that easy to tell. - Clifford

2 Answers

1
votes

Use static variables to retain state and timestamps of the events you want to be periodic. For example, the following will set an LED in a random column on row zero, and every 250ms will move it to the next row until after reaching row 3, it will restart at a new random column.

  static int j = 0 ;
  static int i = 0 ;
  
  // When j == 0, set initial LED
  if( j == 0 )
  {
      i = random(0, 2);
      digitalWrite(LEDrows[i][j], HIGH ) ;
  }
  
     
  // Get current millisecond tick
  unsigned long now = millis() ;

  // Every 250ms move the LED     
  static unsigned long led_timestamp = millis() ;
  if( now - led_timestamp > 250 )
  {
      led_timestamp = now ;

      digitalWrite(LEDrows[i][j], LOW ) ;
      j++ ;
      if( j > 3 )
      {
          j = 0 ;
      }
      else
      {
          digitalWrite(LEDrows[i][j], HIGH ) ;
      }
  }

The general pattern is:

static unsigned long timestamp = millis() ;
unsigned long now = millis() ;

if( now - timestamp > PERIOD_MS )
{
    timestamp = now ;

    // do something every PERIOD_MS here
    ...
}

With multiple timestamp variables you can perform tasks at various independent intervals.

0
votes
void toggle(uint8_t row,uint8_t col){
 static long time[4][4];

 long curr_time = millis(); //current system time
 long last_time = time[row][col];

 if(curr_time >= (last_time + toogle_delay)){
    digitalWrite((LEDrows[row][col]),!digitalread((LEDrows[row][col])));
    time[row][col] = curr_time;
 }
 else{}
}