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);
}
}
}
}
}
5 Answers 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– R1S8K2016年11月05日 06:45:22 +00:00Commented Nov 5, 2016 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– R1S8K2016年11月05日 12:02:00 +00:00Commented Nov 5, 2016 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_functionsa_leinad– sa_leinad2016年11月09日 15:04:52 +00:00Commented Nov 9, 2016 at 15:04
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– R1S8K2016年11月04日 20:16:28 +00:00Commented Nov 4, 2016 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.2016年11月04日 22:42:41 +00:00Commented Nov 4, 2016 at 22:42
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– R1S8K2016年11月05日 12:36:52 +00:00Commented Nov 5, 2016 at 12:36
-
Yes you can, but I'm curious to know why you want to.2016年11月05日 20:41:59 +00:00Commented Nov 5, 2016 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– R1S8K2016年11月07日 11:51:51 +00:00Commented Nov 7, 2016 at 11:51
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– R1S8K2016年11月04日 18:18:20 +00:00Commented Nov 4, 2016 at 18:18
-
try adding in a function that nofade or turn off to make it more readableDat Han Bag– Dat Han Bag2016年11月04日 18:25:18 +00:00Commented Nov 4, 2016 at 18:25
-
so at least you will know it turns off -you should be able to fix it from thereDat Han Bag– Dat Han Bag2016年11月04日 18:26:07 +00:00Commented Nov 4, 2016 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– R1S8K2016年11月04日 18:50:58 +00:00Commented Nov 4, 2016 at 18:50
-
using the inbetweeen idea is correct -it wwill work if you code it correctlyDat Han Bag– Dat Han Bag2016年11月04日 18:58:07 +00:00Commented Nov 4, 2016 at 18:58
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.2016年11月05日 20:43:08 +00:00Commented Nov 5, 2016 at 20:43
-
What you mean exactly? Because I must count the OCR because they are the SFRs which produce the PWM effect.R1S8K– R1S8K2016年11月07日 11:50:14 +00:00Commented Nov 7, 2016 at 11:50
-
SFR = Special Function Register, I gather. I see. Wouldn't just doing
analogWrite
be a lot easier to read? Comparingif (OCR0A == 255)
like that has a chance you will miss that exact number and have to wait for another cycle.2016年11月07日 20:44:31 +00:00Commented Nov 7, 2016 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– R1S8K2016年11月08日 03:48:19 +00:00Commented Nov 8, 2016 at 3:48
-
I see. Well I was wrong about the comparison.
OCR0A
won't change unless you change it.2016年11月08日 04:33:42 +00:00Commented Nov 8, 2016 at 4:33
first_function(); second_function();
loop
function looks to me the same as:while (true) fade_red(1);