New member with question about multiple loops

Please forgive me if this has been covered before, but I searched to forum and was unable to locate it.

I am new to the Arduino concept, but have done some other programming.

I am currently trying to write a program that will control a few LEDs for a ghostbuster pack.

Let me begin by showing a simple version of what I have:

//internal integers (these are are my internal counter, etc) int safety = 0; ....

//Pin configuration int sw1 = 0; ....

void setup() { pinMode (sw1, INPUT); .... }

So far all that compiles ok. Here is where I get into trouble

I have about 4 or 5 looping sub routines that I want to call. each routine is on its own time base.

What I am used to is to call a single function (i.e startup) and in startup you call each routine. Each routine has it's own loop command to keep it running.

I know it is probably very simple, and I have been trying to go through all the tutorials and forum, but cannot find the answer I am looking for.

Thank you in advance for your help.

Not sure I understand the problem. If your startup function does not return then you can call it at the end of setup or in loop. If you are familiar with C programs, think of a hidden main doing something like:

main() { setup(); while(1) loop(); }

I am sorry if I was unclear. Let me try this.

Here is a programming style I use:

Startup () { saferty() pack() wand() cyclotron() }

Startup is run during boot up, one time. Now each function (safety, etc) has a loop. so Safety would look like this:

Safety() { loop() { delay(500); LED == HIGH; delay(500); LED == LOW; } }

Arduino does not support separate threads of execution. Generally a state machine or some kind of round robin service polling would be used. If your routines are primarily interested in responding to external events then you may be able to use interrupts to do what you want. Perhaps you could say a little more about what you want to make.

I’d be happy to.

In fact, I have done a little more reading, and a little more writing, and let me post what I have. Hopefully this should help explain what I am wanting to do.

(I apologize for the length)

/*

  • GB packs controller Board
  • For Back Pack and Wand Lights

*/

// internal intergers
int cyclocount = 0;
int safety = 0;
int wandbg = 0;
int packbg = 0;
int fire = 0;

// Pin configuration
int sw1 = 0; // Switch 1 Top Right
int sw2 = 1; // Switch 2 Bottom Right
int sw3 = 2; // Switch 3 Bottom Left
int sw4 = 3; // Switch 4 Top Left
int sw5 = 4; // Switch 5 Wand End
int wand1 = 5; // LED 1 inside barell
int wand2 = 6; // LED 2 inside barell
int flash = 7; // Safety Flashing LED
int bargraph1 = 8; // Wand Power Bar Graph
int bargraph2 = 9; // Pack Power Bar Graph
int cyc_LED_1 = 10; // Cyclotron LED 1
int cyc_LED_2 = 11; // Cyclotron LED 2
int cyc_LED_3 = 12; // Cyclotron LED 3
int cyc_LED_4 = 13; // Cyclotron LED 4

void setup() // run once, when the sketch starts
{
pinMode (sw1, INPUT); // Switch 1 Top Right
pinMode (sw2, INPUT); // Switch 2 Bottom Right
pinMode (sw3, INPUT); // Switch 3 Bottom Left
pinMode (sw4, INPUT); // Switch 4 Top Left
pinMode (sw5, INPUT); // Switch 5 Wand End
pinMode (wand1, OUTPUT); // LED 1 inside barell
pinMode (wand2, OUTPUT); // LED 2 inside barell
pinMode (flash, OUTPUT); // Safety Flashing LED
; // Wand Power Bar Graph (pin mode not needed. Holding place marker)
; // Pack Power Bar Graph (pin mode not needed. Holding place marker)
pinMode (cyc_LED_1, OUTPUT); // Cyclotron LED 1
pinMode (cyc_LED_2, OUTPUT); // Cyclotron LED 2
pinMode (cyc_LED_3, OUTPUT); // Cyclotron LED 3
pinMode (cyc_LED_4, OUTPUT); // Cyclotron LED 4
}

// Safety Flash ()
void Flash()
{
loop();
{
safety = digitalRead(sw3); // read input value
if (sw3 == HIGH)
{
digitalWrite(flash, HIGH); // sets the LED on
}
else
{
digitalWrite(flash, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(flash, LOW); // sets the LED off
delay(1000); // waits for a second
}
}
}

// wandgraph ()
void wandgraph()
{
loop();
{
fire = digitalRead(sw4); // read input value
if (sw4 == HIGH)
{
wandbg == 255;
for(wandbg = 255; wandbg >=0; wandbg-=5) // fade out (from max to min)
{
analogWrite(bargraph1, wandbg); // sets the value (range from 0 to 255)
delay(500); // waits for 30 milli seconds to see the dimming effect
}
}
else
{
for(wandbg = 0 ; wandbg <= 255; wandbg+=5) // fade in (from min to max)
{
analogWrite(bargraph1, wandbg); // sets the value (range from 0 to 255)
delay(30); // waits for 30 milli seconds to see the dimming effect
}
for(wandbg = 255; wandbg >=0; wandbg-=5) // fade out (from max to min)
{
analogWrite(bargraph1, wandbg);
delay(30);
}
}
}
}

// packgraph ()
void packgraph()
{
loop();
{
for(packbg = 0 ; packbg <= 255; packbg+=5) // fade in (from min to max)
{
analogWrite(bargraph2, packbg); // sets the value (range from 0 to 255)
delay(65); // waits for 30 milli seconds to see the dimming effect
}
for(packbg = 255; packbg >=0; packbg-=5) // fade out (from max to min)
{
analogWrite(bargraph2, packbg);
delay(65);
}
}
}

by the way, forgot to mention, bar graph 1 & 2 will be a dimmer output run to a VU chip (like a LM3916) to create a bar graph.

I will also be adding in a few more routines, adding another function for 4 LEDs chasing each other, and then an addition to routine “wandgraph” to control 2 LEDs for a “firing sequence” since all that is affected by the state of sw4.

Hi Vader, what is a GB packs controller Board and Wand Light?

And it would help me if you could provide a brief description of what the does and what you wanted it to do

GB = Ghostbuster

The pack is the backpack worn in the movie. I am working with a friend to make a replica of the movie pack.

I will explain the end result from the "Pin Configuration" sw1 = not in use at this time

sw2 = not in use at this time

sw3 = when signal = 0, flash will blink. When =1 flash will be solid

sw4 = when signal = 0, wand1 & wand 2 will be off and bargraph1 will have a simple up/dn output. When =1, wand1 & wand2 will flash back and forth at a med/high rate and bargraph1 will start at max and slowly creep down. When bargraph1 has ended, wand1 & 2 will end, and bargraph1 will return to normal.

sw5 = when signal = 0, wand1 & wand2 will be off. When = 1, wand1 & 2 will flash back and forth at a high rate (faster than off sw4).

wand1 & wand2 = LED outputs controlled by sw4 and sw5

flash = LED output controlled by sw3

bargraph1 & bargraph2 = each one is a "dimmer" code controlling an LM3914. #2 is constant and never deviates from it's program. #1 is affected by sw4

cyc_led_{1-4} = each one is an LED that will chase each other, with only one on at the time. This one, like bargraph2, will run it's routine at all times, never being affected.

Now, here is the kickers, each cycle (bargraph1, 2, cyc_LED, etc) has their own time base. each one changes at their own rates.

Does this help and make sense?

Just as a disclaimer. I am new to the arduino too. Furthermore, I am also new to programming in general and to electronics. No formal education in any of these.

Still here? Great!

To run multiple activities concurrently you will have to index them to the a timer. Look up millis() in the arduino reference and also check out the "Knight Rider" example for clues. You might also have some luck searching the term timeStamp.

The idea is that you store the current millis() as the "startTime" (or some such) at the start of your time driven task.

startTime = millis();

You know you want your task to run for a certain amount of milliseconds. We'll use "cycle" to represent this value. Then periodically you check the millis() to see if the cycle time of your task has elapsed by using something like

if (millis() >= startTime + cycle) {
// Whatever you want to happen when the cycle ends

I'm sure that isn't exactly clear but I did put a disclaimer at the top. Good luck!

Sam, thank you. I found that bit of code, but I am trying not to "link" each function together with a common clock. There will be times when the timing has to change on certain events.

For this, I prefer the simple "delay" command. I know it is not exact, but in each loop, a couple milsecs here and there will not affect me.

The functions are not linked to the clock they just use it as a reference point. If you use delay, nothing else gets executed while the chip is waiting out the delay time. Also, you will have to have the "long" variable type when setting your time stamped variables. Remember, delay will just sit and do absolutely nothing for the duration of the delay and then it will move on to the next line of code after the delay has elapsed. If you time stamp your activities you can start them and then move on to other things while say an LED is lit, then check back periodically to see if the first activity should be halted.

Hope that helps.

Sam

Ah, ok. I will have to look into that. That methodology is different from what I am used to. Each function ran on it's own, and so a delay in one function had no effect on another function.

So if I may ask, using the millis () command, how would that affect the function surrounding sw4? (the switch that changes bargraph1 and wand1 & 2)

Sorry Vader, it looks like I'm out of my depth at this point. Like I said, I'm new too.

When I look at your code I see that the first line of your functions call the function "loop();". To me that looks like it would just drop you back into the main loop of the program and any code that came after that function call will never get executed... I may be COMPLETELY wrong about that. (If so, will someone please say so.) Sorry that I don't have more specific advice regarding that.

However, I do have some general advice that you have probably already heard but it doesn't hurt to repeat.

Start small. Break your code down into small activities, like one time stamp controlled event. Once you understand exactly what works then you can move on and apply that knowledge to the next piece of the puzzle. It gives you little accomplishments to keep you interested and feeling like you are getting somewhere. I know that if I try to code the whole picture at once, I loose focus and it gets really hard to figure out where things went awry. Also, it is a good idea to make a flow chart of sorts to map out the logic and sequence of events. This will help you find the small tasks to focus on. Again, this is what I have done with my grand total of one project! But its working and I think that is the test that matters.

Lastly, you are basically using C++ to write your program. So, if you haven't already found it, this is an excellent reference: http://www.cplusplus.com/doc/tutorial/. Just ignore the cout stuff.

Best of luck, Sam

If you really want to have what is effectively a separate thread for each function, why not use a separate ATmega168 for each function? Just glancing at your code it looks like there isn't really any communication between the threads, so it should be very easy to implement it that way.

No apologies needed. You actually pointed me in the right direction.

I see what you were saying about the delay command, and I went back and implemented the millis in the flash portion. I am not going back and using the increment and decrement commands on my bargraph portions. I figured out how to use the millis and those 2 to make it work.

So all in all, i am using a common timer, but each function is based on it's own count.

I see what I need to do, and I am writing each portion in it's own section, testing it and moving on. When I get each section working, I will put them all together in the main routine and run just the one loop and the few millisecons will not affect me.