Помогите доработать функцию
- Войдите на сайт для отправки комментариев
Втр, 19/04/2022 - 17:09
Добрый день!
Помогите плез доработать функцию бегущей строки на светодиодной адресной матрице!
Суть в том, что в программировании очень слаб, проект для личного пользования. Есть функция вывода бегущей строки - runText. В Loop - прописано условие приема кода с ИК пульта (т.е. если пришел нужный HEX код - запускаем runText). Проблема в том, что при нажатии на кнопку пульта - функция выполняется 1 раз, т.е. текст смещается ровно на 1 пиксель. А надо чтоб надпись проигралась до конца, и только потом ловила следующий код с пульта. Пытался играть с While - но происходит полная ерунда...
#include <FastLED.h> #include "font.h" #include <IRremote.h> // подключаем библиотеку для IR приемника #define DATA_PIN 2 #define NUM_LEDS 256 #define MATRIX_WIDTH 32 #define MATRIX_HEIGHT 8 #define BRIGHTNESS 200 IRrecv irrecv(11); // указываем пин, к которому подключен IR приемник decode_results results; //константы и переменные для работы с текстом const String fontNumStr="0123456789 !,.:;?"; const String fontLetStr="АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; uint16_t curPixel; uint8_t curX; uint8_t curY; unsigned long timer; CRGB leds[NUM_LEDS]; //переменные для работы с бегущей строкой uint16_t lineStart=0;//с какого столбца строки начинаем вопроизведение текста uint16_t lineFin=0;//каким столбцом строки заканчиваем вопроизведение текста uint8_t startRunLineX=MATRIX_WIDTH-1;//столбец X начала отрисовки бегущей строки void setup() { irrecv.enableIRIn(); // запускаем прием инфракрасного сигнала FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(BRIGHTNESS);//0-255 Serial.begin (9600); //вывод статического текста //showText("123", 2, 0, 0xFF0000); //showText("АБВГ", 0, 8, 0x0000FF); FastLED.show(); } void loop() { if ( irrecv.decode( &results )) { // если данные пришли Serial.println(results.value, HEX); switch ( results.value ) { case 0xFFA25D: runText("СПАСИБО!", 0, 0x32CD32, 50); break; case 0xE318261B: runText("СПАСИБО!", 0, 0x32CD32, 50); break; case 0xFF629D: runText("КОШМАР!!", 0, 0xFF8C00, 50); break; case 0x462CAD38: runText("КОШМАР!!", 0, 0xFF8C00, 50); break; case 0x511DBB: runText("КОШМАР!!", 0, 0xFF8C00, 50); break; case 0xFF: results.value=0; break; } irrecv.resume(); // принимаем следующую команду } } void setPixel (byte x, byte y, uint32_t color) { uint16_t curLed; if (x%2==0){ curLed=MATRIX_HEIGHT*x+y; } else { curLed=(MATRIX_HEIGHT*(x+1)-1)-y; } leds[curLed]=color; } byte getPixel (uint8_t vertPixels, byte startY, uint32_t color) { byte pixel; for (int k = 7; k >=0; k--) {// pixel = ((vertPixels >> k) & 0x01); if (pixel==1){ setPixel (curX, curY, color); } curY++; } curY=startY; curX++; } void showText(String text, byte startX, byte startY, uint32_t color){//вывод статического текста int i; byte n; bool isRusLetter=false; byte vertPixels; curX=startX; curY=startY; for (i=0;i<text.length();i++){ if (int(text[i])>=0){//цифры и символы n=fontNumStr.indexOf(text[i]); for (byte j=0;j<4;j++){ vertPixels=pgm_read_byte(&(font7num[n][j])); if ((j==0)||(vertPixels>0)){//только первая колонка и не пустые колонки getPixel (vertPixels, startY, color); } if (curX>=MATRIX_WIDTH) { break; } } curX++; if (curX>=MATRIX_WIDTH) { break; } } else {//русские буквы if (isRusLetter==true){ isRusLetter=false; n=112+int(text[i]); for (byte j=0;j<7;j++){ vertPixels=pgm_read_byte(&(font7let[n][j])); if ((j==0)||(vertPixels>0)||((n==27)&&(j<6))){//только первая колонка, не пустые колонки и исключения буквы Ы getPixel (vertPixels, startY, color); } if (curX>=MATRIX_WIDTH) { break; } } curX++; if (curX>=MATRIX_WIDTH) { break; } } else { isRusLetter=true; } } } } void runText(String text, byte startY, uint32_t color, int speedText){//вывод бегущей строки int i; byte n; bool isRusLetter=false; byte vertPixels; curY=startY; curX=startRunLineX; FastLED.clear(); int l=0; for (i=0;i<text.length();i++){ if (int(text[i])>0){ n=fontNumStr.indexOf(text[i]); for (byte j=0;j<4;j++){ vertPixels=pgm_read_byte(&(font7num[n][j])); if ((j==0)||(vertPixels>0)){//только первая колонка и не пустые колонки if ((l>=lineStart)&&(l<=lineFin)){ getPixel (vertPixels, startY, color); } l++; } if (j==3){//в конце каждого символа добавляем пробел if ((l>=lineStart)&&(l<=lineFin)){ curX++; } l++; } } } else { if (isRusLetter==true){ isRusLetter=false; n=112+int(text[i]); for (byte j=0;j<7;j++){ vertPixels=pgm_read_byte(&(font7let[n][j])); if ((j==0)||(vertPixels>0)||((n==27)&&(j<6))){//только первая колонка, не пустые колонки или буква Ы if ((l>=lineStart)&&(l<=lineFin)){ getPixel (vertPixels, startY, color); } l++; } if (j==6){//в конце каждого символа добавляем пробел if ((l>=lineStart)&&(l<=lineFin)){ curX++; } l++; } } } else { isRusLetter=true; } } } lineFin++; if (lineFin>=MATRIX_WIDTH) { lineStart++; } if (startRunLineX>0){//каждый кадр смещаем начало отрисовки бегущей строки на 1 пиксель влево от правого края матрицы startRunLineX--; } /* if (lineStart>l){//воспроизводим с начала l=0; lineStart=0; lineFin=0; startRunLineX=MATRIX_WIDTH-1; }*/ FastLED.show(); delay(speedText); }
Одного цикла не хватает внутри runtext. Без номеров строк хз как ориентироваться.
Вставляйте программу с номерами строк, чтобы было на что ссылаться
(компилировать не пробовал)
А чем библиотека Adafruit_NeoMatrix не угодила ?
Теперь к тексту - у Вас задокументирована строка 217, которая возвращает значение startRunLineX в изначальное состояние, когда цикл вывода прошел.
Далее - 209 строка, как я понимаю, должна зацикливать воспроизведение, пока startRunLineX>0, а у Вас там стоит if. Подумайте над do{}while()
(компилировать не пробовал)
Только после
} while ((--startRunLineX) > 0);
Надо поставить
startRunLineX=MATRIX_WIDTH-1;
Но ,по моему, это глупость делать эту переменную глобальной. Ее надо сделать статичной, а в подпрограмме ввести локальную переменную.
Да - я уже подправил.
Плюс скорее всего надо еще добавить одно гашение ленты через какой то промежуток времени.
Хм... Все начало вести себя вроде лучше, но странно.
При нажатии на нужную клавишу - надпись пробегает, но не до уходит до конца. А останавливается, когда первая буква достигла конца ленты. Т.е. не уходит дальше.
И после нажатия кнопки - ардуино очень долго не воспринимает сигналы с пульта, ловля какие-то дребезги и прочее.. Сижу пока думаю...
А бог его знает. Поставьте в 224 строку
Serial.println(startRunLineX);
и посмотрите чего там творится
Значит по осям могут быть и отрицательные числа !
https://wokwi.com/projects/329525261530825299
У вас строка объявления матрицы скорее всего будет выглядеть так:
Доходит до 6-8 строчки и выдает такую прелесть:
⸮⸮⸮Q)7⸮⸮⸮⸮⸮⸮Xv,*⸮.⸮J⸮⸮⸮/a⸮R⸮⸮b⸮c١⸮⸮⸮6⸮⸮⸮⸮E⸮⸮+⸮⸮⸮$⸮⸮ ⸮⸮⸮&b
Дальше на команды не реагирует