Обрезается вывод текста на дисплей ILI9341 при приеме по Serial

ua4lcn
Offline
Зарегистрирован: 27.02.2016
  //Для 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();

         };

 

ua4lcn
Offline
Зарегистрирован: 27.02.2016
Если вставить код:
  while (millis() <= (timer + 1000))  { };   
  timer = millis();
 тогда, при приеме через аппаратный Serial
русского текста, этот текст выводиться только частично .
Было подсчитано, что на экран выводится  не более 99 символов.
Это примерно 45-46 букв русского алфавита и плюс несколько пробелов.
Закомментировав эти две строчки
 
//  while (millis() <= (timer + 1000))  { };   
//  timer = millis(); 

,на экран выводиться весь текст ,

т.е я могу посылать более 250 символов. 
Как добиться полного отображения текста?
 
BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А зачем тебе пустой цикл?

ua4lcn
Offline
Зарегистрирован: 27.02.2016

Сам по себе пустой цикл в этом примере ни на что не влияет, он как пример. На самом деле, в этом скетче, вместо этого цикла работают часы на i2c (DS3231) , а этот цикл просто его   заменяет. Но даже с этим пустым циклом ,на дисплей не выводится весь текст(русский).  

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Ты понимаешь, что код с пустым циклом полностью блокирует дальнейшую работу программы? Выкладывай весь код как есть, а не пустые циклы. Сейчас будем одно решать, а по факту другое нужно будет. Это лишняя работа.

Или код сверхсекретный?)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua4lcn пишет:

Как добиться полного отображения текста?

Или убрать этот цикл нахрен, или добавить в него обработку приведших символов. Можно ещё увеличить буфер, но это говнокостыль. Он там достаточный и при правильном обращении его увеличивать не нужно.

Проблема в том, что пока Ваш цикл ничего не делает, символы приходят, буфер переполняется и символы теряются.

ua4lcn
Offline
Зарегистрирован: 27.02.2016

 Да код  то не секретный 

#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){ 

.... в это время и принимаю текст

}

все равно текст выводится не полностью.

Специально слежу, в мониторе порта он читается полностью.

 

b707
Offline
Зарегистрирован: 26.05.2017

так все равно в коде пустой цикл в строке 140, который точно так же нарушает прием символов в сериал. Уберите его - без него будет работать?

и строчка 86 чтения из порта тоже блокирующая... Две блокирующие операции в одном цикле? -они не могут работать вместе.

ua4lcn
Offline
Зарегистрирован: 27.02.2016

ЕвгенийП пишет:

ua4lcn пишет:

Как добиться полного отображения текста?

Или убрать этот цикл нахрен, или добавить в него обработку приведших символов. Можно ещё увеличить буфер, но это говнокостыль. Он там достаточный и при правильном обращении его увеличивать не нужно.

Проблема в том, что пока Ваш цикл ничего не делает, символы приходят, буфер переполняется и символы теряются.

Добавил стороку 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();
 };

 

b707
Offline
Зарегистрирован: 26.05.2017

ua4lcn пишет:

Добавил стороку if(digitalRead(2)==0 && Serial.available()>0){

хм.... вы правда идиот или прикидываетесь? Вам куда сказали добавить обработку символов? - внутрь цикла while! - а вы куда добавили?

ua4lcn
Offline
Зарегистрирован: 27.02.2016

b707 пишет:

так все равно в коде пустой цикл в строке 140, который точно так же нарушает прием символов в сериал. Уберите его - без него будет работать?

и строчка 86 чтения из порта тоже блокирующая... Две блокирующие операции в одном цикле? -они не могут работать вместе.

Так как раз 86 строка и выводит текст , который мне и нужен.

Строку 140 закомментировал - теперь секунды мечутся, а выводимый текст теряется .

 

 

b707
Offline
Зарегистрирован: 26.05.2017

ua4lcn пишет:

Так как раз 86 строка и выводит текст , который мне и нужен.

readStringUntil - не единственный оператор, который может читать из Сериал. И как раз в вашем случае этот оператор не подходит, потому что он блокирующий. Вам надо заменить readStringUntil на обычный read(), читать из порта посимвольно и самому проверять пришедший символ на равенство символу /n.

Строчка - это первое. А вторая ваша ошибка - тот самый цикл while. Зачем он нужен, чтобы данные на дисплей выводились точно раз в секунду, я угадал? - но делаете вы это неправильно, так миллис только чайники используют. Ваш цикл вставляет блокирующую задержку до конца след. секунды, не давая программе принимать символы. Вместо блокирования программы на время до конца секунды надо просто обновлять дисплей раз в секунду, а все остальное время прием из Сериал должен работать.

ua4lcn
Offline
Зарегистрирован: 27.02.2016

Добавил  обработку в 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();
 };

Текст не теряется. Оригинально.Спасибо.

b707
Offline
Зарегистрирован: 26.05.2017

ua4lcn пишет:

Текст не теряется. Оригинально.Спасибо.

все равно может теряться. От readStringUntil избавляйтесь

ua4lcn
Offline
Зарегистрирован: 27.02.2016

b707 пишет:

ua4lcn пишет:

Текст не теряется. Оригинально.Спасибо.

все равно может теряться. От readStringUntil избавляйтесь

Попробую уже на реальном проекте адаптировать эту возможность(принимать текст). 

Надо .что бы и часы ходили , и чтоб в любой момент была возможность принять текст.

Спасибо за подсказки.

b707
Offline
Зарегистрирован: 26.05.2017

ua4lcn пишет:

Попробую уже на реальном проекте адаптировать эту возможность(принимать текст). 

Надо .что бы и часы ходили , и чтоб в любой момент была возможность принять текст.

Спасибо за подсказки.

когда вы ставите прием символов внутрь while, как в последнем коде - у вас длина цикла зависит от времени приема символов и может быть не точно 1 сек, а больше. Наверно для часов это не очень хорошо, но решать вам.

ua4lcn
Offline
Зарегистрирован: 27.02.2016

Не, тут все нормально . Времени на передачу текста хватает , сбоев не наблюдается. Испытывал много раз, пока что без сбоев. Текст приходит полностью.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Странно, что никто не предложил увеличить буфер Serial'a.
Хотя нет, предлагали.
Впрочем ТСа устраивает и его костыль , пусть радуется(до поры до времени)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

наверно и 45 строку надо тоже исправить...
 

 while (millis() <= (timer + 1000))  { 

 while (millis() - timer <= 1000)  { 

 

ua4lcn
Offline
Зарегистрирован: 27.02.2016

ua6em пишет:

наверно и 45 строку надо тоже исправить...
 

 while (millis() <= (timer + 1000))  { 

 while (millis() - timer <= 1000)  { 

 


Исправить бы не сложно, другое дело, хотябы правильно _как нужно? Просто много об этом подсказывают, но не говорят, все же как правильно. Встречаются многие примеры и это путает_все же правильнее как?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Правильнее вычитать, это «обход» переполнения millis().

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ua4lcn пишет:

Исправить бы не сложно, другое дело, хотябы правильно _как нужно?

http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis

ua4lcn
Offline
Зарегистрирован: 27.02.2016

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=

 

ua4lcn
Offline
Зарегистрирован: 27.02.2016

ЕвгенийП пишет:

ua4lcn пишет:

Исправить бы не сложно, другое дело, хотябы правильно _как нужно?

http://arduino.ru/forum/programmirovanie/velikoe-perepolnenie-millis

По этой ссылке  -  конкретный уже ответ, изучаю...