Светодиодная лента RGB с дистанционным управлением Arduino, проблемы с яркостью/затемнением
У меня есть этот скетч:
#include <TimerOne.h>
#include <IRremote.h>
#include <RGBMood.h>
int RECV_PIN = 2; // PIN-код ИК-приемника
int led = 13; // Satus-LED PIN
int modus; // Метод прерывания-запроса
int ledr = 11; // Красный светодиод RGB PIN
int ledg = 12; // RGB-светодиод зеленый PIN-код
int ledb = 13; // RGB-светодиод синий PIN-код
int SerialBuffer = 0;
RGBMood m(ledr, ledg, ledb);
int timerwert = 20; // Время таймера прерывания в мс
String readString;
// Массивы цветов
int black[3] = { 0, 0, 0 };
int white[3] = { 100, 100, 100 };
int red[3] = { 100, 0, 0 };
int green[3] = { 0, 100, 0 };
int blue[3] = { 0, 0, 100 };
int yellow[3] = { 40, 95, 0 };
int dimWhite[3] = { 30, 30, 30 };
int brightness = 0; // насколько яркий светодиод
int fadeAmount = 5; // на сколько точек затухать светодиод
// и т. д.
// Установить начальный цвет
int redVal = black[0];
int grnVal = black[1];
int bluVal = black[2];
int wait = 10; // 10 мс внутренняя задержка кроссфейда; увеличить для более медленного затухания
int hold = 0; // Необязательная задержка, когда цвет завершен, до следующего кроссфейда
int DEBUG = 1; // счетчик ОТЛАДКИ; если установлено значение 1, значения будут записываться обратно через последовательный порт
int loopCount = 60; // Как часто должен сообщать DEBUG?
int repeat = 3; // Сколько раз мы должны выполнить цикл перед остановкой? (0 без остановки)
int j = 0; // Счетчик цикла для повтора
// Инициализировать цветовые переменные
int prevR = redVal;
int prevG = grnVal;
int prevB = bluVal;
#define ON 0xF4F37A66
#define OFF 0x1363ADB4
#define BRIGHTNESS_UP 0xE6721691
#define BRIGHTNESS_DOWN 0xE9721B48
#define FLASH 0xFFF00F
#define STROBE 0xFFE817
#define FADE 0x39ED1255
#define SMOOTH 0xFFC837
#define RED 0x9D561314
#define GREEN 0XCB8E93A5
#define BLUE 0xC88E8EEC
#define WHITE 0x16DBBEE3
#define ORANGE 0xFFB04F
#define YELLOW_DARK 0xFFA857
#define YELLOW_MEDIUM 0xFF9867
#define YELLOW_LIGHT 0xFF8877
#define GREEN_LIGHT 0XFF30CF
#define GREEN_BLUE1 0XFF28D7
#define GREEN_BLUE2 0XFF18E7
#define GREEN_BLUE3 0XFF08F7
#define BLUE_RED 0XFF708F
#define PURPLE_DARK 0XFF6897
#define PURPLE_LIGHT 0XFF58A7
#define PINK 0XFF48B7
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
pinMode(ledr, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(ledg, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(ledb, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(led, OUTPUT); // установить светодиод состояния как выход
m.setMode(RGBMood::RANDOM_HUE_MODE); // Автоматическое случайное затухание.
m.setHoldingTime(4000); // Сохраняйте тот же цвет в течение 4 секунд, прежде чем снова исчезнуть.
m.setFadingSteps(150); // Затухание со 150 шагами.
m.setFadingSpeed(50); // Каждый шаг длится 50 мс. Полное исчезновение занимает 50 * 150 = 7,5 секунд.
m.setHSB(random(359), 255, 255);
Serial.begin(9600);
irrecv.enableIRIn(); // Начало ИК-приема
Timer1.initialize(timerwert); // Инициализация прерываний по таймеру
Timer1.attachInterrupt(leseIR); // ИК-чтение из прерывания
}
void leseIR(){
if (irrecv.decode(&results)){
irrecv.resume(); // Получаем следующее значение
switch (results.value) {
case FADE: // Modus Fade (DIY 4)
modus = 1;
break;
case 0xFF906F: // Modus pcambi (DIY 5)
modus = 2;
break;
case ON: //Питание
modus = 0;
crossFade(white); // Светодиоды RGB выключены
break;
case OFF: //Питание
modus = 0;
crossFade(black); // Светодиоды RGB выключены
break;
case BLUE: //Синий 0,0,255
modus = 0;
crossFade(blue);
break;
case RED: // Гниль
modus = 0;
crossFade(red);
break;
case GREEN://Grün
modus = 0;
crossFade(green);
break;
case WHITE: //Weiss
modus = 0;
crossFade(white);
break;
case BRIGHTNESS_UP: // ЗАТЕМНЕНИЕ
modus = 0;
// переход от минимального к максимальному с шагом 5 пунктов:
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
// устанавливаем значение (диапазон от 0 до 255):
analogWrite(ledg, fadeValue);
}
break;
case BRIGHTNESS_DOWN: //оранжевый
modus = 0;
for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
// устанавливаем значение (диапазон от 0 до 255):
analogWrite(ledg, fadeValue);
}
break;
case 0xFFAA55://Grün mitrtel
modus = 0;
break;
case 0xFF926D: // синий миттель
modus = 0;
break;
case 0xFF12ED: //роза
modus = 0;
break;
} // Переключение КОНЕЦ
}
}
void loop() {
if(modus==1){ // Запрос pb Modus:1
m.tick();
}
Serial.println(results.value, HEX);
Serial.println(DEC);
Serial.println(DEC);
Serial.println(DEC);
}
int calculateStep(int prevValue, int endValue) {
int step = endValue - prevValue; // Каков общий разрыв?
if (step) { // Если не ноль,
step = 1020/step; // делим на 1020
}
return step;
}
/* The next function is calculateVal. When the loop value, i,
* reaches the step size appropriate for one of the
* colors, it increases or decreases the value of that color by 1.
* (R, G, and B are each calculated separately.)
*/
int calculateVal(int step, int val, int i) {
if ((step) && i % step == 0) { // Если шаг не равен нулю и пришло время изменить значение,
if (step > 0) { // увеличиваем значение, если шаг положительный...
val += 1;
}
else if (step < 0) { // ...или уменьшить его, если шаг отрицательный
val -= 1;
}
}
// Защитное вождение: убедитесь, что значение val находится в диапазоне 0-255.
if (val > 255) {
val = 255;
}
else if (val < 0) {
val = 0;
}
return val;
}
/* crossFade() converts the percentage colors to a
* 0-255 range, then loops 1020 times, checking to see if
* the value needs to be updated each time, then writing
* the color values to the correct pins.
*/
void crossFade(int color[3]) {
// Преобразование в 0-255
int R = (color[0] * 255) / 100;
int G = (color[1] * 255) / 100;
int B = (color[2] * 255) / 100;
int stepR = calculateStep(prevR, R);
int stepG = calculateStep(prevG, G);
int stepB = calculateStep(prevB, B);
for (int i = 0; i <= 1020; i++) {
redVal = calculateVal(stepR, redVal, i);
grnVal = calculateVal(stepG, grnVal, i);
bluVal = calculateVal(stepB, bluVal, i);
analogWrite(ledr, redVal); // Записываем текущие значения на выводы светодиода
analogWrite(ledg, grnVal);
analogWrite(ledb, bluVal);
delay(wait); // Пауза в миллисекундах ожидания перед возобновлением цикла
}
// Обновить текущие значения для следующего цикла
prevR = redVal;
prevG = grnVal;
prevB = bluVal;
delay(hold); // Пауза для необязательных миллисекунд ожидания перед возобновлением цикла
}
Он работает как шарм, затухание работает плавно с использованием timer1
, цвета на светодиодах отображаются правильно, но я не могу исправить часть яркости. Может ли кто-нибудь предоставить пример кода для этого?
Если кто-то еще хочет использовать код, я использую Arduino Mega 2560, пожалуйста, используйте те же PIN-коды, что и у меня, поскольку таймеры работают только на 11,12,13 на этом Arduino. (ссылка с информацией о выводах для нескольких плат Arduino)
- библиотека настроений RGB
- библиотека TimerOne
- ИК-библиотека
Я использую маленькое ИК-управление Xbox 360 (без цифровой клавиатуры), некоторые шестнадцатеричные коды остались нетронутыми из оригинального скетча, найденного в Интернете.
исходная тема
@Stathis Ntonas, 👍5
Обсуждение2 ответа
Лучший ответ:
У вас нет задержки в цикле затухания, он изменяется от 0 до 255 почти мгновенно:
for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
// устанавливаем значение (диапазон от 0 до 255):
analogWrite(ledg, fadeValue);
}
Но я не уверен, что вы хотите переходить от выключенного к включенному за один раз. Если вы хотите просто увеличивать и уменьшать яркость:
Сначала обратите внимание, что prevR, prevG, prevB
содержат текущие значения светодиодов. Поэтому мы будем использовать их.
Измените регистр переключателя на:
case BRIGHTNESS_UP:
modus = 0;
int c[3];
// уменьшаем на 0,9*значение, но также уменьшаем на 2, так что получаем ноль
c[0] = (prevR-2) * 90 / 100;
c[1] = (prevG-2) * 90 / 100;
c[2] = (prevB-2) * 90 / 100;
for( int j = 0; j < 3; j++ ) {
if (c[j] < 0) c[j] = 0;
}
crossFade(c);
break;
case BRIGHTNESS_DOWN:
modus = 0;
int c[3];
// увеличим значение на 1/0,9, но также добавим 2, чтобы получить ноль
c[0] = (prevR+2) * 100 / 90 + 2;
c[1] = (prevG+2) * 100 / 90 + 2;
c[2] = (prevB+2) * 100 / 90 + 2;
for( int j = 0; j < 3; j++ ) {
if (c[j] > 100) c[j] = 100;
}
crossFade(c);
break;
Я не могу проверить, работает ли это, пожалуйста, проверьте и посмотрите.
Другой подход:
Глобальная переменная яркости:
int brightness = 100;
int c[3];
Изменяйте это значение каждый раз:
case BRIGHTNESS_UP:
modus = 0;
brightness += 5;
if (brightness > 255) brightness = 255;
c[0] = prevR; c[1] = prevG; c[2] = prevB;
crossFade(c);
break;
case BRIGHTNESS_DOWN:
modus = 0;
brightness -= 5;
if (brightness < 0) brightness = 0;
c[0] = prevR; c[1] = prevG; c[2] = prevB;
crossFade(c);
break;
Затем в crossFade
мы меняем последние несколько строк:
analogWrite(ledr, redVal * brightness / 255); // Записываем текущие значения на выводы светодиода
analogWrite(ledg, grnVal * brightness / 255);
analogWrite(ledb, bluVal * brightness / 255);
Обновление 2:
Я думаю, что может произойти то, что цвет уменьшается на яркость, а затем это уменьшенное значение сохраняется в prevR/G/B, хотя на самом деле это должно быть просто полное значение яркости. Попробуйте изменить последний бит crossFade
на :
prevR = color[0];
prevG = color[1];
prevB = color[2];
IDE сообщает, что происходит переобъявление 'int c [3], @Stathis Ntonas
Попробуйте переместить int c[3]
за пределы leseIR()
и сделать его глобальным. Удалите все экземпляры в операторе переключения., @geometrikal
возможно, вам захочется повозиться и с соотношениями, скажем, использовать 80 вместо 90, 5 вместо 2 и т. д. Я пытался использовать соотношение, потому что наши глаза воспринимают яркость в логарифмическом масштабе, поэтому небольшое изменение низкой яркости похоже на большое изменение высокой яркости., @geometrikal
Я удалил его, код скомпилировал, но когда я нажимаю кнопку увеличения яркости, цвет становится черным (выключается), а когда я нажимаю кнопку уменьшения яркости, после нескольких нажатий кнопки цвет становится белым., @Stathis Ntonas
упс, я неправильно перепутал BRIGHTNESS_UP
и BRIGHTNESS_DOWN
, @geometrikal
см. этот вопрос, чтобы узнать о подходе некоторых людей к правильному изменению яркости http://electronics.stackexchange.com/questions/1983/correcting-for-non-linear-brightness-in-leds-when-using-pwm, @geometrikal
Яркость, возможно, придется сделать отдельной переменной и применить в CrossFade., @geometrikal
Привет, я попробовал отредактированный подход: все цвета тускнеют до 0 одним нажатием кнопки, независимо от того, увеличиваете или уменьшаете яркость. Итак, если я выбрал ЗЕЛЕНЫЙ цвет, он затемняется до 0, то же самое относится ко всем. Класс Crossfade выполняет следующие действия: когда выбран цвет «КРАСНЫЙ» и нажмите кнопку «ЗЕЛЕНАЯ», цвет «КРАСНЫЙ» тускнеет до «0», а «ЗЕЛЕНЫЙ» — до «100». Я предполагаю, что нам не следует использовать класс Crossfade для управления яркостью., @Stathis Ntonas
Эй, не могли бы вы заставить crossFade
распечатать значения color
и RGB
и просто проверить, все ли в порядке? например Serial.println(color[0],DEC);
и так далее., @geometrikal
Нажатие кнопки RED
приводит к crossfade
**:** 100,0,0
и color
**:** 255,0,0
. ЗЕЛЕНЫЙ crossfade
**:** 0,100,0
и color
**:** 0,255,0
**.** СИНИЙ crossfade
**:** 0,0,100
и color
**:** 0,0,255
**.** БЕЛЫЙ crossfade
**:** 100,100,100
и цвет 255,255,255
**.** Итак, вроде бы все в порядке., @Stathis Ntonas
Ой, извините, я имел в виду увеличение/уменьшение яркости с помощью кода, который я опубликовал. :), @geometrikal
Я переместил часть кода analogWrite
внутрь переключателя
BRIGHTNESS_UP
& BRIGHTNESS_DOWN
, и это работает. Я также удалил строку crossFade(c);
.
Вот рабочий код:
#include <TimerOne.h>
#include <IRremote.h>
#include <RGBMood.h>
int RECV_PIN = 2; // PIN-код ИК-приемника
int led = 13; // Satus-LED PIN
int modus; // Метод прерывания-запроса
int ledr = 11; // Красный светодиод RGB PIN
int ledg = 12; // RGB-светодиод зеленый PIN-код
int ledb = 13; // RGB-светодиод синий PIN-код
int SerialBuffer = 0;
int c[3];
// Массив контактов RGB
int CH[3] = {11, 12, 13};
int val[3] = {0, 0, 0}; // яркость светодиода 0-255
RGBMood m(ledr, ledg, ledb);
int timerwert = 20; // Время таймера прерывания в мс
String readString;
// Массивы цветов
int black[3] = { 0, 0, 0 };
int white[3] = { 100, 100, 100 };
int red[3] = { 100, 0, 0 };
int green[3] = { 0, 100, 0 };
int blue[3] = { 0, 0, 100 };
int yellow[3] = { 40, 95, 0 };
int dimWhite[3] = { 30, 30, 30 };
int brightness = 100; // насколько яркий светодиод
int fadeAmount = 5; // на сколько точек затухать светодиод
// и т. д.
// Установить начальный цвет
int redVal = black[0];
int grnVal = black[1];
int bluVal = black[2];
int wait = 10; // 10 мс внутренняя задержка кроссфейда; увеличить для более медленного затухания
int hold = 0; // Необязательная задержка, когда цвет завершен, до следующего кроссфейда
int DEBUG = 1; // счетчик ОТЛАДКИ; если установлено значение 1, значения будут записываться обратно через последовательный порт
int loopCount = 60; // Как часто должен сообщать DEBUG?
int repeat = 3; // Сколько раз мы должны выполнить цикл перед остановкой? (0 без остановки)
int j = 0; // Счетчик цикла для повтора
// Инициализировать цветовые переменные
int prevR = redVal;
int prevG = grnVal;
int prevB = bluVal;
#define ON 0xF4F37A66
#define OFF 0x1363ADB4
#define BRIGHTNESS_UP 0xE6721691
#define BRIGHTNESS_DOWN 0xE9721B48
#define FLASH 0xFFF00F
#define STROBE 0xFFE817
#define FADE 0x39ED1255
#define SMOOTH 0xFFC837
#define RED 0x9D561314
#define GREEN 0XCB8E93A5
#define BLUE 0xC88E8EEC
#define WHITE 0x16DBBEE3
#define ORANGE 0xFFB04F
#define YELLOW_DARK 0xFFA857
#define YELLOW_MEDIUM 0xFF9867
#define YELLOW_LIGHT 0xFF8877
#define GREEN_LIGHT 0XFF30CF
#define GREEN_BLUE1 0XFF28D7
#define GREEN_BLUE2 0XFF18E7
#define GREEN_BLUE3 0XFF08F7
#define BLUE_RED 0XFF708F
#define PURPLE_DARK 0XFF6897
#define PURPLE_LIGHT 0XFF58A7
#define PINK 0XFF48B7
#define MAX 255
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
pinMode(ledr, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(ledg, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(ledb, OUTPUT); // Установить выводы RGB-светодиода в качестве вывода
pinMode(led, OUTPUT); // установить светодиод состояния как выход
// инициируем вывод rgb pins
for (int i=0; i<3; i++)
{
pinMode(CH[i], OUTPUT);
}
m.setMode(RGBMood::RANDOM_HUE_MODE); // Автоматическое случайное затухание.
m.setHoldingTime(4000); // Сохраняйте тот же цвет в течение 4 секунд, прежде чем снова исчезнуть.
m.setFadingSteps(150); // Затухание со 150 шагами.
m.setFadingSpeed(50); // Каждый шаг длится 50 мс. Полное исчезновение занимает 50 * 150 = 7,5 секунд.
m.setHSB(random(359), 255, 255);
Serial.begin(9600);
irrecv.enableIRIn(); // Начало ИК-приема
Timer1.initialize(timerwert); // Инициализация прерываний по таймеру
Timer1.attachInterrupt(leseIR); // ИК-чтение из прерывания
}
void leseIR(){
if (irrecv.decode(&results)){
irrecv.resume(); // Получаем следующее значение
switch (results.value) {
case FADE: // Modus Fade (DIY 4)
modus = 1;
break;
case 0xFF906F: // Modus pcambi (DIY 5)
modus = 2;
break;
case ON: //Питание
modus = 0;
crossFade(white); // Светодиоды RGB выключены
break;
case OFF: //Питание
modus = 0;
crossFade(black); // Светодиоды RGB выключены
break;
case BLUE: //Синий 0,0,255
modus = 0;
crossFade(blue);
break;
case RED: // Гниль
modus = 0;
crossFade(red);
break;
case GREEN://Grün
modus = 0;
crossFade(green);
break;
case WHITE: //Weiss
modus = 0;
crossFade(white);
break;
case BRIGHTNESS_UP: // ЗАМЕЧАНИЕ
modus = 0;
brightness += 5;
if (brightness > 255) brightness = 255;
c[0] = prevR; c[1] = prevG; c[2] = prevB;
analogWrite(ledr, redVal * brightness / 255); // Записываем текущие значения на выводы светодиода
analogWrite(ledg, grnVal * brightness / 255);
analogWrite(ledb, bluVal * brightness / 255);
break;
case BRIGHTNESS_DOWN: // затемнение вниз
modus = 0;
brightness -= 5;
if (brightness < 0) brightness = 0;
c[0] = prevR; c[1] = prevG; c[2] = prevB;
analogWrite(ledr, redVal * brightness / 255); // Записываем текущие значения на выводы светодиода
analogWrite(ledg, grnVal * brightness / 255);
analogWrite(ledb, bluVal * brightness / 255);
break;
case 0xFFAA55://Grün mitrtel
modus = 0;
break;
case 0xFF926D: // синий миттель
modus = 0;
break;
case 0xFF12ED: //роза
modus = 0;
break;
} // Переключение КОНЕЦ
}
}
void loop() {
if(modus==1){ // Запрос pb Modus:1
m.tick();
}
if(modus==2){ // Запрос pb Modus:1
}
Serial.println(prevR);
Serial.println(prevG);
Serial.println(prevB);
// Serial.println(results.value, HEX);
// Serial.println(DEC);
// Serial.println(DEC);
// Serial.println(DEC);
// Serial.print("Значения каналов 1,2,3:"); // отправляет значения яркости на последовательный монитор
// for(int i=0; i<3; i++){ // при каждом нажатии пульта
// Serial.print(CH[i]);
// Serial.print(" ");
// }
}
int calculateStep(int prevValue, int endValue) {
int step = endValue - prevValue; // Каков общий разрыв?
if (step) { // Если не ноль,
step = 1020/step; // делим на 1020
}
return step;
}
/* The next function is calculateVal. When the loop value, i,
* reaches the step size appropriate for one of the
* colors, it increases or decreases the value of that color by 1.
* (R, G, and B are each calculated separately.)
*/
int calculateVal(int step, int val, int i) {
if ((step) && i % step == 0) { // Если шаг не равен нулю и пришло время изменить значение,
if (step > 0) { // увеличиваем значение, если шаг положительный...
val += 1;
}
else if (step < 0) { // ...или уменьшить его, если шаг отрицательный
val -= 1;
}
}
// Защитное вождение: убедитесь, что значение val находится в диапазоне 0-255.
if (val > 255) {
val = 255;
}
else if (val < 0) {
val = 0;
}
return val;
}
/* crossFade() converts the percentage colors to a
* 0-255 range, then loops 1020 times, checking to see if
* the value needs to be updated each time, then writing
* the color values to the correct pins.
*/
void crossFade(int color[3]) {
// Преобразование в 0-255
int R = (color[0] * 255) / 100;
int G = (color[1] * 255) / 100;
int B = (color[2] * 255) / 100;
int stepR = calculateStep(prevR, R);
int stepG = calculateStep(prevG, G);
int stepB = calculateStep(prevB, B);
for (int i = 0; i <= 1020; i++) {
redVal = calculateVal(stepR, redVal, i);
grnVal = calculateVal(stepG, grnVal, i);
bluVal = calculateVal(stepB, bluVal, i);
analogWrite(ledr, redVal); // Записываем текущие значения на выводы светодиода
analogWrite(ledg, grnVal);
analogWrite(ledb, bluVal);
delay(wait); // Пауза в миллисекундах ожидания перед возобновлением цикла
}
// Обновить текущие значения для следующего цикла
prevR = redVal;
prevG = grnVal;
prevB = bluVal;
delay(hold); // Пауза для необязательных миллисекунд ожидания перед возобновлением цикла
}
Спасибо, geometrikal, за вашу поддержку! Вы верите, что можно также манипулировать затемнением эффекта затухания? Он использует класс RGBMood для создания сочетания цветов HSB.
- Реализовать связь Visible Light с помощью Arduino
- 4-битный счетчик вверх и вниз
- Скетч мигания ESP8266 не мигает светодиодом
- Pro Micro ATMEGA32U4 не может загрузить
- Акцептант векселей ИКТ
- Отдельный ATmega 2560 - включение одного светодиода - устранение неполадок
- В подтверждение этого светодиод будет мигать с заданной частотой
- Как запустить 4 светодиода последовательно на основе кнопочного входа?
Что не так с яркостью?, @geometrikal
не могу настроить яркость светодиодов. Возможно, мне следует использовать выражение «тусклый» вместо «яркость», чтобы было более понятно. Если я установлю цвет КРАСНЫЙ, я не смогу увеличить или уменьшить его яркость, то же самое относится и к ЗЕЛЕНОМУ и СИНЕМУ., @Stathis Ntonas
Никакая «яркость» не была ясна, я просто не мог понять, что не работает из вашего вопроса. :П, @geometrikal