Legion2 / CorsairLightingProtocol

Control LEDs connected to an Arduino with iCUE, create an unofficial Corsair iCUE compatible Arduino LED controller.
Apache License 2.0
499 stars 64 forks source link

Reversing part of a LED strip and size issue #364

Closed tiburcillo closed 4 months ago

tiburcillo commented 4 months ago

Describe the problem Based on a previous solution the creator of the project offered to reverse a part of the LED strip, I tried to apply it for a different project. In this project I have 5 strips of 10 leds and five 15-led fans. I think the code I reused works fine but when compiling for Arduino Pro Micro, its a tiny bit too large: Sketch uses 28950 bytes (100%) of program storage space. Maximum is 28672 bytes.

Screenshots ledschema

Code changes

/*
   Copyright 2020 Leon Kiefer

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
#include <CorsairLightingProtocol.h>
#include <FastLED.h>

#define NUMBER_OF_LEDS_PER_FAN 12

// spare

// actually used
#define DATA_PIN_FAN_1 5
#define DATA_PIN_FAN_2 6
#define DATA_PIN_FAN_3 7
#define DATA_PIN_FAN_4 8
#define DATA_PIN_FAN_5 9

#define DATA_PIN_STRIP_1 14
#define DATA_PIN_STRIP_1R 10
#define DATA_PIN_STRIP_2 16

CRGB ledsChannel1[75];
CRGB ledsChannel2[50];
CRGB ledsChannel2Reverse[20];

const char mySerialNumber[] PROGMEM = "2024B0BB1000";

CorsairLightingFirmwareStorageEEPROM firmwareStorage;
CorsairLightingFirmware firmware(CORSAIR_LIGHTING_NODE_PRO, &firmwareStorage);
FastLEDControllerStorageEEPROM storage;
FastLEDController ledController(&storage);
CorsairLightingProtocolController cLP(&ledController, &firmware);
CorsairLightingProtocolHID cHID(&cLP);

void setup() {
  //CLP::disableBuildInLEDs();
  // LED Fans
  //                          FAN_PIN           CRGB array            offset             number of leds per fan
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_1, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 0, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_2, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 1, NUMBER_OF_LEDS_PER_FAN);  
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_3, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 2, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_4, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 3, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_5, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 4, NUMBER_OF_LEDS_PER_FAN);

    // LED Strips
    //                          FAN_PIN           CRGB array            offset             number of leds per fan
  // INVERT Green/red for 12V led strips
    // virtual strip of 20 LEDs to be reversed
    FastLED.addLeds<WS2812B, DATA_PIN_STRIP_1, RGB>(ledsChannel2, 0, 20);
  // FRONT (20)
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_1R, RGB>(ledsChannel2Reverse, 0, 20);
  // TOP (20) to BACK (10)
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_2, RGB>(ledsChannel2, 20, 30);

  ledController.addLEDs(0, ledsChannel1, 60);
    ledController.addLEDs(1, ledsChannel2, 50);

  // stretch 5x 12-LED fans (type Corsair HD) to the 15 leds in the ThermalRight Ring type
  ledController.onUpdateHook(0, []() {
    CLP::scale(&ledController, 0, 75);
  });
}

void loop() {
    cHID.update();
  for (uint8_t i=0; i<20; i++) {
    ledsChannel2Reverse[20 - 1 - i] = ledsChannel2[i];
  }
    if (ledController.updateLEDs()) {
        FastLED.show();
    }
}

Is there a way to save some bytes and did I correctly understand the code? Thanks sooo much!

Legion2 commented 4 months ago

We can save some bytes by optimizing the Reverse Operation. We can do it in-place so it doesn't need double memory.

tiburcillo commented 4 months ago

Thanks for the hint, I'm no programmer but I got some help and will be trying as follows:

 CRGB overwritten;
  for (uint8_t i=0; i<10; i++) {
    overwritten = ledsChannel2[i];
    ledsChannel2[i] = ledsChannel2[19-i];
    ledsChannel2[19-i] = overwritten;
  }

Off to soldering the led strips now, will get back to you when I get to the testing phase. 👍

Legion2 commented 4 months ago

nice, the loop should go to 20 not to 10. for (uint8_t i=0; i<20; i++)

tiburcillo commented 4 months ago

Ah yes, thats a leftover because I was keeping the loop smaller so I could draw the led strip on paper. :) Thanks!

tiburcillo commented 4 months ago

It seems something is not coming through (white, then green over red to blue should start at bottom if reversed): ledstrip IMG20240313162405

With the current code the first 20 leds are not reversed.

/*
   Copyright 2020 Leon Kiefer

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
#include <CorsairLightingProtocol.h>
#include <FastLED.h>

#define NUMBER_OF_LEDS_PER_FAN 12

// spare

// actually used
#define DATA_PIN_FAN_1 5
#define DATA_PIN_FAN_2 6
#define DATA_PIN_FAN_3 7
#define DATA_PIN_FAN_4 8
#define DATA_PIN_FAN_5 9

#define DATA_PIN_STRIP_1R 10
#define DATA_PIN_STRIP_2 16

CRGB ledsChannel1[75];
CRGB ledsChannel2[50];

const char mySerialNumber[] PROGMEM = "2024B0BB100X";

CorsairLightingFirmwareStorageEEPROM firmwareStorage;
CorsairLightingFirmware firmware(CORSAIR_LIGHTING_NODE_PRO, &firmwareStorage);
FastLEDControllerStorageEEPROM storage;
FastLEDController ledController(&storage);
CorsairLightingProtocolController cLP(&ledController, &firmware);
CorsairLightingProtocolHID cHID(&cLP);

void setup() {
  CLP::disableBuildInLEDs();
  // LED Fans
  //                          FAN_PIN           CRGB array            offset             number of leds per fan
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_1, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 0, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_2, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 1, NUMBER_OF_LEDS_PER_FAN);  
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_3, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 2, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_4, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 3, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_5, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 4, NUMBER_OF_LEDS_PER_FAN);

    // LED Strips
    //                          FAN_PIN           CRGB array            offset             number of leds per fan
  // RGB for 12V led strips // GRB for 5V led strips
  // BOTTOM
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_1R, GRB>(ledsChannel2, 0, 20);
  // SIDE to TOP
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_2, GRB>(ledsChannel2, 20, 30);

  // Adding the LEDS to the controller
  ledController.addLEDs(0, ledsChannel1, 60);
    ledController.addLEDs(1, ledsChannel2, 50);

  // stretch 5x 12-LED fans (type Corsair HD) to the 15 leds in the ThermalRight Ring type
  ledController.onUpdateHook(0, []() {
    CLP::scale(&ledController, 0, 75);
  });

}

void loop() {
  cHID.update();
  CRGB overwritten;
  for (uint8_t i=0; i<20; i++) {
    overwritten = ledsChannel2[i];
    ledsChannel2[i] = ledsChannel2[19-i];
    ledsChannel2[19-i] = overwritten;
  }
    if (ledController.updateLEDs()) {
        FastLED.show();
    }
}
Legion2 commented 4 months ago

You must put the for loop in to the if block before the FastLED.show();

Legion2 commented 4 months ago

Alternatively you can create an on update hook for the channel and place the for loop in it

tiburcillo commented 4 months ago

I was just trying to put it in an update hook and now it works now indeed. I did keep the loop on 10 iterations though as two positions are swapped in one go. I also had to debug my code for the fans. I was struggling getting multiple fans to work with the scaling function. My mistake was setting 12 leds per data pin and then the scaling. That didn't look nice as the ring stayed dark for leds 13-15 and then jumped to the next fan. Setting 15 leds per data pin solved the issue. This is the finale code, in case somebody can use it:

/*
   Copyright 2020 Leon Kiefer

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
#include <CorsairLightingProtocol.h>
#include <FastLED.h>

#define NUMBER_OF_LEDS_PER_FAN 15

// spare

// actually used
#define DATA_PIN_FAN_1 5
#define DATA_PIN_FAN_2 6
#define DATA_PIN_FAN_3 7
#define DATA_PIN_FAN_4 8
#define DATA_PIN_FAN_5 9

#define DATA_PIN_STRIP_1R 10
#define DATA_PIN_STRIP_2 16

CRGB ledsChannel1[75];
CRGB ledsChannel2[50];
CRGB overwritten;

const char mySerialNumber[] PROGMEM = "2024B0BB1006";

CorsairLightingFirmwareStorageEEPROM firmwareStorage;
CorsairLightingFirmware firmware(CORSAIR_LIGHTING_NODE_PRO, &firmwareStorage);
FastLEDControllerStorageEEPROM storage;
FastLEDController ledController(&storage);
CorsairLightingProtocolController cLP(&ledController, &firmware);
CorsairLightingProtocolHID cHID(&cLP);

void setup() {
  CLP::disableBuildInLEDs();
  // LED Fans
  //                          FAN_PIN           CRGB array            offset             number of leds per fan
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_1, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 0, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_2, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 1, NUMBER_OF_LEDS_PER_FAN);  
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_3, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 2, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_4, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 3, NUMBER_OF_LEDS_PER_FAN);
  FastLED.addLeds<WS2812B, DATA_PIN_FAN_5, GRB>(ledsChannel1, NUMBER_OF_LEDS_PER_FAN * 4, NUMBER_OF_LEDS_PER_FAN);

    // LED Strips
    //                          FAN_PIN           CRGB array            offset             number of leds per fan

  // RGB for 12V led strips // GRB for 5V led strips
  // BOTTOM
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_1R, GRB>(ledsChannel2, 0, 20);
  // SIDE to TOP
  FastLED.addLeds<WS2812B, DATA_PIN_STRIP_2, GRB>(ledsChannel2, 20, 30);

  // Adding the LEDS to the controller
  ledController.addLEDs(0, ledsChannel1, 75);
    ledController.addLEDs(1, ledsChannel2, 50);

  // stretch 60 leds to 75 leds: 5x 12-LED fans (type Corsair HD in iCUE) to the 15 leds in the ThermalRight Ring type
  ledController.onUpdateHook(0, []() {
     CLP::SegmentScaling segments[5] = {{12, 15}, {12, 15}, {12, 15}, {12, 15}, {12, 15}};
     CLP::scaleSegments(&ledController, 0, segments, 5);
  });

  ledController.onUpdateHook(1, []() {
      // reverse the first 20 LEDs of ledsChannel2
    for (uint8_t i=0; i<10; i++) {
    overwritten = ledsChannel2[i];
    ledsChannel2[i] = ledsChannel2[19-i];
    ledsChannel2[19-i] = overwritten;
    }
  });

}

void loop() {
  cHID.update();

  if (ledController.updateLEDs()) {
        FastLED.show();
    }
}