Go Down

Topic: For loops?? (Read 3 times) previous topic - next topic

marco_c

What you can do with Multiblink as it stands is blink one LED fast (say at 50 ms) and then another one slowly (say at 150ms) by creating a table of 2 elements.

What will happen is that on the third blink the second LED will light at the same time as the first. That is probably not what you are looking for,

There is a way to modify multblink to include the cycling a pattern and then adding in a delay at the end of the cycle. You could then define that one led will cycle 3 times at 50ms then delay 100ms before starting the cycle again. The second LED would not need this as it only goes off once. The change is relatively easy to do and I can help with that if I have described it correctly.
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

marco_c

OK, so I modified MultiBlink to add the concept of looping in patterns. I think this does what you want from a flashing lights perspective, and I have a more flexible program to boot!

Let me know how you go with this.

Multi_Blink2.h
Code: [Select]
// Multi_Blink2.h
//
// Blink lots of LEDs at diffreent frequencies simultaneously
//
// Header file is required to be able to define the structured types
//
#include <Arduino.h>

#ifndef  MULTIBLINKH
#define  MULTIBLINKH

// State values for FSM
#define  MB_NULL  0
#define  MB_LOW   1
#define  MB_HIGH  2
#define  MB_LOOP  3

#define  LOOP_UNDEF  255

typedef struct
{
  uint8_t  activeVal;     // state value for this state to be active (MB_* defines)
  uint16_t activeTime;    // time to stay active in this state stay in milliseconds or loop counter
  uint8_t  nextState;     // If MB_LOOP this is the state to loop back/forward to
} stateDef;

typedef struct
{
  uint8_t  ledPin;         // Arduino I/O pin number
  uint8_t  currentState;   // current active state
  uint8_t  currentLoop;    // current position in the cycle
  stateDef state[4];       // the MB_* state definitions. Add more states if required
  uint32_t nextWakeup;     // the 'time' for the next wakeup - saves the millis() value
} ledTable;

#endif


Multi_Blink2.ino
Code: [Select]
// Multi_Blink2
//
// Blink lots of LEDs at different frequencies simultaneously, include delays and loops in patterns
//
// Marco Colli - September 2012
//
// Demonstrates the way to carry out multiple time based tasks without using the delay() function
// Demonstrates the use of structures (and structures within structures)
// Demonstrates a data driven approach to programming to create compact, reusable code
//

#include "Multi_Blink2.h"  // type definitions

// Blink Table T - Modify this table to suit whatever the output requirements are
// Add or delete lines as required to achieve the desired effects.
// To add additional states the structure in the header file needs to be modified
//
ledTable  T[] =
//Pin  St Lopp  State 0          State 1            State 2          State 3         Wkup
{
  { 3, 0, 0, {{MB_HIGH, 50, 0}, {MB_LOW, 100, 0}, {MB_LOOP, 4, 0}, {MB_LOW, 800, 0}}, 0 },
  { 4, 0, 0, {{MB_LOW, 100, 0}, {MB_HIGH, 50, 0}, {MB_LOOP, 4, 0}, {MB_LOW, 800, 0}}, 0 },
  { 5, 0, 0, {{MB_LOW, 800, 0}, {MB_HIGH, 50, 0}, {MB_LOW, 100, 0}, {MB_LOOP, 4, 1}}, 0 },
  { 6, 0, 0, {{MB_LOW, 800, 0}, {MB_LOW, 100, 0}, {MB_HIGH, 50, 0}, {MB_LOOP, 4, 1}}, 0 },
};

// Self adjusting constants for loop indexes
#define  MAX_STATE  (sizeof(T[0].state)/sizeof(stateDef))
#define  MAX_LED    (sizeof(T)/sizeof(ledTable))

void setup()
{
  for (int i=0; i < MAX_LED; i++)
  {
    pinMode(T[i].ledPin, OUTPUT);
   
    T[i].nextWakeup = 0;
    digitalWrite(T[i].ledPin, LOW);
    T[i].currentLoop = LOOP_UNDEF;
  }
}

void loop()
{
  for (int i=0; i < MAX_LED; i++)
  {
    // check if the state active time has expired (ie, it is less than current time)
    if (millis() >= T[i].nextWakeup)
    {
      T[i].nextWakeup = millis() + T[i].state[T[i].currentState].activeTime;

      switch (T[i].state[T[i].currentState].activeVal)
      {
        case MB_LOW:
        case MB_HIGH:    // Write digital value
          digitalWrite(T[i].ledPin, T[i].state[T[i].currentState].activeVal == MB_HIGH ? HIGH : LOW);
          T[i].currentState = (++T[i].currentState) % MAX_STATE;
          break;
         
        case MB_LOOP:  // loop back to specified state if there is still count left
          // first time in this state set the loop counter
          if (T[i].currentLoop == LOOP_UNDEF)
          {
            T[i].currentLoop = T[i].state[T[i].currentState].activeTime;
          }

          // loop around or keep going?         
          if (T[i].currentLoop-- > 0)
          {
            T[i].currentState = T[i].state[T[i].currentState].nextState;
            T[i].nextWakeup = 0;  // do it immediately
          }
          else
          {
            T[i].currentLoop = LOOP_UNDEF; // set up loop counter
            T[i].currentState = (++T[i].currentState) % MAX_STATE;
          }
          break; 
         
        default:  // just move on - handles NULL and any stupid states we may get into
          T[i].currentState = (++T[i].currentState) % MAX_STATE;
          break;
      }
    }
  }
}
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

faeve

#17
Sep 04, 2012, 12:52 am Last Edit: Sep 04, 2012, 12:59 am by faeve Reason: 1
Hi Marco,

thanks for sharing your code.
I have tried your first version of your Multiblink, I have created a doc.h called Multi_Blink.h and saved it in the same folder as Multi_Blink.ino, I have also created a folder and placed it in the Arduino Library folder.
It was giving me this type of error 'leadTable does not name a type'.
Then I have created a Multi_Blink2.h file, placed it in the same folder, closed everything, and it now works like a charm.
Many thanks for sharing!

Best

F

PGT

ok just wrote something simple.. you can ad more if lines if you have more leds, code is real short i guess it should work, not tested it.
Code: [Select]

setup{
state1=false;
state2=false;
int pin1=1;
int pin2=2;
int x =0;
PinMode(pin1,OUTPUT);
PinMode(pin2,OUTPUT);
}

// a short method using modulo function >> % <<

void loop(){
x++
if(x%3==0)   {state1=!state1;digitalWrite(pin2,state2);}
if(x%13==0) {state2=!state2;digitalWrite(pin2,state2);}

delay(.....)
}

AWOL

If you like ( I do), you can use the IDE's auto format feature to help make your code more legible before you post it.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

And that big key at the bottom of the keyboard? You know which one. Use it more often. Ditto for that big one on the middle row of characters, on the right.

AWOL

#21
Sep 04, 2012, 11:42 am Last Edit: Sep 04, 2012, 12:19 pm by AWOL Reason: 1
And scope.
You need to pay more attention to scope.

Quote
code is real short i guess it should work, not

sp. "Code is real short I guess it should work. Not!"
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Nick Gammon

http://www.gammon.com.au/blink
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Code: [Select]

void loop(){
x++
if(x%3==0)   {state1=!state1;digitalWrite(pin2,state2);}
if(x%13==0) {state2=!state2;digitalWrite(pin2,state2);}


That doesn't even compile, right?

Read this before posting a programming question
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Antennas

I have tried that code Marco_C and I like it. I don't really get most of it yet... But in these lines here
ledTable  T[] =
//Pin  St Lopp  State 0          State 1            State 2          State 3         Wkup
{
  { 3, 0, 0, {{MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 0}, {MB_LOW, 300, 0}}, 0 },
  { 4, 0, 0, {{MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 0}, {MB_LOW, 300, 0}}, 0 },
  { 5, 0, 0, {{MB_LOW, 250, 0}, {MB_HIGH, 250, 0}, {MB_LOW, 250, 0}, {MB_LOOP, 4, 1}}, 0 },
  { 6, 0, 0, {{MB_LOW, 250, 0}, {MB_LOW, 250, 0}, {MB_HIGH, 250, 0}, {MB_LOOP, 4, 1}}, 0 },
  {7, 0, 0,  {{MB_LOW, 0, 0}, {MB_LOW, 500, 0}, {MB_HIGH, 500, 0}, {MB_LOOP, 4, 1}}, 0 },
};

I have fiddled with them somewhat. But I want the LED on pin 3 to do it's thing and it does..I have it flashing 3 times quickly and then wait, but I want it's mate on pin 4 to wait while it flashes then flash 3 times and then back to pin 3. They are a pair one flashes 3 times quickly then the other, on and off like that, but I can't get it work. They just flash together at the same time. How could I change it?

Also why is the loop in a different spot in two of the lines? (MB_LOOP)? I guess you can move it around to fit your LED state changes??

Thanks for the help ...

Andrew

Nick Gammon

Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

marco_c

#26
Dec 01, 2012, 01:54 am Last Edit: Dec 01, 2012, 01:59 am by marco_c Reason: 1
Here is the explanation:
* MB_HIGH and MB_LOW are pretty obvious. They keep the LED on or off for the specified time.
* MB_LOOP makes the pattern loop back to the nominated array element in the pattern for the specificed number of times.

So the data
Code: [Select]
 { 3, 0, 0, {{MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 0}, {MB_LOW, 300, 0}}, 0 },

does this:
0 LED on for 25 ms
1 LED off for 25 ms
2 Loop back to element 0 and repeat it 2 more time (3 total)
3 LED off for 300 ms - this is just a delay while the 'other' LED does its thing

So if we want to have a paired LED that works in tandem with this one we need to have the logic
0 LED off for 300 ms - this is just a delay while the 'other' LED does its thing
1 LED on for 25 ms
2 LED off for 25 ms
3 Loop back to element 1 and repeat it 2 more time (3 total)

which provides to table entry
Code: [Select]
 { 4, 0, 0, {{MB_LOW, 300, 0}, {MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 1}}, 0 },


So if we look at them as a pair:
Code: [Select]

 { 3, 0, 0, {{MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 0}, {MB_LOW, 300, 0}}, 0 },
 { 4, 0, 0, {{MB_LOW, 300, 0}, {MB_HIGH, 25, 0}, {MB_LOW, 25, 0}, {MB_LOOP, 3, 1}}, 0 },


You can see that the second MB_LOOP (pin 4) is in a different spot in the sequence and it loops back to a different place in the array. That is because we need to add the initial delay to the second LED while the sequence for pin 3 is executing.

Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Antennas

Thanks Marco. It is making more sense now. I will play around with it and see what I can get going. I learn a tidbit from each piece of code others write, so thank you.

I am sure I will have other questions and I'll post them soon!!  :) 

Thank you to everyone for their input so far.  I'll try and remember the "code" thingy to make it easier for you to read.

Andrew

Antennas

#28
Dec 02, 2012, 09:17 pm Last Edit: Dec 02, 2012, 09:39 pm by Antennas Reason: 1
I am digging around in that code Marco, thanks. Now can I just load that into an ATTiny85? I think it will fit?
Does most code work with the different chips?

I tried to just upload the code and it took it. But...the LED's stay on after they blink instead of stay off. I tried playing with some numbers in the table but no luck. Any ideas? (I say that but I am sure you already know...LOL)

Sorry for the noob questions, but I find you folks are very helpful!!

Andrew

dhenry

Fairly easy: send a set of patterns to the leds and that pattern determines how fast they blink.

For example, if '1' means on and '0' means off,

0b11 -> both leds are on
0b01 -> bit 0 is still on, but bit 1 is blinking
0b10 -> bit 0 is blinking and bit 1 is blinking
0b00 -> bit 1 is blinking and bit 0 isn't.

A sequence like that will blink one led at 1/2 of the speed of the other led.

You can expand this approach to cover multiple leds at multiple speed.

Go Up