Pages: [1]   Go Down
Author Topic: Quesiton about how to not block processor execution when programming  (Read 353 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi all, I finally found time to pull out an old arduino board I had lying around and decided I'd mess around with it for a while. I have some code experience but none with microelectronics like an arduino. To cut to the chase, I wanted to make a program that would blink two separate LEDs at different rates. In the event that both LEDs were ON, a third LED would also light up. At first I noobishly used the delay() function, but after some simple googling, I found that does not work since an arduino only has one processing thread to work with. If someone could just look at this - I think the problem is in the 'myBlink' function, but again this is my first shot at programming a microcontroller like this, so maybe it is in my main loop. I attached my code at the bottom. 

Code:
int blue = 2;
int white = 3;
int red = 5;

long previousMillis = 0;


void setup(){
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop() {
  unsigned long time = millis();
  myBlink(red, 1000);
  myBlink(blue, 1000);
  if (digitalRead(red)==HIGH && digitalRead(blue)==HIGH){  //this part works quite well
    digitalWrite(white, HIGH);
  }
  else {
    digitalWrite(white, LOW);
  }
 
}

int myBlink(int led, int interval){    //it's this function that I'm struggling with
  unsigned long currentMillis = millis(); // I feel as if this should work
  int ledState = digitalRead(led);
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    Serial.print(previousMillis);
    Serial.print("\n");
    if (ledState == LOW){
      ledState = HIGH;
    }
    else{
      ledState = LOW;
    }
    digitalWrite(led, ledState);
}
}



Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 651
Posts: 50841
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I think the problem is in the 'myBlink' function
I think you haven't told us what the problem is. That code does something. You have not told us what that is. You want that code to do something. You haven't told us exactly what that is.

If you want the two LEDs to be on and off at different intervals, it doesn't help to call the function with the same interval every time.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're right, sorry. Currently, the two LEDs light up, however the pattern in which they light up is strange and somewhat vague. However, when I made the main loop function, I intended for them to light up at the same time. This would cause the third LED to light up as well. The third LED does light up, though again, the two blinking LEDs do not light up in the way that I am trying to make them. Does that define the problem?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 651
Posts: 50841
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Does that define the problem?
Let me ask another question, first.

Quote
The third LED does light up, though again, the two blinking LEDs do not light up in the way that I am trying to make them.
Does that tell us anything about how they DO light up OR how you INTENDED for them to light up? Personally, I don't think so.

Reading the state of OUTPUT pins is really unnecessary. You can keep track of what you have written to them.

Code:
    Serial.print(previousMillis);
    Serial.print("\n");
You've never met the println() method?

Putting every { on a new line, and using Tools + Auto Format would make your code more readable.
Logged

Offline Offline
Full Member
***
Karma: 9
Posts: 226
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think you would need at least a different variable to record previousMillis for red and blue LEDs.
Logged

Please don't PM me asking for help. Ask questions in the forum.

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Does that tell us anything about how they DO light up OR how you INTENDED for them to light up? Personally, I don't think so.

I'll be as specific as I can, so that you -personally- will understand. I'll start with the simplest part: my circuit. All I have is 3 diodes wired in series to 3 different pins on my board. Now on to the code. As I hope you can see from what I posted, the two LEDs are supposed to light up at 1 second intervals. No matter what bugs there may be in my code, what is certain is that something should change each second.

 Well, something DOES change each second. I tried outputting the which LED's were on during each second. I'm currently watching the serial monitor now. There is no pattern. The diodes sometimes blink in 1 second intervals, but never together. Either one goes off and the other comes on, or one stays on while the other comes on.

Quote
You've never met the println() method?

Ah yes that is what I was looking for, thank you - but that's really beside the point.

Quote
Putting every { on a new line, and using Tools + Auto Format would make your code more readable.

Sure, I'm just more used to it the other way. Here's how it looks now:

Code:
int blue = 2;
int white = 3;
int red = 5;

long previousMillis = 0;


void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);
}

void loop()
{
  unsigned long time = millis();
  myBlink(red, 3000);
  myBlink(blue, 3000);
  if (digitalRead(red)==HIGH && digitalRead(blue)==HIGH){  //this part works quite well
    digitalWrite(white, HIGH);
  }
  else
  {
    digitalWrite(white, LOW);
  }

}

int myBlink(int led, int interval)
{    //it's this function that I'm struggling with
  unsigned long currentMillis = millis(); // I feel as if this should work
  int ledState = digitalRead(led);
  if (currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    Serial.print(previousMillis);
    Serial.print("\n");
    if (ledState == LOW)
    {
      ledState = HIGH;
    }
    else
    {
      ledState = LOW;
    }
    digitalWrite(led, ledState);
  }
}
Logged

Global Moderator
Melbourne, Australia
Offline Offline
Brattain Member
*****
Karma: 511
Posts: 19306
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I wanted to make a program that would blink two separate LEDs at different rates.

http://www.gammon.com.au/blink
Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks a lot.

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 651
Posts: 50841
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So, what about bobcousins' comment in reply #4?
Logged

Sydney, Australia
Offline Offline
Edison Member
*
Karma: 33
Posts: 1287
Big things come in large packages
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

It is not beginner's code, but you may want to look at the MultiBlink sketch at the google code site in my signature block. It is designed to run LEDs in patterns and blinking at different rates.
Logged

Arduino libraries http://arduinocode.codeplex.com
Parola hardware & library http://parola.codeplex.com

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You seem to be trying to blink two LEDs independently, but you aren't keeping track of their respective states independently. Hence it will be doing some flashing i.e. turning something on and off at regular intervals, but it will be inconsistent which LED is switched for each on/off operation.

Since you seem to be using the same interval for both LEDs, if this code worked both LEDs would blink exactly together. In that case you might just as well have one set of blink code that turns both LEDs on and off at the same time.

From your description, I suppose what you're actually trying to achieve is have the two LEDs blink independently at different intervals (and then have the third LED show their combined state).

There are loads of different ways to implement this, but one easy way is to write a separate function for each LED. For example:

Code:
// incomplete, untested
void blinkRed()
{
    static unsigned long lastBlink = millis();
    const unsigned long interval = 500;
    const int pin = red;

    if(millis() - lastBlink >= interval)
    {
        lastBlink += interval;
        digitalWrite(pin, !digitalRead(pin));
    }
}

Copy/paste to produce a similar function for the green LED.

Your loop then looks like this:

Code:
void loop()
{
  blinkRed();
  blinkGreen();

  digitalWrite(white, digitalRead(red) && digitalRead(green));
}

If you were going to do this with more than a couple of LEDs I'd take a different approach, using a single function and holding the blink states in arrays, but this is a nice simple version that is easy to understand.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just want to address something that people mentioned: I set the two rates to 1000 just for testing. Setting the rates to anything but 1000 (or just the same, rather) causes the circuit to exhibit behavior that makes no sense and is completely unfixable. I understand that I could make functions to do this just as easily, but that is not my goal.

Quote
I think you would need at least a different variable to record previousMillis for red and blue LEDs.


Ok. This is the problem. Trying to use just one function here is tricky because the new value of previous can't be set until after the if statement is evaluated. PeterH, your suggestions worked perfectly (and were much simpler than my fine mess of code). Thanks for all the help. 
Logged

Pages: [1]   Go Up
Jump to: