0

I want to fade a red LED up and down, then a green LED up and down, and repeat the whole cycle indefinitely.

I've been trying to run multiple functions one after another. However my current code seems to have them both fading in parallel.

I tried using a switch case, do while and the while loop but the code runs the two functions at once. So what is wrong with the code below?

This is my code:

void setup() {
    Serial.begin(9600);
    DDRD |= (1<<DDD6)|(1<<DDD5);
    TCCR0A = 0xF1;
}

uint8_t fade_seq;

void loop() {
    loop1:
    fade_seq++;
    while (fade_seq==1)
    {
        fade_red(1);
    }
    Serial.println(fade_seq);
    while (fade_seq==2)
    {
        fade_green(1);
    }
    if (fade_seq==3)
    {
        fade_seq=0;
        goto loop1;
    }
}

void fade_red(uint8_t cnt)
{
    uint8_t i,k;
    for (k=0;k<cnt;k++)
    {
        OCR0A+=1;
        _delay_ms(10);
        if (OCR0A == 255)
        {
            for (i=0;i<255;i++)
            {
                OCR0A--;
                _delay_ms(10);
            }  
        }
    }
}

void fade_green(uint8_t cnt)
{
    uint8_t i,k,c;
    for (c=0;c<cnt;c++)
    {
        for (k=0;k<255;k++)
        {
            OCR0B+=1;
            _delay_ms(10);
            if (OCR0B == 255)
            {
                for (i=0;i<255;i++)
                {
                    OCR0B--;
                    _delay_ms(10);
                }  
            }
        }
    }
}
  • Write the function calls one after the other, each terminated with a semicolon, like: first_function(); second_function(); – Edgar Bonet Nov 4 '16 at 18:03
  • This was my first attempt which also gives the same result, they run at the same time. Which I don't want, I want to run one after the other. – R1S8K Nov 4 '16 at 18:09
  • 2
    they run at the same time”. No, they don't. They run one after the other. You are misinterpreting the symptoms you see: the Arduino runs a single thread of execution, with no provisions for parallelism. – Edgar Bonet Nov 4 '16 at 20:40
  • 2
    Your very complicated loop function looks to me the same as: while (true) fade_red(1); – Nick Gammon Nov 4 '16 at 22:41
  • @Edgar Bonet Yes, I know it's not intel multithreaded processor. I know it does 1 fetch and 1 execute every cycle. Of course there's no parallelism in processing. The Atmega 328p actually runs them simultaneously which updates each function so fast. It doesn't run one function and waits for it to finish. – R1S8K Nov 5 '16 at 6:35
5

I did not quite understand what you are actually trying to accomplish. Neither you question nor your code is very clear in this respect. And your code is probably buggy anyway, since it does not do what you expect.

Then, I am just guessing: you may just want to fade a red LED up and down, then a green LED up and down, and repeat the whole cycle indefinitely. I am guessing right?

First of all, I would recommend you stick with the functions provided by the Arduino core library, as they will make your life easier. The kind of low level AVR programming you are attempting here is for advanced users. You should learn the basics first before moving to that realm.

Here is how I would write that using the plain analogRead() function:

const uint8_t RED   = 6;  // pin connected to the red LED
const uint8_t GREEN = 5;  // pin connected to the green LED

void setup()
{
    Serial.begin(9600);
    pinMode(RED, OUTPUT);
    pinMode(GREEN, OUTPUT);
}

// Fade an analog pin up and down.
void fade(uint8_t pin)
{
    for (int i = 1; i <= 255; i++) {
        analogWrite(pin, i);
        delay(10);
    }
    for (int i = 254; i >= 0; i--) {
        analogWrite(pin, i);
        delay(10);
    }
}

void loop()
{
    Serial.println(F("Fading RED."));
    fade(RED);
    Serial.println(F("Fading GREEN."));
    fade(GREEN);
}

Each LED fading up and down takes roughly 5 seconds: 2 ramps × 255 steps/ramp × 10 ms/step.

  • Thank you for your suggestion. And yes your guessing is right I want to perform each one at a time. And I don't want to code with Arduino coding style, that's why I switched to true C coding. And thanks for the provided code I think I learned something here, you wrote one function for fading! Interesting :) – R1S8K Nov 5 '16 at 6:45
  • OK, I tested your code and it actually does very similar to my previous code, it also mixes the colors in more beautiful way :) – R1S8K Nov 5 '16 at 12:02
  • @PerchEagle the "Arduino coding style" is true C/C++ code. The Arduino platform developers have just used function wrappers to make everything easier to read. See en.wikipedia.org/wiki/Wrapper_function – sa_leinad Nov 9 '16 at 15:04
4

It simply is not possible for the processor to run both functions at once. What probably is happening is that the sequence of functions executes too fast to distinguish it as two sequential processes. You'll need to do something like call them with a delay in between. It could be as simple as:

void loop() {
   fade_red();
   delay(500);

   fade_green();
   delay(500);
}

The while loops surrounding your calls do nothing at all. The effect of each one is to call its respective function once. Your code is pretty much equivalent to a switch/case statement using fade_seq as the selector, but without any control over the timing of your calls, the functions will happen in rapid sequence.

  • Yes as I mentioned I tried switch case, do while, if and while loops. All the same result. The code you provided would also be the same, because the MCU starts the first function and not wait for it to finish and go to the second function and starts it as well. So the fading does altogether which is another methodology I would prefer as mixing the colors, but now I want to run each function as a complete fade then starts the second function. I want to learn this skill in C. – R1S8K Nov 4 '16 at 20:16
  • because the MCU starts the first function and not wait for it to finish - well it does wait for it to finish so your observations are flawed. What you think is happening just isn't. – Nick Gammon Nov 4 '16 at 22:42
4

Why my loops are very complicated?

OK, here is your loop:

uint8_t fade_seq;   // <--- initially zero

void loop() {
loop1:
fade_seq++;
while (fade_seq==1)
{
  fade_red(1);
}
Serial.println(fade_seq);
while (fade_seq==2)
{
  fade_green(1);
}
if (fade_seq==3)
{
  fade_seq=0;
  goto loop1;
}
}

So you add 1 to fade_seq and then:

while (fade_seq==1)
{
  fade_red(1);
}

So fade_seq is always 1 so that loops indefinitely. Therefore you can forget about everything else after it.

So you may as well write:

void loop() {
   while (true)
    {
    fade_red(1);
    }
 }

And since loop, well, loops, that simplifies to:

void loop() {
    fade_red(1);
   }
  • Yes, you are correct! OK I have to look for another solution. I looked into pointers, can I connect a pointer to a SFR; like, OCRnA or OCRnB? I tried but didn't work. – R1S8K Nov 5 '16 at 12:36
  • Yes you can, but I'm curious to know why you want to. – Nick Gammon Nov 5 '16 at 20:41
  • Because I want to merge two functions which are the red and green fade functions which control SFRs. So I want to design one function which has a pointer to deal with 2 SFRs so as I choose a specific color there are assignments for each OCR. – R1S8K Nov 7 '16 at 11:51
2

try this-and add to it calling a function in between-as discussed in comments that gives a visible delay-note I increased the delays as its probably going too fast

uint8_t fade_seq=1;
 void setup() {
DDRD |= (1<<DDD6)|(1<<DDD5);
TCCR0A = 0xF1;
}

void loop() {
fade_seq++;
if (fade_seq==1)
{
  fade_red(1);

}

if (fade_seq==2)
{
  fade_green(1);

}
if (fade_seq==3)
{
fade_seq=0;
}
}



void fade_red(uint8_t cnt)
{
  uint8_t i,k;
  for (k=0;k<cnt;k++)
  {
    OCR0A+=1;
    _delay_ms(100);
    if (OCR0A == 255)
    {
      for (i=0;i<255;i++)
      {
        OCR0A--;
        _delay_ms(100);
      }  
    }
  }
}

void fade_green(uint8_t cnt)
{
  uint8_t i,k;
  for (k=0;k<cnt;k++)
  {
    OCR0B+=1;
    _delay_ms(1-0);
    if (OCR0B == 255)
    {
      for (i=0;i<255;i++)
      {
        OCR0B--;
        _delay_ms(100);
      }  
    }
  }
}
  • Thank you very much for the help but they still somehow run together! It's little improved from my code. – R1S8K Nov 4 '16 at 18:18
  • try adding in a function that nofade or turn off to make it more readable – Dat Han Bag Nov 4 '16 at 18:25
  • so at least you will know it turns off -you should be able to fix it from there – Dat Han Bag Nov 4 '16 at 18:26
  • OK, I think I have to add a different function in between the two functions! Sounds a good idea :) But also I think it would be the same, that the microcontroller would run them all in parallel where I want to achieve the sequential methodology. – R1S8K Nov 4 '16 at 18:50
  • using the inbetweeen idea is correct -it wwill work if you code it correctly – Dat Han Bag Nov 4 '16 at 18:58
0

OK I did it :)

void setup() {
DDRD |= (1<<DDD6)|(1<<DDD5);
TCCR0A = 0xF1;
}

void loop() {
  fade_red(255);
  fade_green(255); 
}


void fade_red(uint8_t cnt)
{
  uint8_t i,k;
  for (k=0;k<cnt;k++)
  {
    OCR0A++;
    _delay_ms(10);
    if (OCR0A == 255)
    {
      for (i=0;i<255;i++)
      {
        OCR0A--;
        _delay_ms(10);
      }  
    }
  }
}
void fade_green(uint8_t cnt)
{
  uint8_t i,k;
  for (k=0;k<cnt;k++)
  {
    OCR0B++;
    _delay_ms(10);
    if (OCR0B == 255)
    {
      for (i=0;i<255;i++)
      {
        OCR0B--;
        _delay_ms(10);
      }  
    }
  }
}
  • I don't understand why you are altering an internal timer's "compare" value like that. I'm not sure that will even have any effect, as the timer will be in PWM mode, counting up to 255 anyway. – Nick Gammon Nov 5 '16 at 20:43
  • What you mean exactly? Because I must count the OCR because they are the SFRs which produce the PWM effect. – R1S8K Nov 7 '16 at 11:50
  • SFR = Special Function Register, I gather. I see. Wouldn't just doing analogWrite be a lot easier to read? Comparing if (OCR0A == 255) like that has a chance you will miss that exact number and have to wait for another cycle. – Nick Gammon Nov 7 '16 at 20:44
  • I don't want to program with Arduino coding style, I want to work with true C. The comparison works OK, there's no miss in my configuration until now. – R1S8K Nov 8 '16 at 3:48
  • I see. Well I was wrong about the comparison. OCR0A won't change unless you change it. – Nick Gammon Nov 8 '16 at 4:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.