Управление светодиодной лентой через последовательный монитор
Я изо всех сил пытался написать код для Arduino UNO, чтобы я мог использовать свой телефон и менять цвет светодиодной ленты через терминал.
#include <FastLED.h>
#include <SoftwareSerial.h>
SoftwareSerial btSerial(2, 4); // RX, TX
#define NUM_LEDS 22
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
void setup() {
btSerial.begin(9600);
btSerial.println("Connected to Arduino");
FastLED.addLeds<WS2812, DATA_PIN>(leds, NUM_LEDS);
}
char a;
void loop()
{
if (btSerial.available())
{
a= (char)btSerial.read();
if(a=="b")
{
btSerial.println("Turning LED blue");
leds[0] = CRGB::Blue; // Turns 1 LED to blue
FastLED.show();
}
}
}
По сути, я хотел бы иметь возможность менять цвета светодиодов на своем телефоне. Если вы введете «r», светодиоды станут красными, если вы введете «b», светодиоды станут синими и т. Д. Возможно, даже добавите некоторые шаблоны. Регулятор яркости тоже не помешал бы, чтобы сэкономить заряд батареи.
ОТРЕДАКТИРОВАНО. Серийные работы.
#include <FastLED.h>
#include <SoftwareSerial.h>
SoftwareSerial btSerial(2, 4); // RX, TX
#define NUM_LEDS 22
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
btSerial.begin(9600);
btSerial.println("Connected to Arduino");
FastLED.addLeds<WS2812, DATA_PIN>(leds, NUM_LEDS);}
char a;
void loop(){
if (btSerial.available())
Serial.write(btSerial.read());
if (Serial.available())
btSerial.write(Serial.read());}
3.
#include <FastLED.h>
#include <SoftwareSerial.h>
SoftwareSerial btSerial(2, 4); // RX, TX
#define NUM_LEDS 22
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
btSerial.begin(9600);
btSerial.println("Connected to Arduino");
FastLED.addLeds<WS2812, DATA_PIN>(leds, NUM_LEDS);}
char a;
void loop(){
if (btSerial.available())
Serial.write(btSerial.read());
if (Serial.available())
btSerial.write(Serial.read());}
if (a=='b'){
btSerial.println("Turning LED blue");
leds[0] = CRGB::Blue;
FastLED.show();}
ПОСЛЕДНИЕ:
#include <FastLED.h>
#include <SoftwareSerial.h>
SoftwareSerial btSerial(2, 4); // прием, передача
#define NUM_LEDS 28
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
void setup()
{
Serial.begin(9600);
btSerial.begin(9600);
btSerial.println("Connected to Arduino");
FastLED.addLeds<WS2812, DATA_PIN>(leds, NUM_LEDS);
}
char a;
void loop()
{
if (btSerial.available())
{
a= (char)btSerial.read();
if( a == 'b' )
{
btSerial.println("Sinine"); //Все светодиоды синие
fill_solid( leds, NUM_LEDS, CRGB::Blue);
FastLED.show();
}
if( a == 'r' )
{
btSerial.println("Punane"); //Все светодиоды красные
fill_solid( leds, NUM_LEDS, CRGB::Green);
FastLED.show();
}
if( a == 'g' )
{
btSerial.println("Roheline"); //Все светодиоды зеленые
fill_solid( leds, NUM_LEDS, CRGB::Red);
FastLED.show();
}
if( a == 'y' )
{
btSerial.println("Sinine"); //Все светодиоды желтые
fill_solid( leds, NUM_LEDS, CRGB::Yellow);
FastLED.show();
}
if( a == 'w' )
{
btSerial.println("Sinine"); //Все светодиоды белые
fill_solid( leds, NUM_LEDS, CRGB::White);
FastLED.show();
}
if( a == 'o' )
{
btSerial.println("Väljas"); //Все светодиоды выключены
fill_solid( leds, NUM_LEDS, CRGB::Black);
FastLED.show();}
if ( a == 'z' ) //1 синий светодиод от начала до конца
{
int i= 2;
while (i > 0)
{
for (int dot = 0; dot < NUM_LEDS; dot++)
{
leds[dot] = CRGB::Blue;
FastLED.show();
leds[dot] = CRGB::Black;
delay(100);
}
}
}
if ( a == 'x' ) //1 красный светодиод от начала до конца
{
int i= 2;
while (i > 0)
{
for (int dot = 0; dot < NUM_LEDS; dot++)
{
leds[dot] = CRGB::Green;
FastLED.show();
leds[dot] = CRGB::Black;
delay(100);
}
}
}
}
}
@Janar, 👍0
Обсуждение1 ответ
Лучший ответ:
Похоже, вам не хватает базового понимания того, как работает последовательная (UART) связь. Поэтому я объясню основные принципы. Оттуда вы сможете реализовать то, что хотите.
Последовательный (он же UART) передает данные последовательно, байт за байтом (отсюда и название). Когда вы вводите текст в Serial Monitor Arduino IDE и отправляете его, вы не можете повлиять на то, когда именно будет передан каждый байт. Поскольку интерфейс UART не знает сообщений или «фрагментов данных», только байты, он будет передавать каждый байт, когда он будет готов. Между байтами может быть короткая пауза. Это важно знать, если вы хотите реализовать команды длиннее 1 байта.
Обычный интерфейс Последовательный
в основном реализован на аппаратном уровне Uno, поэтому он не так сильно зависит от запущенного программного обеспечения. SoftwareSerial
выполняет всю тяжелую коммуникационную работу в программном обеспечении, поэтому он имеет некоторые оговорки (блокировка операций записи, более ограниченная скорость передачи данных, возможность одновременного приема только на одном интерфейсе SoftwareSerial
, ...). Но оба в основном используют один и тот же интерфейс кода.
Serial.available()
возвращает количество полученных байтов, которые все еще находятся во внутреннем буфере. Вы уже используете это только для чтения из буфера, когда в нем действительно есть данные для чтения (с оператором if). Затем вы читаете один байт из буфера с помощью Serial.read()
. В настоящее время вы передаете возвращаемое значение (прочитанные данные) непосредственно другому последовательному интерфейсу для отправки. Таким образом, значение не сохраняется нигде в вашем скетче. Выполнение Serial.read()
удалит прочитанный байт из буфера и вернет его. Таким образом, прочитанный байт больше не будет находиться в буфере.
Код с двумя операторами if и последовательными функциями в основном используется для пересылки данных между двумя последовательными интерфейсами. Для вашего варианта использования вам это не нужно. Вместо этого вы должны прочитать данные в локальную переменную, как вы сделали в своем первом скетче:
if (btSerial.available())
{
a= (char)btSerial.read();
if(a=="b")
{
btSerial.println("Turning LED blue");
leds[0] = CRGB::Blue; // превращает 1 светодиод в синий
FastLED.show();
}
}
Здесь вы сначала проверяете, есть ли данные для чтения в буфере btSerial
. Если да, вы читаете его в переменную a
. Эта переменная теперь содержит один символ. Если вы также хотите перенаправить этот символ в Serial
, теперь вы можете использовать для этого Serial.write(a);
. Затем вы хотите проверить значение полученного символа. Здесь мы делаем небольшой экскурс:
В C/C++ используются 2 разных типа кавычек: двойные кавычки "
и одинарные кавычки '
. Двойные кавычки обозначают строковые литералы, состоящие из ряда символов. Одинарные кавычки отмечают односимвольные значения - только один символ. В вашем операторе if вы проверяете равенство. Если вы задумаетесь об этом, вы увидите, что проверка равенства двух одиночных символов намного проще, чем проверка двух строк равны (проверка 1 символа с каждой стороны по сравнению с проверкой нескольких символов с каждой стороны). Таким образом, это разница, если вы сравниваете строковые литералы или отдельные символы. Сравнение односимвольной переменной со строковым литералом не работает - они два совершенно разные вещи. Вместо этого вы должны сравнить символьную переменную с одним символом:
if( a == 'b' )
Поскольку вы будете добавлять больше команд в свой проект, вы увидите, что операторы if не очень хорошо упорядочивают код. В этом случае оператор switch лучше:
switch(a){
case 'b':
// Делаем здесь то, что хотим со светодиодами
break;
case 'c':
...
break;
}
Это выполнит соответствующую часть кода в зависимости от значения a
. Подробнее об этой конструкции можно прочитать в Интернете (погуглите что-нибудь вроде "переключатель C").
Теперь вы должны уметь реализовывать в своем коде простые 1-байтовые/символьные команды. Также просмотрите и поймите примеры из Arduino IDE о последовательном интерфейсе.
Если вам нужны более сложные команды (возможно, с некоторыми полезными данными в дополнение к команде), вы должны ввести протокол связи в последовательный интерфейс. Самый простой способ — определить целые сообщения, используя символ-разделитель в конце каждого сообщения. В основном для этой цели используется символ новой строки '\n'
. Вы в основном читаете данные из Serial и сохраняете их в char
-array/string, пока не получите символ новой строки. Тогда вы знаете, что получили полное сообщение, и можете приступить к его обработке в целом. Закончив, вы очищаете буфер сообщений и снова ждете нового сообщения. Чтобы это работало, вы, конечно, должны убедиться, что символ-разделитель никогда не является частью ваших данных отправки (так как код будет думать, что он отмечает конец сообщения).
Вы можете увидеть это в примере SerialEvent
в Arduino IDE. Попытайтесь понять, что там происходит. В Интернете также есть множество руководств.
Надеюсь, я смог вас немного просветить. Удачи в вашем проекте.
Большое спасибо Крис! Получил работу. Сейчас работаю над разными шаблонами и делаю приложение для телефона. Заработали основные цвета., @Janar
Если вы считаете, что мой ответ был правильным, вы можете отметить его как правильный ответ. Так другие узнают, что этот вопрос решен. Спасибо, @chrisl
Отредактировал код. Теперь я могу управлять обычными цветами через приложение для телефона, которое я сделал сам. Теперь у меня трудности с созданием более интересных узоров. Мне удалось сделать цикл while внутри void loop(), но цикл не закончится. Мне предложили добавить еще один цикл в цикл while, но я не уверен, как это должно выглядеть. Решил не использовать оператор switch, поскольку в настоящее время все работает нормально (если только это не требуется для работы других шаблонов). Ура, очень ценю помощь до сих пор., @Janar
Удалены строки "int i= 2;" и «пока (i > 0)» заменил его на «пока (!btSerial.available())», теперь он работает отлично. :), @Janar
Поэтому, когда я отправляю что-либо в последовательный порт, цикл while останавливается., @Janar
- Библиотека FastLED: Как настроить яркость одного пикселя в абсолютном масштабе?
- Управлять несколькими полосками WS2812B с разным количеством светодиодов.
- Адресная RGB-полоса работает по отдельности, но не может настроить все светодиоды на полностью белый цвет.
- Светодиодная лента WS2812B + First Pixel продолжает ломаться
- ESP32 + Фастлед + WS2801
- FastLED fill_rainbow - Неожиданный красный пиксель
- Использование аккумуляторов 18650 с повышающим преобразователем 3,7 В в 5 В.
- Нужно ли подключать светодиодную ленту WS2812 «последовательно», если я хочу адресовать каждый светодиод отдельно?
А в чем именно ваш вопрос? Ваш код не включает в себя много серийного материала. Хотите знать, как читать из Serial? Тогда вы просмотрели кучу руководств внутри Arduino IDE или в Интернете? Или у вас проблемы со светодиодами? Затем, пытались ли вы использовать и понимать примеры, которые поставляются с библиотекой FastLED? В настоящее время неясно, в чем именно ваша проблема, @chrisl
Вы так и не задали настоящего вопроса, поэтому мы не знаем, в чем проблема с вашим кодом. Кстати: вы можете попробовать заменить двойные кавычки в своем операторе if одинарными кавычками, поскольку здесь вы хотите сравнить одиночные символы (которые представлены одинарными кавычками вокруг одного символа), а не строковые литералы (которые представлены двойными кавычки вокруг нескольких символов)., @chrisl
Мне нужно, чтобы серийный номер работал, прямо сейчас он ничего не дает мне, когда я печатаю на своем телефоне., @Janar
Я удалил кое-что и заработал серийный номер. Не уверен, например, как я читаю то, что набираю с телефона, а затем превращаю их в команды if., @Janar
Я вижу сообщения в обоих направлениях. Не уверен, как поместить это в код. «Если этот (конкретный текст, например, «r» набирается в серийный номер через телефон, светодиоды меняют цвет на красный)»., @Janar
Это зависит от ваших потребностей. Для очень простых команд достаточно 1 байта/символа, и ваш первый код был неплохим началом для этого. Если вам нужны более сложные команды, вы можете посмотреть пример SerialEvent в Arduino IDE. Он использует символ новой строки в качестве разделителя сообщений., @chrisl
Обновленный код. Как бы вы определили «а» как то, что вводится в серийный номер? Прямо сейчас код не знает, что такое «а»., @Janar
у вас уже есть это в первом скетче .... кстати, не используйте имена переменных, такие как
a
, потому что это не описательное имя .... используйте что-то вродеbtData
илиbtChar
илиbtCmd
иликоманда
и т. д., @jsotola