Обрезается вывод текста на дисплей ILI9341 при приеме по Serial
- Войдите на сайт для отправки комментариев
Сб, 15/01/2022 - 15:30
//Для ARDUINO PRO or PRO mini
//Vcc=5,0 V
//Gnd=0.0 V
#define CS 10
#define RST -1 // Или на RES или на 3.3v
#define DC 9 //По умолчанию
#define MOSI 11 // По умолчанию
#define SCLK 13 // по умолчанию
//Led=5.0 V
#define MISO -1 // Не используется
#define BLACK 0x0000
#include <SPI.h>
#include "PDQ_GFX.h"
#include "PDQ_ILI9341_config.h"
#include "PDQ_ILI9341.h"
PDQ_ILI9341 tft;
#include "FontsRus/TimesNRCyr16.h"
String str = "";
long timer;
void setup() {
Serial.begin(9600);
Serial.setTimeout(128);
tft.begin();
tft.setRotation(-1);
tft.fillScreen(BLACK);
tft.setTextSize(1);
tft.setFont(&TimesNRCyr16pt8b);
pinMode (2, INPUT);
};
void loop(){
if(digitalRead(2)==0){
str =Serial.readStringUntil('\n');
if(str !=0){
tft.fillScreen(BLACK);
tft.setCursor(9, 26);
tft.print(str);
str = "";
}
}
//Если вставить код, который ниже, тогда при приеме через аппаратный Serial
русского текста этот текст выводиться только частично .
while (millis() <= (timer + 1000)) { };
timer = millis();
};
// while (millis() <= (timer + 1000)) { }; // timer = millis();,на экран выводиться весь текст ,
А зачем тебе пустой цикл?
Сам по себе пустой цикл в этом примере ни на что не влияет, он как пример. На самом деле, в этом скетче, вместо этого цикла работают часы на i2c (DS3231) , а этот цикл просто его заменяет. Но даже с этим пустым циклом ,на дисплей не выводится весь текст(русский).
Ты понимаешь, что код с пустым циклом полностью блокирует дальнейшую работу программы? Выкладывай весь код как есть, а не пустые циклы. Сейчас будем одно решать, а по факту другое нужно будет. Это лишняя работа.
Или код сверхсекретный?)
Как добиться полного отображения текста?
Или убрать этот цикл нахрен, или добавить в него обработку приведших символов. Можно ещё увеличить буфер, но это говнокостыль. Он там достаточный и при правильном обращении его увеличивать не нужно.
Проблема в том, что пока Ваш цикл ничего не делает, символы приходят, буфер переполняется и символы теряются.
Да код то не секретный
#define BLACK 0x0000 /* 0, 0, 0 */ #define NAVY 0x000F /* 0, 0, 128 */ #define DARKGREEN 0x03E0 /* 0, 128, 0 */ #define DARKCYAN 0x03EF /* 0, 128, 128 */ #define MAROON 0x7800 /* 128, 0, 0 */ #define PURPLE 0x780F /* 128, 0, 128 */ #define OLIVE 0x7BE0 /* 128, 128, 0 */ #define LIGHTGREY 0xC618 /* 192, 192, 192 */ #define LIGHTGREY_1 0x630C /* 192, 192, 192 */ #define DARKGREY 0x7BEF /* 128, 128, 128 */ #define BLUE 0x001F /* 0, 0, 255 */ #define GREEN 0x07E0 /* 0, 255, 0 */ #define CYAN 0x07FF /* 0, 255, 255 */ #define RED 0xF800 /* 255, 0, 0 */ #define MAGENTA 0x630C /* 255, 0, 255 */ #define YELLOW 0xFFE0 /* 255, 255, 0 */ #define WHITE 0xFFFF /* 255, 255, 255 */ #define ORANGE 0xFD20 /* 255, 165, 0 */ #define GREENYELLOW 0xAFE5 /* 173, 255, 47 */ #define PINK 0xF81F #define CREF_BACKGROUND BLACK #define FACE ORANGE #define CREF_SECOND RED #define CREF_MINUTE CYAN #define CREF_HOUR CYAN #define NUMERIC_POINT WHITE #define CREF_HELLO RED #define CREF_TEXT DARKCYAN #define CREF_TEXT_BRAND ORANGE #define CREF_DATE MAGENTA #define CREF_TIME GREENYELLOW //Для ARDUINO PRO or PRO mini //Vcc=5,0 V //Gnd=0.0 V #define CS 10 #define RST -1 // Или на RES или на 3.3v #define DC 9 //По умолчанию #define MOSI 11 // По умолчанию #define SCLK 13 // по умолчанию //Led=5.0 V #define MISO -1 // Не используется #include <SPI.h> #include <Wire.h> #include "Sodaq_DS3231.h" #include "PDQ_GFX.h" #include "PDQ_ILI9341_config.h" #include "PDQ_ILI9341.h" PDQ_ILI9341 tft; #include "FontsRus/TimesNRCyr16.h" #include <Fonts/FreeSansBold18pt7b.h> int h = 0; // hour int m = 0; // minute int s = 0; // second int old_h = 0; // previous hour int old_m = 0; // previous minute int old_s = 0; // previous second long timer; // 1 second count variable String str = ""; void setup() { Serial.begin(9600); Serial.setTimeout(128); Wire.begin(); rtc.begin(); tft.begin(); tft.setRotation(-1); tft.fillScreen(BLACK); tft.setTextSize(1); tft.setFont(&FreeSansBold18pt7b); tft.setCursor(9, 26); tft.print("Hello"); pinMode (2, INPUT); }; void loop(){ if(digitalRead(2)==0){ str =Serial.readStringUntil('\n'); if(str !=0){ tft.fillScreen(BLACK); tft.setTextSize(1); tft.setFont(&TimesNRCyr16pt8b); tft.setTextColor(WHITE); tft.setCursor(9, 26); tft.print(str); str = ""; } }; DateTime now = rtc.now(); h = now.hour(); m = now.minute(); s = now.second(); tft.setFont(&TimesNRCyr16pt8b); tft.setTextColor(YELLOW); tft.setTextSize(2); if (old_h == 23 && h == 0) { old_h = 0; tft.fillRect(26, 82, 80, 54, 0); } if (h > old_h) { tft.fillRect(26, 82, 80, 54, 0); old_h = h; } tft.setCursor(26, 130); if (h <= 9){ tft.print("0"); } tft.print(h); tft.print(":"); if (old_m == 59 && m == 0) { old_m = 0; tft.fillRect(120, 82, 80, 54, 0); } if (m > old_m) { tft.fillRect(120, 82, 80, 54, 0); old_m = m; } if (m <= 9) { tft.print("0");} tft.print(m); tft.print(":"); tft.fillRect(212, 82, 80, 54, 0); if (old_s == 59 && s == 0) { old_s = 0; old_s = s; } if (s <= 9){ tft.print("0");} tft.print(s); tft.println(""); while (millis() <= (timer + 1000)) { }; timer = millis(); };Вот именно что при if(digitalRead(2)==0){
.... в это время и принимаю текст
}
все равно текст выводится не полностью.
Специально слежу, в мониторе порта он читается полностью.
так все равно в коде пустой цикл в строке 140, который точно так же нарушает прием символов в сериал. Уберите его - без него будет работать?
и строчка 86 чтения из порта тоже блокирующая... Две блокирующие операции в одном цикле? -они не могут работать вместе.
Как добиться полного отображения текста?
Или убрать этот цикл нахрен, или добавить в него обработку приведших символов. Можно ещё увеличить буфер, но это говнокостыль. Он там достаточный и при правильном обращении его увеличивать не нужно.
Проблема в том, что пока Ваш цикл ничего не делает, символы приходят, буфер переполняется и символы теряются.
Добавил стороку if(digitalRead(2)==0 && Serial.available()>0){
лучше не стало.
//Для ARDUINO PRO or PRO mini //Vcc=5,0 V //Gnd=0.0 V #define CS 10 #define RST -1 // Или на RES или на 3.3v #define DC 9 //По умолчанию #define MOSI 11 // По умолчанию #define SCLK 13 // по умолчанию //Led=5.0 V #define MISO -1 // Не используется #define BLACK 0x0000 #include <SPI.h> #include "PDQ_GFX.h" #include "PDQ_ILI9341_config.h" #include "PDQ_ILI9341.h" PDQ_ILI9341 tft; #include "FontsRus/TimesNRCyr16.h" String str = ""; long timer; void setup() { Serial.begin(9600); Serial.setTimeout(128); tft.begin(); tft.setRotation(-1); tft.fillScreen(BLACK); tft.setTextSize(1); tft.setFont(&TimesNRCyr16pt8b); pinMode (2, INPUT); }; void loop(){ if(digitalRead(2)==0 && Serial.available()>0 ){ str =Serial.readStringUntil('\n'); if(str !=0){ tft.fillScreen(BLACK); tft.setCursor(9, 26); tft.print(str); str = ""; } } //Если вставить код, который ниже, тогда при приеме через аппаратный Serial //русского текста этот текст выводиться только частично . while (millis() <= (timer + 1000)) { }; timer = millis(); };Добавил стороку if(digitalRead(2)==0 && Serial.available()>0){
хм.... вы правда идиот или прикидываетесь? Вам куда сказали добавить обработку символов? - внутрь цикла while! - а вы куда добавили?
так все равно в коде пустой цикл в строке 140, который точно так же нарушает прием символов в сериал. Уберите его - без него будет работать?
и строчка 86 чтения из порта тоже блокирующая... Две блокирующие операции в одном цикле? -они не могут работать вместе.
Так как раз 86 строка и выводит текст , который мне и нужен.
Строку 140 закомментировал - теперь секунды мечутся, а выводимый текст теряется .
Так как раз 86 строка и выводит текст , который мне и нужен.
readStringUntil - не единственный оператор, который может читать из Сериал. И как раз в вашем случае этот оператор не подходит, потому что он блокирующий. Вам надо заменить readStringUntil на обычный read(), читать из порта посимвольно и самому проверять пришедший символ на равенство символу /n.
Строчка - это первое. А вторая ваша ошибка - тот самый цикл while. Зачем он нужен, чтобы данные на дисплей выводились точно раз в секунду, я угадал? - но делаете вы это неправильно, так миллис только чайники используют. Ваш цикл вставляет блокирующую задержку до конца след. секунды, не давая программе принимать символы. Вместо блокирования программы на время до конца секунды надо просто обновлять дисплей раз в секунду, а все остальное время прием из Сериал должен работать.
Добавил обработку в while
//Для ARDUINO PRO or PRO mini //Vcc=5,0 V //Gnd=0.0 V #define CS 10 #define RST -1 // Или на RES или на 3.3v #define DC 9 //По умолчанию #define MOSI 11 // По умолчанию #define SCLK 13 // по умолчанию //Led=5.0 V #define MISO -1 // Не используется #define BLACK 0x0000 #include <SPI.h> #include "PDQ_GFX.h" #include "PDQ_ILI9341_config.h" #include "PDQ_ILI9341.h" PDQ_ILI9341 tft; #include "FontsRus/TimesNRCyr16.h" String str = ""; long timer; void setup() { Serial.begin(9600); Serial.setTimeout(128); tft.begin(); tft.setRotation(-1); tft.fillScreen(BLACK); tft.setTextSize(1); tft.setFont(&TimesNRCyr16pt8b); pinMode (2, INPUT); }; void loop(){ // if(digitalRead(2)==0 && Serial.available()>0 ){ // str =Serial.readStringUntil('\n'); // if(str !=0){ // tft.fillScreen(BLACK); // tft.setCursor(9, 26); // tft.print(str); // str = ""; // } // } //Если вставить код, который ниже, тогда при приеме через аппаратный Serial //русского текста этот текст выводиться только частично . while (millis() <= (timer + 1000)) { if(digitalRead(2)==0 ){ str =Serial.readStringUntil('\n'); if(str !=0){ tft.fillScreen(BLACK); tft.setCursor(9, 26); tft.print(str); str = ""; } } }; timer = millis(); };Текст не теряется. Оригинально.Спасибо.
Текст не теряется. Оригинально.Спасибо.
все равно может теряться. От readStringUntil избавляйтесь
Текст не теряется. Оригинально.Спасибо.
все равно может теряться. От readStringUntil избавляйтесь
Попробую уже на реальном проекте адаптировать эту возможность(принимать текст).
Надо .что бы и часы ходили , и чтоб в любой момент была возможность принять текст.
Спасибо за подсказки.
Попробую уже на реальном проекте адаптировать эту возможность(принимать текст).
Надо .что бы и часы ходили , и чтоб в любой момент была возможность принять текст.
Спасибо за подсказки.
когда вы ставите прием символов внутрь while, как в последнем коде - у вас длина цикла зависит от времени приема символов и может быть не точно 1 сек, а больше. Наверно для часов это не очень хорошо, но решать вам.
Не, тут все нормально . Времени на передачу текста хватает , сбоев не наблюдается. Испытывал много раз, пока что без сбоев. Текст приходит полностью.
Странно, что никто не предложил увеличить буфер Serial'a.
Хотя нет, предлагали.
Впрочем ТСа устраивает и его костыль , пусть радуется(до поры до времени)
наверно и 45 строку надо тоже исправить...
while (millis() <= (timer + 1000)) { while (millis() - timer <= 1000) {наверно и 45 строку надо тоже исправить...
while (millis() <= (timer + 1000)) { while (millis() - timer <= 1000) {Исправить бы не сложно, другое дело, хотябы правильно _как нужно? Просто много об этом подсказывают, но не говорят, все же как правильно. Встречаются многие примеры и это путает_все же правильнее как?
Правильнее вычитать, это «обход» переполнения millis().
Исправить бы не сложно, другое дело, хотябы правильно _как нужно?
http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
uint16_t period =1000;// переменная периода unsigned long timer; // Сделал без знаковой переменную timer void setup () { .....Инициализация } void loop () { ...........Выполняем while (millis() - timer <=period ) { ......Мои действия } timer = millis(); } //Ну и сделал костыль в HardwareSerial.h //Вписав увеличенный размер буфера //#define SERIAL_TX_BUFFER_SIZE 128 //#define SERIAL_RX_BUFFER_SIZE 128 Прислушавшись к рекомендациям, увеличил размер буфера Serial и теперь от millis() вычитается переменная timer=Прислушавшись к рекомендациям, увеличил размер буфера Serial и теперь от millis() вычитается переменная timer=
Исправить бы не сложно, другое дело, хотябы правильно _как нужно?
http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis
По этой ссылке - конкретный уже ответ, изучаю...