FastLed library use the CRGB as attribute - arduino

I'm working on a program for an addressable LED strip. It is working and at this point I'm trying to make my code better. I have 3 LED strips and I made a function which all three has to do. In the function I want to specify which one needs to be updated so I used attributes, but this doesn't seem to work. I can't find this on the FastLed documentation.
//Number of leds powered
int led_state_1 = 0;
int led_state_2 = 0;
int led_state_3 = 0;
// This is an array of leds. One item for each led in your strip.
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB leds3[NUM_LEDS];
void CheckAndUpdateLed(CRGB LedArray, int led_state){
resetLedStrip(LedArray);
for(int whiteLed = 0; whiteLed < led_state; whiteLed = whiteLed + 1) {
// Turn our current led on to white, then show the leds
LedArray[whiteLed] = CRGB::White;
// Show the leds (only one of which is set to white, from above)
FastLED.show();
}
}
When I change LedArray to leds1 it is working. I'm calling the function as CheckAndUpdateLed(leds1, led_state_1);

I think my question was a bit unclear sorry for that. I came up with another way of doing this. Instead of 1 led strip I check them all in the same function.
#define NUM_STRIPS 3
#define NUM_LEDS_PER_STRIP 15
CRGB leds[NUM_STRIPS][NUM_LEDS_PER_STRIP];
int led_states[] = {0, 0, 0};
void CheckAndUpdateLeds(){
//resets the leds to black
resetLedStrips();
// This outer loop will go over each LED strip, one at a time
for(int x = 0; x < NUM_STRIPS; x++) {
// This inner loop will go over each led in the current strip, one at a time till the amount of light is the same as in the led_state
for(int led = 0; led < led_states[x]; led = led + 1) {
// Turn our current led on to white, then show the leds
leds[x][led] = CRGB::White;
FastLED.show();
}
}
}
void resetLedStrips(){
for(int x = 0; x < NUM_STRIPS; x++) {
for(int led = 0; led < NUM_LEDS_PER_STRIP; led = led + 1) {
leds[x][led] = CRGB::Black;
}
}
}

Related

Fading RGB light from yellow to red using reed switch

I am still quite new to arduino coding, so I would very much appreciate your help!
I have recently made a circuit using reed switch and a simple LED light, which makes a light slowly fade out once it is taken away from a magnetic field and light up again once it is close to the magnet.
For my project, I need the LED to produce constant yellow light when it is close to the magnetic field, but as soon as it is taken away, the light has to fade to the red light and fade out in general at the same time.
So simply put:
reed switch "closed" = constant yellow light
reed switch "open" = fading to the red light and fading out at the same time
Bellow is the code that I already have for simple LED and reed switch.
`
int ledPin = 9;
int reedPin = 2;
int brightness = 0;
int fadeAmount = 5;
unsigned long timestamp = 0;
void setup(){
pinMode(ledPin, OUTPUT);
pinMode(reedPin, INPUT_PULLUP);
}
void loop(){
if(millis()-timestamp > 30){
brightness = brightness - fadeAmount;
if(brightness < 0) brightness = 0;
timestamp = millis();
}
if(!digitalRead(reedPin)){
brightness = 255;
}
analogWrite(ledPin, brightness);
}
//different code begins here
int rVal = 254;
int gVal = 1;
int bVal = 127;
int rDir = -1;
int gDir = 1;
int bDir = -1;
const int rPin = 11;
const int gPin = 10;
const int bPin = 9;
void setup() {
pinMode(rPin, OUTPUT);
pinMode(gPin, OUTPUT);
pinMode(bPin, OUTPUT);
}
void loop() {
analogWrite(rPin, rVal);
analogWrite(gPin, gVal);
analogWrite(bPin, bVal);
// change the values of the LEDs
rVal = rVal + rDir;
gVal = gVal + gDir;
bVal = bVal + bDir;
if (rVal >= 255 || rVal <= 0) {
rDir = rDir * -1;
}
if (gVal >= 255 || gVal <= 0) {
gDir = gDir * -1;
}
if (bVal >= 255 || bVal <= 0) {
bDir = bDir * -1;
}
delay(33);
}
}
`
Bottom one is the code that makes RGB led crossfade different colours, but I need it to go from yellow to red. How could I do that? And how can I incorporate the RGB light code into reed switch code?
You achieve yellow with the green and red emitter at the same level.
In order to fade to red you need to decrease the green emitter to 0.
This of course will also decrease the overall brightness.
Once you faded out green you can fade red to 0.
Of course you can also fade out both leds at the same time. Fading the green component faster will also move the colour towards red.
That's personal preference

issue with Arduino using FastLed with IRremote change mode

Hi I am trying to build a arduino project to control led strip and change the light pattern when pressed different button
the code i am using is
#include <IRremote.h> //include the library
#include <FastLED.h>
// How many leds in your strip?
#define NUM_LEDS 70
#define DATA_PIN 3
#define CLOCK_PIN 13
#define Button_0 0xFF9867
#define Button_1 0xFFA25D
#define Button_2 0xFF629D
#define Button_3 0xFFE21D
#define Button_4 0xFF22DD
#define Button_5 0xFF02FD
#define Button_6 0xFFC23D
#define Button_7 0xFFE01F
#define Button_8 0xFFA857
#define Button_9 0xFF906F
int receiver = 7; //initialize pin 13 as recevier pin.
IRrecv irrecv(receiver); //create a new instance of receiver
decode_results results;
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
LEDS.addLeds<WS2812,DATA_PIN,RGB>(leds,NUM_LEDS);
LEDS.setBrightness(84);
irrecv.enableIRIn(); //start the receiver
}
void loop() {
if (irrecv.decode(&results)) { //if we have received an IR signal
Serial.println (results.value, HEX); //display HEX results
irrecv.resume(); //next value
if (results.value == Button_0) {
RunningLightSlow();
}
else if(results.value == Button_1) {
RainbowLights();
}
// switch (results.value) {
//
// case Button_0: RunningLightSlow(); break;
// case Button_1: RainbowLights(); break;
// }
}
}
// LIGHTSHOW 0 starts --------------------------------------------------------------------------------------------------
void fadeall() { for(int i = 0; i < NUM_LEDS; i++) { leds[i].nscale8(250); } }
void RunningLightSlow() {
while(1) {
static uint8_t hue = 0;
Serial.print("x");
// First slide the led in one direction
for(int i = 0; i < NUM_LEDS; i++) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
Serial.print("x");
// Now go in the other direction.
for(int i = (NUM_LEDS)-1; i >= 0; i--) {
// Set the i'th led to red
leds[i] = CHSV(hue++, 255, 255);
// Show the leds
FastLED.show();
// now that we've shown the leds, reset the i'th led to black
// leds[i] = CRGB::Black;
fadeall();
// Wait a little bit before we loop around and do it again
delay(10);
}
}
}
// LIGHTSHOW 0 ends --------------------------------------------------------------------------------------------------------
// LIGHTSHOW 1 STARTS ------------------------------------------------------------------------------------------------------
void RainbowLights() {
randomSeed(millis());
int wait=random(10,30);
int dim=random(4,6);
int max_cycles=8;
int cycles=random(1,max_cycles+1);
while(1) {
rainbowCycle(wait, cycles, dim);
}
}
void rainbowCycle(int wait, int cycles, int dim)
{
Serial.println("Let's make a rainbow.");
//loop several times with same configurations and same delay
for(int cycle=0; cycle < cycles; cycle++)
{
byte dir=random(0,2);
int k=255;
//loop through all colors in the wheel
for (int j=0; j < 256; j++,k--)
{
if(k<0)
{
k=255;
}
//Set RGB color of each LED
for(int i=0; i<NUM_LEDS; i++)
{
CRGB ledColor = wheel(((i * 256 / NUM_LEDS) + (dir==0?j:k)) % 256,dim);
leds[i]=ledColor;
}
FastLED.show();
FastLED.delay(wait);
}
}
}
CRGB wheel(int WheelPos, int dim)
{
CRGB color;
if (85 > WheelPos)
{
color.r=0;
color.g=WheelPos * 3/dim;
color.b=(255 - WheelPos * 3)/dim;;
}
else if (170 > WheelPos)
{
color.r=WheelPos * 3/dim;
color.g=(255 - WheelPos * 3)/dim;
color.b=0;
}
else
{
color.r=(255 - WheelPos * 3)/dim;
color.g=0;
color.b=WheelPos * 3/dim;
}
return color;
}
Now the issue i am facing is when i press a button (for eg 0) it runs the function RunningLightSlow(); i have written the infinite loop code because i want infinite light show and when i press button 1 it does not change the light pattern ,
Root cause would be once the function goes into infinite loop it then never receives the ir signal and hence never change the light pattern
Remove all infinite loops from your program and create a simple structure in loop() where you check for IR signal and update a "state" variable with the last button pressed.
void loop() {
// create a function or add here whatever is needed to read the IR code
irCode = readIrCode();
// check if the new code is identical to a previous code
if (lastIrCode != irCode) {
// memorize the current code
lastIrCode = irCode;
/ act according to user selection
switch (irCode) {
case Button_0:
doThis(); // this could be your RunningLightSlow()
break;
case Button_1:
doThat(); // maybe RainbowLights()
break;
default:
// for cases you have not handled above
doWhatever();
}
}
}
Do not forget to remove the infinite loops from the functions that run the lights and obviously you would need to declare the variables and set the correct calls.

lights not flashing off in loop function

So for a little background I am both new to Arduino and as well as to C++. I mostly deal with Javascript, so its likely I made some assumptions while programming this.
The goal of my code is to have a number of lights all flashing in sequence.
the function should turned the light on for each pin, waiting a second or so, then turning off all the pin, and then this is called again in the loop. However, in both the arduino and the online IDE, the LED flashed on but remained on.
My (incredibly generic) question is what is going wrong with my loop?
int NumOfOutputs = 1;
void setup() {
// put your setup code here, to run once:
if(NumOfOutputs >= 1){
for(int i = 2; i < NumOfOutputs + 2; i++){
pinMode(i, OUTPUT);
}
}
}
void flashSequence1(float baseRate){
for(int i = 2; i < NumOfOutputs + 2; i++){
digitalWrite(i,HIGH);
}
size_t: print(delay);
delay(baseRate * 1.00);
for(int i = 2; i < NumOfOutputs + 2; i++){
digitalWrite(i,LOW);
}
}
void flashSequence2(float baseRate, unsigned int repeat){
}
void flashSequence3(float baseRate, unsigned int repeat){
}
void loop() {
float baseRate = 1.0;
flashSequence1(baseRate);
//flashSequence2();
//flashSequence3();
}
Your delay is so short. It's simple: In order to make the human eye detect that a led is flashing, the delay between the led is on and the led is off must be greater than 10 msec. This came from my experiment with leds on Arduino.
Also, you should put a delay after led is on and a delay after led is off too.

(Arduino) Counting with cases

I am working on a stereo controller and have 1 rotary encoder with a push button. When I push the button it cycles through the options and the rotary encoder lets me set the intensity. I want the individual intensities to remain when I am switching back and forth. When I turn the bass to 50% and then set the volume to 80% I want to come back and the base still be at 50%. The problem I am having is that the intensities are transferring over.
For prototyping I am using 3 LEDS. I can set individual brightness but when I go to change the next LED it automatically changes to the intensity of the previous LED.
The reasoning behind this is that when I set the bass and treble and the volume I don't want the values jumping around when I come back to change something. I want to pick off where it left off.
I think the structure I am going for is a counter based on cases. A common variable outside the case is incremented by the rotary encoder and then stored in case if that is possible.
/*
** Rotary Encoder Example
** Use the Sparkfun Rotary Encoder to vary brightness of LED
**
** Sample the encoder at 200Hz using the millis() function
*/
int brightness = 0; // how bright the LED is, start at half brightness
int fadeAmount = 30; // how many points to fade the LED by
unsigned long currentTime;
unsigned long loopTime;
const int pin_A = 4; // pin 12
const int pin_B = 5; // pin 11
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
const int green = 11;
const int blue = 10;
const int red=9;
int last_bright=0;
int mode = 0; // Selector State (Initial state = ALL OFF)
int val = 0; // Pin 13 HIGH/LOW Status
int butState = 0; // Last Button State
int modeState = 0;
int selected=710;
int greenvol=0;
int redvol=0;
int bluevol=0;
int select_bright=0;
void setup() {
// declare pin 9 to be an output:
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(pin_A, INPUT);
pinMode(pin_B, INPUT);
currentTime = millis();
loopTime = currentTime;
}
void loop() {
// get the current elapsed time
currentTime = millis();
brightness=select_bright;
if(currentTime >= (loopTime + 5)){
// 5ms since last check of encoder = 200Hz
encoder_A = digitalRead(pin_A); // Read encoder pins
encoder_B = digitalRead(pin_B);
if((!encoder_A) && (encoder_A_prev)){
// A has gone from high to low
if(encoder_B) {
// B is high so clockwise
// increase the brightness, dont go over 255
if(brightness + fadeAmount <= 255) brightness += fadeAmount;
}
else {
// B is low so counter-clockwise
// decrease the brightness, dont go below 0
if(brightness - fadeAmount >= 0) brightness -= fadeAmount;
}
}
encoder_A_prev = encoder_A; // Store value of A for next time
// set the brightness of pin 9:
analogWrite(selected, brightness);
last_bright=brightness;
loopTime = currentTime; // Updates loopTime
}
// end of rotary encoder
val = digitalRead(8);
delay(5);
// If we see a change in button state, increment mode value
if (val != butState && val == HIGH){
mode++;
}
butState = val; // Keep track of most recent button state
// No need to keep setting pins *every* loop
if (modeState != mode)
// If no keys have been pressed yet don't execute
// the switch code below
{
switch ( mode ) {
case 2:
selected=red;
select_bright=redvol;
redvol=last_bright;
break;
case 3:
selected=green;
select_bright=greenvol;
greenvol = last_bright;
break;
default:
selected=blue;
select_bright=bluevol;
bluevol = last_bright;
mode = 1;
break;
}
}
}
I'd store the brightness value in an array and then use an index to change only one led.
Here is a (i hope) working example. Try it and see if it fits your needs ;)
I made some other changes (you can see them in the comments). Anyway I suggest you to add at least
debouncing on the encoder and the button pins
the complete encoder checking, i.e. check if either A or B changed, and in both directions.
Here is the code; just let me know ;)
byte fadeAmount = 30;
const byte pin_button = 8;
const byte pin_A = 4; // pin 12
const byte pin_B = 5; // pin 11
unsigned long loopTime;
unsigned char encoder_A;
unsigned char encoder_B;
unsigned char encoder_A_prev=0;
// Array to store the brightness of the
// red (0), green (1) and blue (2) leds
byte brightnesses[3];
byte lastbrightnesses[3];
byte currentLed;
// Pins for red (0), green (1) and blue (2) leds
byte led_pins[] = {9, 10, 11};
void setup() {
pinMode(pin_button, INPUT);
pinMode(pin_A, INPUT);
pinMode(pin_B, INPUT);
// set the brightnesses to their initial states
// and the lastbrightnesses to ANOTHER value
for (currentLed=0; currentLed<3; i++)
{
pinMode(led_pins[currentLed], OUTPUT);
brightnesses[currentLed] = 255;
lastbrightnesses[currentLed] = 0;
}
currentLed = 0;
loopTime = millis() - 5;
}
void loop() {
// I prefer this instead of yours
// because this is overflow-safe
if((millis() - loopTime) >= 5) {
loopTime += 5;
// Check encoder
encoder_A = digitalRead(pin_A);
encoder_B = digitalRead(pin_B);
if((!encoder_A) && (encoder_A_prev)){
// A has gone from high to low
if(encoder_B) {
// B is high so clockwise
// Again, this is overflow-safe
// And it compensates for not reaching the end of the values
if(brightnesses[currentLed] <= 255 - fadeAmount)
brightnesses[currentLed] += fadeAmount;
else
brightnesses[currentLed] = 255;
}
else {
// B is low so counter-clockwise
// decrease the brightness, dont go below 0
if(brightnesses[currentLed] >= fadeAmount)
brightnesses[currentLed] -= fadeAmount;
else
brightnesses[currentLed] = 0;
}
}
encoder_A_prev = encoder_A; // Store value of A for next time
// I'd read the button every 5ms too
val = digitalRead(pin_button);
if (val != butState && val == HIGH){
currentLed++;
if (currentLed >= 3) currentLed = 0;
butState = val;
}
}
// Here you can also check only currentLed instead
// of every led if you can only change it through
// the encoder
byte i;
for (i=0; i<3; i++)
{
if (lastbrightnesses[i] != brightnesses[i])
{
analogWrite(led_pins[i], brightnesses[i]);
lastbrightnesses[i] = brightnesses[i];
}
}
}

ATTiny array update error

I am making a persistence of vision display using an ATTiny85, programmed with Arduino using the arduino-tiny core.
It consists of a stick with 16 LEDs on it which is spun round quickly to 'draw' a picture in the air. The display buffer is represented by an array, the next index of which is output every time the timer fires. It uses a hall sensor wired to INT0 to sense top dead centre, where it zeroes the array index.
It is an 8 bit processor and I have 16 LEDs connected to LED drivers, so I actually use two arrays for the display.
So the weird thing is that when I initialised the display with a cross pattern, it displayed a bunch of broken lines; so I zeroed it first in case memory had some random stuff in it. Now it doesn't display anything (even though I write the cross pattern to it straight after zeroing it). I have no idea what is happening, any ideas?
I had it previously outputting just the index value, and the picture it traces appears to look like counting binary, so I think the hardware is working.
Note that I'm not using digitalWrite because it disables interrupts which might throw the timing off.
Here is the code: (sorry it's quite a lot)
#define COLUMNCOUNT 180
const int datapin = 4;
const int clockpin = 0;
const int latchpin = 1;
const int rxpin = 3;
const int hallpin = 2;
volatile int columns0[COLUMNCOUNT];
volatile int columns1[COLUMNCOUNT];
volatile int counter = 0;
void setup()
{
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
pinMode(rxpin, INPUT);
pinMode(hallpin, INPUT);
//make sure the arrays are all zeroed
for (int i = 0; i < COLUMNCOUNT; i++)
{
columns0[i] = 0;
columns1[i] = 0;
}
//make a cross pattern
columns0[0] = 255;
columns1[0] = 255;
columns0[45] = 255;
columns1[45] = 255;
columns0[90] = 255;
columns1[90] = 255;
columns0[135] = 255;
columns1[135] = 255;
//turn on the timer (prescale CK/16)
OCR1A = 255;
OCR1C = 255;
TCNT1 = 0;
TIMSK = _BV(OCIE1A);
TCCR1 = _BV(CTC1) | _BV(CS12) | _BV(CS10);
GIMSK = _BV(INT0);
sei();
}
void loop()
{
//nothing to do here
}
ISR(TIMER1_COMPA_vect)
{
if (counter < COLUMNCOUNT)
counter++;
outputWord(columns0[counter], columns1[counter]);
}
ISR(INT0_vect)
{
counter = 0;
}
void outputByte(int b)
{
int currentBit;
for (int i = 0; i < 8; i++)
{
currentBit = (b & 128) == 128;
PORTB = _BV(clockpin) | (currentBit ? _BV(datapin) : 0);
PORTB = PORTB ^ _BV(clockpin);
b <<= 1;
}
}
void outputWord(int hi, int lo)
{
outputByte(hi);
outputByte(lo);
PORTB = _BV(latchpin);
PORTB = 0;
}
Per C standard, global variables are initialised to 0. As such,
//make sure the arrays are all zeroed
for (int i = 0; i < COLUMNCOUNT; i++)
{
columns0[i] = 0;
columns1[i] = 0;
}
is not necessary. That action is taken care of automatically when the __do_clear_bss section is executed.
Also, as per C standard, the int type must be at least 16 bits wide. In AVR, the minimum is used. If you are using the free software toolchain, it contains inttypes.h which provides the functionality offered by stdint.h and some extra stuff. This was mentioned in another answer.
The statement:
PORTB = PORTB ^ _BV(clockpin);
can be rewritten as:
PINB = _BV(clockpin);
which compiles to only 1 instruction, as per Atmel's datasheets.
Macros provided by pgmspace.h can read from flash. Notice that you can not change the contents of flash as your program runs in most AVR chips.
Beware local/global variables and stack/heap collisions when handling this much data.
I've figured it out: it's an SRAM issue. The ATTiny85 only has 512 bytes of SRAM, so it can't hold all that data in memory at the same time. I'm investigating storing the data in flash memory using the PROGMEM directive instead.
I am also doing a Persistance of Vision (POV) with the Attiny44. (I am programming it via the Arduino as an ISP)
user Ben Jackson's tip for conserving SRAM memory was spot on: I originally was using "int"'s for my arrays and my Attiny would bug out if I tried to include additional arrays- However when I simply declared all of my arrays as "unsigned char"'s my code worked fabulously as it should!
Next time I will either order attiny45's or similar for more SRAM memory, and continue to use unsigned char's for my array declarations.
Thanks for the discussion guys!

Resources