Hello there!
Sorry for my english - not my native.
I'm trying to avoid 'delay()' in RGB led fading code. Fading code is from Digispark RGB LED fader :
Rewrote it using 'millis' like 'BlinkWithoutDelay'. Code run as charm and fading is smooth until there is 'Serial print' stuff at the end. If 'Serial print' is commented out fading is not smooth, it more like jumping from color to color.
Cannot figure out where is problem and how to solve it! :~
Currently running this on Atmega2560 but planning to migrate it to Attiny85.
Please some help for absolute beginner.
There is code:
int LED1;
int LED2;
int LED3;
int p0=5; // atmega pins led attached to
int p1=6;
int p4=7;
float x;
float r;
float g;
float b;
long previousMillis = 0;
long fadeRGBinterval = 10;
void setup() {
Serial.begin(9600); //start serial interface
// initialize the digital pin as an output.
pinMode(p0, OUTPUT); //sets up pin 0 for pwm
pinMode(p1, OUTPUT); //sets up pin 1 for pwm
pinMode(p4, OUTPUT); //sets up pin 4 for pwm
}
void loop() {
for (int i=0; i<360; i++)
{
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > fadeRGBinterval) {
previousMillis = currentMillis;
//convert into a float to calculate r,g,b ( increase amplitute by multiplying by 127 and make positive by adding 1)
x=float(i);
r=127*(sin(x/180*PI)+1);
g=127*(sin(x/180*PI+3/2*PI)+1);
b=127*(sin(x/180*PI+0.5*PI)+1);
//convert flaot r,g,b to integer and assisting values to LED
LED1= int(r);
LED2= int(g);
LED3= int(b);
//write LED levels to p0, p1, p4 (ASSIGN PWM values to LEDs)
analogWrite (p0,LED1);
analogWrite (p1,LED2);
analogWrite (p4,LED3);
Serial.print("LED1 ");
Serial.print (LED1);
Serial.print(" LED2 ");
Serial.print(LED2);
Serial.print(" LED3 ");
Serial.println(LED3);
}
}
}
You need to ditch the for loop. The time needed to print all that stuff causes the for loop to take long enough. You might have read and understood the blinck without delay example, but you did not embrace it.
You need, on each pass through loop (not on each pass through the for loop), to determine if it is time to change the intensity/color of the LED. If so, you make the change, based on a static or global counter, increment (or decrement) the counter, and reset the last LED change time.
Sending data through serial is SLOW - especially at 9600 baud...
9600 baud is 9600 symbols per second - one character is 8 bits, plus 1 start and 1 stop bit, so 10 bits. That is 960 characters per second.
That's 1/960 seconds per character - or 0.001041667 seconds.
You're printing over 40 characters every time. That's more than 0.04 seconds - 40ms - every time, and you're only allowing 10ms for each fade point.
See the problem now?
Running the serial at a higher baud rate can help - for instance running at 115200 baud would reduce it to between 300 and 400µs depending on the size of the numbers you're printing.
Oh, and what is that for loop supposed to be doing on the outside? It's certainly not doing what you think it is.
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > fadeRGBinterval) {
previousMillis = currentMillis;
for (int i=0; i<360; i++) ...
...remaining part of code......
is it correct now?
But still without Serialprint it do not work as expected. Only on baud 9600 it run smooth.
Running on baud 115200 makes fade too fast. If increase fadeRGBinterval=1000 can see-very quick fade through (more like blink) LED1, LED2 and longer time Led3.