Making Ambient Light on Raspberry Pico. Contribution to OpenRgb
Ambient Light helps you work at night. When it is dark around and only the monitor shines, the eyes are very strained. Personally, I enjoy working without a top color, and this solution helps me do that.

I got this idea when I moved to a new place with a large table. I remembered the video AlexGyver and decided to do the same. But unlike Haver, I’m making a device based on the Corsair Lightning Protocol, which allows it to be more versatile in setting up effects and choosing a platform.
AlexGyver Solution Problems
Windows only
Difficulty finding Arduino and its price (at the time of January 2023)
No other effects
Giant4 decision problem [ссылка удалена мод.]
Windows or Android only
No other effects
There is also a solution from Aliexpress, but they also use a proprietary program for Windows.

What is Ambient Light?
This is a dynamic backlight of the monitor, which, as it were, continues it. LEDs bring out the edges of the screen, thereby giving the illusion of an increase in size.
IMPORTANT!
Ambient Light for PC only. That is, we do without Hdmi Splitter.
Accessories
I chose the rpi pico because it was cheaper than the Arduino (later I had to suffer a little because of this, but everything works). I took everything in different stores, so I can not advise anything.

We will need:
soldering iron
Solder Coil
address LED strip (depends on the perimeter of your monitor, you need to count it with a tape measure, 4 meters was enough for me, I took it at 5v)
Active flux
A piece for cleaning the flux (you can take alcohol or acetone)
300-500 ohm resistor (without it the LEDs will burn out)
Power supply for your tape (better to take with a margin, 20w was enough for me)
Power connector (needed to support your voltage)
Beautiful box
Glue gun to keep it all together
Wires that would withstand your voltage (took 10 meters)
rpi pico itself
usb cable for rpi pico
Breadboard for soldering
Straight arms (optional)
The price came out under 6-8 thousand rubles, since there were no many elements (soldering iron, solder and other things for soldering)
How will we output from the screen to the LED strip?
For this we will use Corsair Lightning Protocol, which is compatible with many programs. We are interested in OpenRGB (available on Mac os, Windows, Linux). With it, we will set the colors for the LEDs.
IMPORTANT! x2
I accidentally burned as many as 4 LEDs, as I started without a resistor. Don’t repeat my mistakes.
Collecting!




We solve the problem with the firmware
There is a small feature. The FastLed library does not have support for the rp2040 (rpi pico) processor in the upstream branch. Therefore, you need to manually download the unofficial library https://github.com/Zitt/FastLED/tree/rp2040
Installation




Link to additional list of devices: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json



We flash
Download arduino ide. Then we install the drivers for rpi pico and flash it by changing the number of LEDs and the tape port.
We flash


Ribbon setup via iCUE
iCUE (corsair node management software) is designed for proprietary tapes, but you can add your own there, which is what you need to do.
Settings


OpenRgb and its features
OpenRgb lacked settings to achieve the effect I wanted. I also didn’t like the Ambient Light modes of operation: only the average value of the entire screen or the screen output completely without anti-aliasing, which causes the tape to change colors abruptly and hurt the eyes. And Ambient Light takes pictures through Qt at 60 frames per second. Because of this, the fps of the screen sags twice !! This is not the case, and I decided to change the code that would have to solve these two problems.
OpenRgb also has an api, but it’s not suitable for video streaming. It changes very slowly and has a lot of latency.
Making our effect
For the effect to work adequately, I had to change part of the Effects OpenRgb plugin code and add new functionality. In two days I:
Improved ScreenRecorder performance
Made an additional menu with global settings
Added the smoothness parameter which is responsible for smoothing
Made the SmoothMatrix function to work for the matrix
Code
ScreenRecorder
Initially, there was no instance in the Screen Recorder code. So, with each new effect using screen recording, it was necessary to create another one, thereby increasing the load on the computer.
ScreenRecorder* ScreenRecorder::Get()
{
if(!instance) // Проверяем что instance еще нет
{
instance = new ScreenRecorder(); // Создаем если нет
}
return instance;
}
Now all effects can use one instance of ScreenRecorder
Global Settings
First you need to make these same settings in qtcreator

This is how it looks in the editor

I took the existing About window as a basis. I copied it and wrote my own logic
GlobalSettings::GlobalSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::GlobalSettings)
{
ui->setupUi(this); // подключаемся к qt
int fpscapture = ScreenRecorder::Get()->GetFpsCapture(); // получаем скорость захвата кадров
ui->fpscapture->setValue(fpscapture); // ставим ползунок на нужное место
}
Widget initialization code
void GlobalSettings::on_fpscapture_valueChanged(int value)
{
ScreenRecorder::Get()->SetFpsCapture(value); // устанвлиавем кадры
ui->fpscapture->setValue(value); // меняем значение позунка
}
Code that, when the value of the slider changes, changes the value of the frame capture rate
Smoothness parameter


Smooth Matrix
The main effect in Ambient I think is Screen Copy. Therefore, I will explain the principle of operation of SmoothMatrix on it.
for(unsigned int h = 0; h < height; h++) // перебираем экран по высоте
{
for(unsigned int w = 0; w < width; w++) // перебираем экран по ширине
{
// получаем цвет пикселя
QColor color = scaled.pixelColor(reverse ? width - w - 1: w, h);
unsigned int led_num = map[h * width + w];
// изменяем цвет на ленте
controller_zone->SetLED(led_num, SmoothMatrix(ColorUtils::fromQColor(color), w, h), Brightness);
}
}
Here I added only the use of the SmoothMatrix function
RGBColor Ambient::SmoothMatrix(RGBColor color, int w, int h)
{
if(color != previous[w][h]) // проверяем что цвет не равен предыдущему
{
// QToolTipedSlider не можете перебирать в нецелых числах
// поэтому нам нужно превратить переменную в float
float smoothness_f = smoothness;
// используем интерполяцию
color = ColorUtils::Interpolate(previous[w][h], color, smoothness_f / 1000);
// записываем его как предыдущий цвет
previous[w][h] = color;
}
return color;
}
The function itself
Result
Video with work
Whole code made available to the public. To install this plugin, you need:
Install latest openrgb version from pipeline
Download plugin from my repository
Import extension in settings section
Instructions with pictures



Windows will swear, but only because the software does not have a signature due to the fact that we use the pipeline version


Settings
For normal operation, you still need to download plugin to create a matrix so that the screen is displayed correctly.





Outcome
I made myself a backlight, exactly what I wanted. I really liked doing it with my hands and understanding both the C-code and soldering. For me it was a great experience for the New Year holidays. I experienced a lot of emotions from this process, when something went wrong, when something did not work out, but in the end everything worked!
This implementation works on any platform (Windows, Linux, Mac os). In addition to the Ambient Light effect, you can configure others in the Effects plugin.
PS
I think I’ll also tell you about the rebirth of my Openwrt router, which I ruined. To fix it, I had to connect via UART using 🐬 Flipper Zero and modify the Openwrt firmware.