scanner, chaser and blinker

Trying to write code to allow for blinking, chasing and scanning using four push buttons. Not able to switch between the four while they are running continuously. Would appreciate some guidance

// One Button On/Off Toggle
const byte buttonPin[] = {14,15,16,13};     // the number of the pushbutton pin
const byte ledPin[] =  {3,4,5,6};      // the number of the LED pin
const int pinled1 = 12; 
const int pinled2 = 11;
const int pinled3 = 10;
const int pinled4 = 9;
const int pinled5 = 8;
const int pinled6 = 7;
const int pinled7 = 6;
const int pinled8 = 5;
const int pinled9 = 4;
const int pinled10 = 3;

// Variables will change:
int ledState[] = {LOW,LOW,LOW,LOW};         // the current state of the output pin
int buttonState[] = {LOW,LOW,LOW,LOW};             // the current reading from the input pin
int lastButtonState[] = {HIGH,HIGH,HIGH,HIGH};   // the previous reading from the input pin
int reading;
int foo;
int tim=88;//speed of blink
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers
int i = 0;
void setup() {
      for(int i = 0; i < 4; i++){
  pinMode(buttonPin[i], INPUT);
 // pinMode(ledPin[i], OUTPUT);
 }
 pinMode(pinled1, OUTPUT);
pinMode(pinled2, OUTPUT);
pinMode(pinled3, OUTPUT);
pinMode(pinled4, OUTPUT);
pinMode(pinled5, OUTPUT);
pinMode(pinled6, OUTPUT);
pinMode(pinled7, OUTPUT);
pinMode(pinled8, OUTPUT);
pinMode(pinled9, OUTPUT);
pinMode(pinled10, OUTPUT);    
}


void loop() {
 
                //  for(int i = 0; i < 4; i++){
  reading = digitalRead(buttonPin[i]);
   if (reading != lastButtonState[i]) {
      lastDebounceTime = millis();
      lastButtonState[i] = reading;
   } 
 
   if ((millis() - lastDebounceTime) > debounceDelay) {
       if (buttonState[i] != lastButtonState[i]) {
           buttonState[i] = lastButtonState[i];
           if (buttonState[i] == LOW) {
               //ledState[i] = !ledState[i];
                 //digitalWrite(ledPin[i], ledState[i]);
               
      
       foo = ledPin[i];
       while (foo){
       switch (foo) {
  case 3://chase right
  
   digitalWrite(pinled10, LOW);
digitalWrite(pinled1, HIGH); 
delay(tim); 
digitalWrite(pinled2, HIGH);
delay(tim);
digitalWrite(pinled1, LOW);
delay(tim);
digitalWrite(pinled3, HIGH);
delay(tim);
digitalWrite(pinled2, LOW);
delay(tim);
digitalWrite(pinled4, HIGH);
delay(tim);
digitalWrite(pinled3, LOW);
delay(tim);
digitalWrite(pinled5, HIGH);
delay(tim);
digitalWrite(pinled4, LOW);
delay(tim);
digitalWrite(pinled6, HIGH);
delay(tim);
digitalWrite(pinled5, LOW);
delay(tim);
digitalWrite(pinled7, HIGH);
delay(tim);
digitalWrite(pinled6, LOW);
delay(tim);
digitalWrite(pinled8, HIGH);
delay(tim);
digitalWrite(pinled7, LOW);
delay(tim);
digitalWrite(pinled9, HIGH);
delay(tim);
digitalWrite(pinled8, LOW);
delay(tim);
digitalWrite(pinled10, HIGH);
delay(tim);
digitalWrite(pinled9, LOW);
 delay(tim);
  
    break;
  case 4://blink
  
   digitalWrite(pinled1, HIGH);
digitalWrite(pinled2, HIGH);
digitalWrite(pinled3, HIGH);
digitalWrite(pinled4, HIGH);
digitalWrite(pinled5, HIGH);
digitalWrite(pinled6, HIGH);
digitalWrite(pinled7, HIGH);
digitalWrite(pinled8, HIGH);
digitalWrite(pinled9, HIGH);
digitalWrite(pinled10, HIGH);
delay(tim);
digitalWrite(pinled1, LOW);
digitalWrite(pinled2, LOW);
digitalWrite(pinled3, LOW);
digitalWrite(pinled4, LOW);
digitalWrite(pinled5, LOW);
digitalWrite(pinled6, LOW);
digitalWrite(pinled7, LOW);
digitalWrite(pinled8, LOW);
digitalWrite(pinled9, LOW);
digitalWrite(pinled10, LOW);
delay(tim + 1000);
  
    break;
    case 5://chase left
    digitalWrite(pinled1, LOW);
digitalWrite(pinled10, HIGH);
delay(tim);
digitalWrite(pinled9, LOW);
delay(tim);
digitalWrite(pinled9, HIGH);
delay(tim);
digitalWrite(pinled10, LOW);
delay(tim);
digitalWrite(pinled8, HIGH);
delay(tim);
digitalWrite(pinled9, LOW);
delay(tim);
digitalWrite(pinled7, HIGH);
delay(tim);
digitalWrite(pinled8, LOW);
delay(tim);
digitalWrite(pinled6, HIGH);
delay(tim);
digitalWrite(pinled7, LOW);
delay(tim);
digitalWrite(pinled5, HIGH);
delay(tim);
digitalWrite(pinled6, LOW);
delay(tim);
digitalWrite(pinled4, HIGH);
delay(tim);
digitalWrite(pinled5, LOW);
delay(tim);
digitalWrite(pinled3, HIGH);
delay(tim);
digitalWrite(pinled4, LOW);
delay(tim);
digitalWrite(pinled2, HIGH);
delay(tim); 
digitalWrite(pinled3, LOW);
delay(tim);
digitalWrite(pinled1, HIGH);
delay(tim);
digitalWrite(pinled2, LOW);
delay(tim);  

    break;
    case 6://scan
    digitalWrite(pinled1, HIGH); 
delay(tim); 
digitalWrite(pinled2, HIGH);
delay(tim);
digitalWrite(pinled1, LOW);
delay(tim);
digitalWrite(pinled3, HIGH);
delay(tim);
digitalWrite(pinled2, LOW);
delay(tim);
digitalWrite(pinled4, HIGH);
delay(tim);
digitalWrite(pinled3, LOW);
delay(tim);
digitalWrite(pinled5, HIGH);
delay(tim);
digitalWrite(pinled4, LOW);
delay(tim);
digitalWrite(pinled6, HIGH);
delay(tim);
digitalWrite(pinled5, LOW);
delay(tim);
digitalWrite(pinled7, HIGH);
delay(tim);
digitalWrite(pinled6, LOW);
delay(tim);
digitalWrite(pinled8, HIGH);
delay(tim);
digitalWrite(pinled7, LOW);
delay(tim);
digitalWrite(pinled9, HIGH);
delay(tim);
digitalWrite(pinled8, LOW);
delay(tim);
digitalWrite(pinled10, HIGH);
delay(tim);
digitalWrite(pinled9, LOW);
delay(tim);
digitalWrite(pinled9, HIGH);
delay(tim);
digitalWrite(pinled10, LOW);
delay(tim);
digitalWrite(pinled8, HIGH);
delay(tim);
digitalWrite(pinled9, LOW);
delay(tim);
digitalWrite(pinled7, HIGH);
delay(tim);
digitalWrite(pinled8, LOW);
delay(tim);
digitalWrite(pinled6, HIGH);
delay(tim);
digitalWrite(pinled7, LOW);
delay(tim);
digitalWrite(pinled5, HIGH);
delay(tim);
digitalWrite(pinled6, LOW);
delay(tim);
digitalWrite(pinled4, HIGH);
delay(tim);
digitalWrite(pinled5, LOW);
delay(tim);
digitalWrite(pinled3, HIGH);
delay(tim);
digitalWrite(pinled4, LOW);
delay(tim);
digitalWrite(pinled2, HIGH);
delay(tim); 
digitalWrite(pinled3, LOW);
delay(tim);
digitalWrite(pinled1, HIGH);
delay(tim);
digitalWrite(pinled2, LOW);
delay(tim);  
    break;
  //default: 
    // statements
}  
       }//while
           }
           
       }
       
   }      
                //  }//for
   
   i++;
if(i>3){
  i=0;
      }
     
}//end loop

Hi, you have reached that point in your programming skills where you have to start thinking in a different way. The starting point for the next stage of learning is the classic Blink Without Delay sketch. Then you have to learn about "state machines". This sounds ominous at first but seems like the most obvious thing in the world once you are familliar with it.

The reason for this change is that you are currently used to getting the Arduino to do a sequence of actions by writing code to do those actions in sequence with delay() commands between. This means the Arduino cannot really do other tasks at the same time. That is because the Arduino has a very simple 1-core processor and no operating system that manages the muti-threading we all take for granted on desktop PCs.

So instead of encoding the sequence of actions with lines of code, you have to think about representing the sequence of actions as a list or stream of data held in memory (could be ram or flash). Your sketch then has to read that stream of data, carry out the actions, time the delays between them and keep track of the current position in the stream. This means it is free to do other things in the delays, even managing multiple sequences which are running cuncurrently and asynchronously.

As a compromise, you can use a technique where you use switch/case statements to execute one step of a sequence at a time. Each step must be given its own step number. The switch statement contains the code to perform the actions at each step. It can also set the delay time required before the next step, but it does not actually do that delay. Instead, it returns control to loop().

Hope that doesn't worry you too much!

Paul

Thanks for your reply and comment about delay() .

This code allows for quick response when using a switch, but is not easy to understand, is difficult to compile and add DMXSerial.h to it. It may have the answers I need. The unit will primarily run DMX, but will have switches for testing, overriding DMX.

/*
 * Larson Scanner v1.0
 * by Ray Kuyvenhoven
 * 21 May 2011
 * Modified by Praken: 15/11/2014
 * This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law.
 * You can copy, modify, use and/or redistribute it as you see fit.
 *
 *
 * pattern data is stored in flash (program) memory to save SRAM.
 *
 */
 
#include <avr/pgmspace.h>

#define NUM_PATTERNS 4  //15
#define SPEED_SIZE 8  //8

int pin[] = {12,11,10,9,8,7,6,5,4,3};
int buttonPin[] = {14,15,16,13};    // pin A0,A1,A2,13
int scannerSpeed[SPEED_SIZE] = {100, 8, 7, 5, 4, 3, 2, 1};
//int scannerSpeed[SPEED_SIZE] = {500, 400};   //set speed 100, 20

char buffer[10];
byte pattern[10];  //10
long wait;  
  
boolean lastButton[] = {HIGH, HIGH, HIGH, HIGH};  //LOW, LOW, LOW
boolean currButton[] = {HIGH, HIGH, HIGH, HIGH};  //LOW, LOW, LOW

int currPattern = 0;
int currRow = 0;
int currSpeed = 4; 
int sensorPin = A3;    //   pin A3
int DE = 2;  // DE is pin MAX3089

void setup() {  
  pinMode(DE, OUTPUT);    //  control DE pin MAX3089    
  Serial.begin(9600);  

  for (int i=0; i < 10; i++) {
    pinMode(pin[i], OUTPUT);
    digitalWrite(pin[i], LOW);
  }
  randomSeed(analogRead(sensorPin));  // read pin A3 
}

boolean debounce(int switchPin, boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void processButtons() {
  int button;
  
  button = 0;   // pin
  currButton[button] = debounce(buttonPin[button], lastButton[button]);
  if (lastButton[button] == LOW && currButton[button] == HIGH) 
    {

    currPattern =0;

    Serial.print("Set pattern: ");
    Serial.println(currPattern);    
    currRow = 0;
  }
  lastButton[button] = currButton[button];
  
  button = 1;   //pin15  
 
  currButton[button] = debounce(buttonPin[button], lastButton[button]);
  if (lastButton[button] == LOW && currButton[button] == HIGH)
    {

    currPattern =1;

    Serial.print("Set pattern: ");
    Serial.println(currPattern);    
    currRow = 0;  //0
  }
  lastButton[button] = currButton[button];  

    button = 2;   // pin
  currButton[button] = debounce(buttonPin[button], lastButton[button]);
  if (lastButton[button] == LOW && currButton[button] == HIGH) 
    {

    currPattern =2;

    Serial.print("Set pattern: ");
    Serial.println(currPattern);    
    currRow = 0;
  }
  lastButton[button] = currButton[button];
  
  button = 3;   //pin15  
 
  currButton[button] = debounce(buttonPin[button], lastButton[button]);
  if (lastButton[button] == LOW && currButton[button] == HIGH)
    {

    currPattern =3;

    Serial.print("Set pattern: ");
    Serial.println(currPattern);    
    currRow = 0;  //0
  }
  lastButton[button] = currButton[button];  
  }

void loop() {
  digitalWrite(DE, HIGH);  //   enable DE pin MAX3089 
  currRow = getRow(currPattern, currRow, &pattern[0]);
  for (int i=0; i < 10; i++) {
    digitalWrite(pin[i], pattern[i]);
  }

  wait = millis() + scannerSpeed[currSpeed];
  while (millis() < wait) {
    delay(15);
    processButtons();     
  }
  long time = millis();

int sensorValue = map(analogRead(sensorPin), 0, 1023, 0, 1000);
while (sensorValue >= (millis() - time)) {
sensorValue = analogRead(sensorPin);
}
time = millis();
}  


// pattern A-Larson
  prog_char pattern_A_0[]  PROGMEM = "1000000000"; 
  prog_char pattern_A_1[]  PROGMEM = "1100000000";
  prog_char pattern_A_2[]  PROGMEM = "1110000000";
  prog_char pattern_A_3[]  PROGMEM = "1111000000";
  prog_char pattern_A_4[]  PROGMEM = "1111100000";
  prog_char pattern_A_5[]  PROGMEM = "0111110000";
  prog_char pattern_A_6[]  PROGMEM = "0011111000";
  prog_char pattern_A_7[]  PROGMEM = "0001111100";
  prog_char pattern_A_8[]  PROGMEM = "0000011110";
  prog_char pattern_A_9[]  PROGMEM = "0000001111";
  prog_char pattern_A_10[] PROGMEM = "0000000111";
  prog_char pattern_A_11[] PROGMEM = "0000000011";
  prog_char pattern_A_12[] PROGMEM = "0000000001";

  prog_char pattern_A_13[] PROGMEM = "0000000001";
  prog_char pattern_A_14[] PROGMEM = "0000000011";
  prog_char pattern_A_15[] PROGMEM = "0000000111";
  prog_char pattern_A_16[] PROGMEM = "0000001111";
  prog_char pattern_A_17[] PROGMEM = "0000011110";
  prog_char pattern_A_18[] PROGMEM = "0001111100";
  prog_char pattern_A_19[] PROGMEM = "0011111000";
  prog_char pattern_A_20[] PROGMEM = "0111110000";
  prog_char pattern_A_21[] PROGMEM = "1111100000";
  prog_char pattern_A_22[] PROGMEM = "1111000000";
  prog_char pattern_A_23[] PROGMEM = "1110000000";
  prog_char pattern_A_24[] PROGMEM = "1100000000";
  prog_char pattern_A_25[] PROGMEM = "1000000000"; 
  
  PROGMEM const char *pattern_A[] = {   
    pattern_A_0,
    pattern_A_1,
    pattern_A_2,
    pattern_A_3,
    pattern_A_4,
    pattern_A_5,
    pattern_A_6,
    pattern_A_7,
    pattern_A_8,
    pattern_A_9,
    pattern_A_10,
    pattern_A_11,
    pattern_A_12,
    pattern_A_13,
    pattern_A_14,
    pattern_A_15,
    pattern_A_16,
    pattern_A_17,
    pattern_A_18,
    pattern_A_19,
    pattern_A_20,
    pattern_A_21,
    pattern_A_22,
    pattern_A_23,
    pattern_A_24,
    pattern_A_25, 
  };


 // pattern B-Blinker
  prog_char pattern_B_0[] PROGMEM = "1111111111"; 
  prog_char pattern_B_1[] PROGMEM = "1111111111";
  prog_char pattern_B_2[] PROGMEM = "1111111111"; 
  prog_char pattern_B_3[] PROGMEM = "1111111111";
  prog_char pattern_B_4[] PROGMEM = "0000000000";
  prog_char pattern_B_5[] PROGMEM = "0000000000";
  prog_char pattern_B_6[] PROGMEM = "0000000000";
  prog_char pattern_B_7[] PROGMEM = "0000000000"; 

 
  PROGMEM const char *pattern_B[] = {   
    pattern_B_0,
    pattern_B_1,
    pattern_B_2,
    pattern_B_3,  
    pattern_B_4,
    pattern_B_5,
    pattern_B_6,
    pattern_B_7,
  };

// pattern B1-Blinker
  prog_char pattern_B1_0[] PROGMEM = "0000000000";
  PROGMEM const char *pattern_B1[] = {   
    pattern_B1_0, 
 }; 


// pattern C-Chaser
  prog_char pattern_C_0[] PROGMEM = "1000000000"; 
  prog_char pattern_C_1[] PROGMEM = "0100000000";
  prog_char pattern_C_2[] PROGMEM = "001000000";
  prog_char pattern_C_3[] PROGMEM = "0001000000";
  prog_char pattern_C_4[] PROGMEM = "0000100000";
  prog_char pattern_C_5[] PROGMEM = "0000010000";
  prog_char pattern_C_6[] PROGMEM = "0000001000";
  prog_char pattern_C_7[] PROGMEM = "0000000100";
  prog_char pattern_C_8[] PROGMEM = "0000000010";
  prog_char pattern_C_9[] PROGMEM = "0000000001";
 
  PROGMEM const char *pattern_C[] = {   
    pattern_C_0,
    pattern_C_1,
    pattern_C_2,
    pattern_C_3,
    pattern_C_4,
    pattern_C_5,
    pattern_C_6,
    pattern_C_7,
    pattern_C_8,
    pattern_C_9,
  };
// pattern C1-Chaser
  prog_char pattern_C1_0[] PROGMEM = "0000000001";
  prog_char pattern_C1_1[] PROGMEM = "0000000010";
  prog_char pattern_C1_2[] PROGMEM = "0000000100";
  prog_char pattern_C1_3[] PROGMEM = "0000001000";
  prog_char pattern_C1_4[] PROGMEM = "0000010000";
  prog_char pattern_C1_5[] PROGMEM = "0000100000";
  prog_char pattern_C1_6[] PROGMEM = "0001000000";
  prog_char pattern_C1_7[] PROGMEM = "0010000000";
  prog_char pattern_C1_8[] PROGMEM = "0100000000"; 
  prog_char pattern_C1_9[] PROGMEM = "1000000000"; 
 
  PROGMEM const char *pattern_C1[] = {   
    pattern_C1_0,
    pattern_C1_1,
    pattern_C1_2,
    pattern_C1_3,
    pattern_C1_4,
    pattern_C1_5,
    pattern_C1_6,
    pattern_C1_7,
    pattern_C1_8,
    pattern_C1_9,
 }; 
/*
 * getRow
 * 
 * sets the rowData and returns the next row to be displayed,
 * 
 */
int getRow(int pattern, int row, byte *rowData) {
  int size;
  
  if (pattern == 0) {
    strcpy_P(buffer, (char*)pgm_read_word(&(pattern_A[row])));
    size = 26;
    }
    if (pattern == 1) {
    strcpy_P(buffer, (char*)pgm_read_word(&(pattern_B[row])));
    size = 8;
    }
    if (pattern == 2) {
    strcpy_P(buffer, (char*)pgm_read_word(&(pattern_C[row])));
    size = 10;
    }
    if (pattern == 3) {
    strcpy_P(buffer, (char*)pgm_read_word(&(pattern_C1[row])));
    size = 10;
    }  
    if (pattern == 4) {
    for (int i=0; i < 10; i++) {
      rowData[i] = random(2);
    }

  return 0; 
    }   

  for (int i=0; i < 10; i++) {
    if (buffer[i] == '1') {
      rowData[i] = 1;
    }
    else {
      rowData[i] = 0;
    }
  }
  row++;
  if (row >= size) {
    row = 0;
  }  
  return row;
}

Using the following code, the unit chases nicely. Trying now to get the Larson Scanner to work.

// constants won't change. Used here to
// set pin numbers:
const int ledPin[] = {3,4,5,6,7,8,9,10,11,12}; // the number of the LED pin

// Variables will change:
long previousMillis = 0; // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 100; // interval at which to blink (milliseconds)
int i = 0 ;
void setup() {
// set the digital pin as output:
for(int c = 0; c < 10; c++ ){
pinMode(ledPin

, OUTPUT);
}  
}

void loop()
{

unsigned long currentMillis = millis();
                       digitalWrite(ledPin[i],HIGH);
                       
if(currentMillis - previousMillis > interval) {
  // save the last time you blinked the LED 
  previousMillis = currentMillis;   

  // set the LED with the ledState of the variable:

  digitalWrite(ledPin[i], LOW);
  
if(i>=10){
i=-1; 
}
i++;                       
}
//digitalWrite(ledPin[i], ledState);
}  

To reverse the chase, you just make i = 10 and use i--   Getting the i to go from 0 to 9 and back is perplexing .
  
Any help on the Larson scanner would be appreciated.  Thanks !

You forgot the code tags this time. Your sketch makes a good demonstration of why code tags are important. Notice the sketch suddenly changing to italic font? What's missing at that point in the code?