Blinking 5

Hi Guys,

I'm not novice in electronics, but only starting with programming. Now I have a project, digit 5 made of 14 LEDs in following pattern:

X X X X

X

X X X
X

X

X
X X X

I want to continuously blink them in various patterns, eg one by one lit all and then down, lit on from left to right and down, from top to bottom, etc.

I read tutorial in "Programming" section, and my idea to make every pattern as separate function and in main body of the program only call those functions in order I like, but before reading that, my idea was to use a kind of sentences like 10000000000000, 11000000000000, etc and feed this into executing module. This way is easier for me as beginner to create patterns I like, though I understand, that it may not be "nice looking".

Please advise which way you suggest me to choose and I will much appreciate if you give me a links to similar projects.

Forgot to mention, that I'm using Mega2560, so the number of outputs is not a problem and multiplexing is not required

Take a look at:
http://www.thebox.myzen.co.uk/Tutorial/Arrays.html

Thanx LarryD, it halped a lot! This is my first ever program (besides those BASIC in school 30 years back) and I'm proud since it working!)

int pins [15] = { 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50 };

long previousMillis = 0;        // will store last time LED was updated
int ledState = LOW;             // ledState used to set the LED

void setup() {

  for(int i=0; i<15; i++) pinMode(pins[i], OUTPUT);
  for(int i=0; i<15; i++) digitalWrite(pins[i], LOW);
}

void loop() {
  
 // BlinkAllWithDelay(1000); 
  BlinkAllWithoutDelay(1000);
  
  }


void BlinkAllWithDelay(long Int1) {
  
  for(int i=0; i<15; i++) digitalWrite(pins[i], HIGH);
  delay(Int1);
  for(int i=0; i<15; i++) digitalWrite(pins[i], LOW);
  delay(Int1);
  
  }

void BlinkAllWithoutDelay(long Int2) {
   
   unsigned long currentMillis = millis();
  
   if(currentMillis - previousMillis > Int2) {
      previousMillis = currentMillis;
    
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    for(int i=0; i<15; i++) digitalWrite(pins[i], ledState);

  }
}

I managed to write compilable code, and, using basic examples, to make two BlinkAll functions (just for learning, though one of them I may be able to use). But I'm still far away from my target and second part of article at your link is not very clear to me:

  1. Those binary numbers ( B11001010 etc) - are they have to be eight bit long only, or I can have them 14 bit long?

  2. The "mask" story looks nice, but still beyond my comprehension. I'm thinking about something

for(int i=0; i<15; i++) digitalWrite(pins[i], and then all 14 bits of my pattern bit by bit.

Basically, I need to find the way for parallel output of 14-bit binary numbers to 14 pins with adjustable timing.

Can you or smb else help me to code this please?

If I am understanding you correctly, int is 16 bits in length you need 14, no problem.
Make your perviousMillis into type unsigned long

EDIT:
Is this the way you have things wired?

This should give you a good idea what you need to do:

//#define UNO
//#define MEGA

//#ifdef UNO
//byte pins[14] = {
//  2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//#endif

//#ifdef MEGA

byte pins[14] = {
  22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48};

//#endif

byte ledPattern = 0;   

//LED patterns defined in Arrays
int consecutiveOn[14] = {
  //44444333332222       LED
  //86420864208642       Numbers
  0b00000000000001,  //0 Array element number
  0b00000000000011,  //1
  0b00000000000111,  //2
  0b00000000001111,  //3
  0b00000000011111,  //4
  0b00000000111111,  //5
  0b00000001111111,  //6
  0b00000011111111,  //7
  0b00000111111111,  //8
  0b00001111111111,  //9
  0b00011111111111,  //10
  0b00111111111111,  //11
  0b01111111111111,  //12
  0b11111111111111}; //13

int consecutiveOff[14] = {
  //44444333332222       LED
  //86420864208642       Numbers
  0b01111111111111,  //0 Array element number
  0b00111111111111,  //1
  0b00011111111111,  //2
  0b00001111111111,  //3
  0b00000111111111,  //4
  0b00000011111111,  //5
  0b00000001111111,  //6
  0b00000000111111,  //7
  0b00000000011111,  //8
  0b00000000001111,  //9
  0b00000000000111,  //10
  0b00000000000011,  //11
  0b00000000000001,  //12
  0b00000000000000}; //13

const unsigned long consecutiveOnWait   = 100UL; //every 1/10 Sec 
const unsigned long consecutiveOffWait  = 100UL; //every 1/10 Sec
//add more as needed

unsigned long consecutiveOnMillis;               //
unsigned long consecutiveOffMillis;              //
//add more as needed

unsigned long currentmillis; 

//other variables

//define the available states that we can have for this sketch
enum States{
  consecOn, consecOff};   //add more as needed
States mState = consecOn; //we start out in this machine state 

//========================================================== 
void setup()
{
  Serial.begin(9600);

  currentmillis = millis();
  consecutiveOnMillis  = currentmillis;   //initailize all times 
  consecutiveOffMillis = currentmillis;   //

  for( byte i = 0; i < 15; i++ )
  { 
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], LOW); //turn off the LED
  }

  mState = consecOn;            //we start out in this machine state 
  ledPattern = 0;

} //        >>>>>>>>>>>>>> END OF setup() <<<<<<<<<<<<<<<<<


void loop()
{
  // keep this at this location
  currentmillis = millis();  


  //********* Other loop stuff goes here ************** 


  //************** State Machine section ************** 
  switch (mState)
  {
    //***************************
  case consecOn:

    //is it time to display the next led pattern?
    if (currentmillis - consecutiveOnMillis >= consecutiveOnWait) 
    {
      consecutiveOnMillis += consecutiveOnWait;  //get ready for the next timing cycle

      //Send the next LED pattern to all 14 LEDs
      int mask = 1;
      for (byte x = 0; x < 15; x++)
      {
        //examples, let's say we are now at ledPattern = 2:
        //mask is          00000000000001 1
        //consecutiveOn[2] 00000000000111 Array element 2 (as an example)
        // &                            1 != 0

        //mask is          00000000000010 2  one shift
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                           10 != 0

        //mask is          00000000000100 4  two shifts
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                          100 != 0

        //mask is          00000000001000 8  tree shifts
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                         0000 == 0

        //Note: very first time through ledPattern = 0
        if((mask & consecutiveOn[ledPattern]) == 0)
        {
          //turn off this LED
          digitalWrite(pins[x], LOW); 
        }
        else
        {
          //turn on this LED
          digitalWrite(pins[x], HIGH);
        }

        //we do this 13 times
        mask = mask << 1;

      }  //end of processing all 14 LEDs

      //get ready fo the next LED pattern
      ledPattern++;
      if (ledPattern > 13)
      {
        ledPattern = 0;
        mState = consecOff;
        consecutiveOffMillis = millis();
      }

    } //end of this time period

    break;

    //***************************
  case consecOff:
    //is it time to run this section of code?
    if (currentmillis - consecutiveOffMillis >= consecutiveOffWait) 
    {
      //Send the next LED pattern to all 14 LEDs
      int mask = 1;
      for (byte x = 0; x < 15; x++)
      {
        if((mask & consecutiveOff[ledPattern]) == 0)
        {
          //turn off this LED
          digitalWrite(pins[x], LOW); 
        }
        else
        {
          //turn on this LED
          digitalWrite(pins[x], HIGH);
        }

        //we do this 13 times
        mask = mask << 1;

      }  //end of processing all 14 LEDs

      //get ready fo the next LED pattern
      ledPattern++;
      if (ledPattern > 13)
      {
        ledPattern = 0;
        mState = consecOn;
        consecutiveOnMillis = millis();
      }

    } //end of this time period


    break;

    //***************************
  default: 
    // statements
    break;

    
  } // end of switch/case


} //        >>>>>>>>>>>>>> END OF loop() <<<<<<<<<<<<<<<<<



// FUNCTIONS



//=============================================================
//                             END OF CODE
//=============================================================
  1. Those binary numbers ( B11001010 etc) - are they have to be eight bit long only, or I can have them 14 bit long?

If they start with a capital B then yes those are only 8 bits long, but if they start with zero, lower case b, that is 0b then they can be up to 16 bits long.

The "mask" story looks nice, but still beyond my comprehension.

A mask you wear, covers up part of your face and lets other parts show.
It is just the same with numbers, a mask can blat out individual bits in a bit pattern ( number or variable ) to set or clear some bits while leaving others unchanged.

Thanks for Your replies guys!

Yes, LarryD, this is my wiring, plus on pin 50 I have npn to drive 4 additional bright white LEDs to strobe time by time, and now considering to use 52 to play a melody.

To give more idea - this project is 5th anniversary gift's package box.

The code in your last message can not be compiled, giving errors:

_5_3:15: error: 'byte' does not name a type
_5_3:19: error: 'byte' does not name a type
_5_3.ino: In function 'void setup()':
_5_3:78: error: 'Serial' was not declared in this scope
_5_3:80: error: 'millis' was not declared in this scope
_5_3:84: error: 'byte' was not declared in this scope
_5_3:84: error: expected ;' before 'i' _5_3:84: error: 'i' was not declared in this scope _5_3:86: error: 'pins' was not declared in this scope _5_3:86: error: 'OUTPUT' was not declared in this scope _5_3:86: error: 'pinMode' was not declared in this scope _5_3:87: error: 'LOW' was not declared in this scope _5_3:87: error: 'digitalWrite' was not declared in this scope _5_3:91: error: 'ledPattern' was not declared in this scope _5_3.ino: In function 'void loop()': _5_3:99: error: 'millis' was not declared in this scope _5_3:118: error: 'byte' was not declared in this scope _5_3:118: error: expected ;' before 'x'
_5_3:118: error: 'x' was not declared in this scope
_5_3:138: error: 'ledPattern' was not declared in this scope
_5_3:141: error: 'pins' was not declared in this scope
_5_3:141: error: 'LOW' was not declared in this scope
_5_3:141: error: 'digitalWrite' was not declared in this scope
_5_3:146: error: 'pins' was not declared in this scope
_5_3:146: error: 'HIGH' was not declared in this scope
_5_3:146: error: 'digitalWrite' was not declared in this scope
_5_3:155: error: 'ledPattern' was not declared in this scope
_5_3:174: error: 'byte' was not declared in this scope
_5_3:174: error: expected `;' before 'x'
_5_3:174: error: 'x' was not declared in this scope
_5_3:176: error: 'ledPattern' was not declared in this scope
_5_3:179: error: 'pins' was not declared in this scope
_5_3:179: error: 'LOW' was not declared in this scope
_5_3:179: error: 'digitalWrite' was not declared in this scope
_5_3:184: error: 'pins' was not declared in this scope
_5_3:184: error: 'HIGH' was not declared in this scope
_5_3:184: error: 'digitalWrite' was not declared in this scope
_5_3:193: error: 'ledPattern' was not declared in this scope

_5_3 - this is sketch name - disregard. Without proper coding culture I'm not fully understand where I had to declare those numbers, but I will have closer look. The main idea in your code is clear for me, with thanks again, and perhaps I will use it in final project.

By now I found very nice solution LED effects library - Libraries - Arduino Forum, which suits almost all my needs for this project, though, with a second look into musk solution, will also try to play with.

Now, I want to extend my project to play sound while blinking, but so far have no idea how to make this simultaneously - the examples in tutorials are so far helped me to play sound and then blink LEDs.

Appreciate any suggestions)

Grumpy_Mike, thanks for your reply again. I managed code below - but it does not work properly: first seven LEDs lit at once all together, and rest are one by one - I think something wrong with data type declaration, but not sure - any suggestion?

int LEDPin [15] = { 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50 }; // pin numbers used for LEDs

char Pattern1 [14] = { 0b10000000000000, 0b11000000000000, 0b11100000000000, 0b11110000000000, 0b11111000000000, 0b11111100000000, 0b11111110000000, 0b11111111000000, 0b11111111100000, 0b11111111110000, 0b11111111111000, 0b11111111111100, 0b11111111111110, 0b11111111111111 };


void setup() {
  // use a for loop to initialize each pin as an output:
  for (int i = 0; i < 16; i++)  {
    pinMode(LEDPin[i], OUTPUT);      
  }
}

void loop() {
  
  for(int j = 0; j < 14; j++) {
    ShowPattern ( Pattern1[j]);
    delay(500);
  }


  }

void ShowPattern(int Frame){
  
    
  int mask = 1;
  for(int i=0; i<14; i++){
   if((mask & Frame) == 0) digitalWrite( LEDPin[i], LOW); else digitalWrite(LEDPin[i], HIGH);
   mask = mask << 1;
  }

}
char Pattern1 [14]

A char is only one byte ( 8 bits ) so trying to cram 14 bits into it is not going to work. It should be:-

int Pattern1 [14]

I don't have mega 256, but the code works great on the UNO.
What IDE are you using?
Did you make any changes to my code prior to compiling it?

See my post below

My mistake, try this:

byte pins[14] = {
  22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48};

byte ledPattern = 0;   

//LED patterns defined in Arrays
int consecutiveOn[14] = {
  //44444333332222       LED
  //86420864208642       Numbers
  0b00000000000001,  //0 Array element number
  0b00000000000011,  //1
  0b00000000000111,  //2
  0b00000000001111,  //3
  0b00000000011111,  //4
  0b00000000111111,  //5
  0b00000001111111,  //6
  0b00000011111111,  //7
  0b00000111111111,  //8
  0b00001111111111,  //9
  0b00011111111111,  //10
  0b00111111111111,  //11
  0b01111111111111,  //12
  0b11111111111111}; //13

int consecutiveOff[14] = {
  //44444333332222       LED
  //86420864208642       Numbers
  0b01111111111111,  //0 Array element number
  0b00111111111111,  //1
  0b00011111111111,  //2
  0b00001111111111,  //3
  0b00000111111111,  //4
  0b00000011111111,  //5
  0b00000001111111,  //6
  0b00000000111111,  //7
  0b00000000011111,  //8
  0b00000000001111,  //9
  0b00000000000111,  //10
  0b00000000000011,  //11
  0b00000000000001,  //12
  0b00000000000000}; //13

const unsigned long consecutiveOnWait   = 100UL; //every 1/10 Sec 
const unsigned long consecutiveOffWait  = 100UL; //every 1/10 Sec
//add more as needed

unsigned long consecutiveOnMillis;               //
unsigned long consecutiveOffMillis;              //
//add more as needed

unsigned long currentmillis; 

//other variables

//define the available states that we can have for this sketch
enum States{
  consecOn, consecOff};   //add more as needed
States mState = consecOn; //we start out in this machine state 

//========================================================== 
void setup()
{
  Serial.begin(9600);

  currentmillis = millis();
  consecutiveOnMillis  = currentmillis;   //initailize all times 
  consecutiveOffMillis = currentmillis;   //

  for( byte i = 0; i < 15; i++ )
  { 
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], LOW); //turn off the LED
  }

  mState = consecOn;            //we start out in this machine state 
  ledPattern = 0;

} //        >>>>>>>>>>>>>> END OF setup() <<<<<<<<<<<<<<<<<


void loop()
{
  // keep this at this location
  currentmillis = millis();  

  //********* Other loop stuff goes here ************** 



  //************** State Machine section ************** 
  switch (mState)
  {
    //***************************
  case consecOn:

    //is it time to display the next led pattern?
    if (currentmillis - consecutiveOnMillis >= consecutiveOnWait) 
    {
      consecutiveOnMillis += consecutiveOnWait;  //get ready for the next timing cycle

      //Send the next LED pattern to all 14 LEDs
      int mask = 1;
      for (byte x = 0; x < 15; x++)
      {
        //examples, let's say we are now at ledPattern = 2:
        //mask is          00000000000001 1
        //consecutiveOn[2] 00000000000111 Array element 2 (as an example)
        // &                            1 != 0

        //mask is          00000000000010 2  one shift
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                           10 != 0

        //mask is          00000000000100 4  two shifts
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                          100 != 0

        //mask is          00000000001000 8  tree shifts
        //consecutiveOn[2] 00000000000111 Array element 2
        // &                         0000 == 0

        //Note: very first time through ledPattern = 0
        if((mask & consecutiveOn[ledPattern]) == 0)
        {
          //turn off this LED
          digitalWrite(pins[x], LOW); 
        }
        else
        {
          //turn on this LED
          digitalWrite(pins[x], HIGH);
        }

        //we do this 13 times
        mask = mask << 1;

      }  //end of processing all 14 LEDs

      //get ready fo the next LED pattern
      ledPattern++;
      if (ledPattern > 13)
      {
        ledPattern = 0;
        mState = consecOff;
        consecutiveOffMillis = millis();
      }

    } //end of this time period

    break;

    //***************************
  case consecOff:
    //is it time to run this section of code?
    if (currentmillis - consecutiveOffMillis >= consecutiveOffWait) 
    {
      //Send the next LED pattern to all 14 LEDs
      int mask = 1;
      for (byte x = 0; x < 15; x++)
      {
        if((mask & consecutiveOff[ledPattern]) == 0)
        {
          //turn off this LED
          digitalWrite(pins[x], LOW); 
        }
        else
        {
          //turn on this LED
          digitalWrite(pins[x], HIGH);
        }

        //we do this 13 times
        mask = mask << 1;

      }  //end of processing all 14 LEDs

      //get ready fo the next LED pattern
      ledPattern++;
      if (ledPattern > 13)
      {
        ledPattern = 0;
        mState = consecOn;
        consecutiveOnMillis = millis();
      }

    } //end of this time period


    break;

    //***************************
  default: 
    // statements
    break;

    
  } // end of switch/case


} //        >>>>>>>>>>>>>> END OF loop() <<<<<<<<<<<<<<<<<



// FUNCTIONS



//=============================================================
//                             END OF CODE
//=============================================================

Thanks LarryD, Your code is working fine now, but it's a bit cumbersome... Same thing, with my understanding of use of mask now, and with help and explanation of Grumpy_Mike (Thanks!) my similar code now:

int LEDPin [15] = { 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50 }; // pin numbers used for LEDs

int Pattern1 [14] = { 0b10000000000000, 0b11000000000000, 0b11100000000000, 0b11110000000000, 0b11111000000000, 0b11111100000000, 0b11111110000000, 0b11111111000000, 0b11111111100000, 0b11111111110000, 0b11111111111000, 0b11111111111100, 0b11111111111110, 0b11111111111111 };
int Pattern2 [14] = { 0b00000000000001, 0b00000000000011, 0b00000000000111, 0b00000000001111, 0b00000000011111, 0b00000000111111, 0b00000001111111, 0b00000011111111, 0b00000111111111, 0b00001111111111, 0b00011111111111, 0b00111111111111, 0b01111111111111, 0b11111111111111 };
int Pattern3 [8] = { 0b10000000111000, 0b11000001111100, 0b11100011111110, 0b11111111111111, 0b01111111000111, 0b00111110000011, 0b00011100000001, 0b00000000000000 };

// Patterns - each binary number represents one frame

void setup() {
  // use a for loop to initialize each pin as an output, 15th pin to be used for quick strobing bright white LEDs here and there...
  for (int i = 0; i < 16; i++)  {
    pinMode(LEDPin[i], OUTPUT);      
  }
}

void loop() {
  
  for(int j = 0; j < 14; j++) {
    ShowPattern ( Pattern1[j]);
    delay(500); // delay between frames
    
  }

// Strobe

for(int j = 0; j < 14; j++) {
    
    ShowPattern ( Pattern2[j]);
    delay(500); // delay between frames
}

// Strobe

for(int j = 0; j < 8; j++) {
    
    ShowPattern ( Pattern3[j]);
    delay(500); // delay between frames
}

// Strobe
  }

void ShowPattern(int Frame){
  
    
  int mask = 1;
  for(int i=0; i<14; i++){
   if((mask & Frame) == 0) digitalWrite( LEDPin[i], LOW); else digitalWrite(LEDPin[i], HIGH); // Function, which reads binary sequences bit by bit into output pins pin by pin
   mask = mask << 1;
  }

}

This is exactly, what I wanted, easy to understand, only one function reads all patterns, and creating patterns is straight forward frame by frame and easy to understand. It does not need additional library, as the one I found above, so, I will probably stick to this one...

But, again and again, thanks to both of You - two days ago I had no faith I can do it myself and only expected to find something ready and adjust for my needs.

Any suggestion how to play melody in background?

Keep in mind my version is flexible, maintainable, can add patterns as needed, leaves loop running fast for other things, and introduces several constructs which you should learn.

Happy 5th!