Вывод сообщения на LCD дисплей

DruKot
Offline
Зарегистрирован: 10.06.2013

Всем доброго,

пытаюсь принять и вывести сообщение на LCD дисплей (16х2), чтобы научиться отправлять их из терминала линукс и в последствии уметь отправлять команды из терминала и быть уверенным, что они будут получены так как надо.

На данный момент либо loop выглядит так:

void loop()
{  
  while (Serial.available() == 0);
  
  char string[15] = {0};
  
  for (int i=0; i<16; i++)
  {
    string[i] = Serial.read();
  }
  
  lcd.begin(0, 2);
  lcd.print(string);
}

Так выводит сообщение, но съедает 1-й символ, однако, если отправить один символ, то он успешно появляется. Когда я начал с вывода сообщения в 2 строки, там вообще творилось что то непонятное и страшное, поэтому решил совладать пока что хотя бы с одной.

Помогите разобраться пожалуйста.

 

tsostik
Offline
Зарегистрирован: 28.02.2013

может shar string[17] все таки? 16 для содержимого и один для заключительного нуля?

DruKot
Offline
Зарегистрирован: 10.06.2013

да хоть string[5], хоть string[25] - всеравно съедает первый символ(((

maksim
Offline
Зарегистрирован: 12.02.2012

Ну во-первых не все равно. Если вы выйдите за пределы массива, то не факт что попадется 0 да еще и потрете какие нибудь другие переменные. Так что string должна иметь длину не меньше 17.

Во-вторых, вот это что за строка lcd.begin(0, 2);, что она у вас делает? Инициализирует дисплей, у которого в строке 0 символов и 2 строки? Посмотрите стандартные примеры библиотеки LiquidCrystal. А именно SerialDisplay:

void setup(){
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available()) {
    delay(100);
    lcd.clear();
    lcd.setCursor(0, 1);
    while (Serial.available() > 0) 
      lcd.write(Serial.read());
  }
}

Если же вам нужна эта строка что бы ее еще как то обработать, то тогда так:

void setup() 
{
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop()
{  
  if(Serial.available())
  {
    char string[17];
    for (int i = 0; i < 16; i++)
    {
      delay(2);
      string[i] = Serial.read();
    }
    string[16] = 0;
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print(string);
  }
}

 

DruKot
Offline
Зарегистрирован: 10.06.2013

Большое спасибо, все очень доходчиво и я много узнал важного, так же теперь стало понятно почему у меня ничего не получалось. Еще один вопрос, теперь печатается строка, но если она например 6 символов, то оставшиеся 10 печатаются как закрашенные прямоугольники, пробел при этом печатается как положено. Подскажите почему?

maksim
Offline
Зарегистрирован: 12.02.2012

Ну кто ж его знает почему, код покажите.

DruKot
Offline
Зарегистрирован: 10.06.2013

Код, собственно полностью Ваш, только с инициализацией дисплея:

#include <LiquidCrystal.h>

// RS, E, DB5, DB6, DB7, DB8
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);


void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop()
{  
  if(Serial.available())
  {
    char string[17];
    for (int i = 0; i < 16; i++)
    {
      delay(2);
      string[i] = Serial.read();
    }
    string[16] = 0;
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print(string);
  }
}

Спасибо

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так естественно, если вы выбрали этот вариант то будьте добры отправлять все 16 символов, либо нужно как то это описать

#include <LiquidCrystal.h>

// RS, E, DB5, DB6, DB7, DB8
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);


void setup()
{
  lcd.begin(16, 2);
  Serial.begin(9600);
}

void loop()
{  
  if(Serial.available())
  {
    char string[17];
    byte i = 0;
    while(Serial.available() && i < 16)
    {
      delay(2);
      string[i] = Serial.read();
      i++;
    }
    string[i] = 0;
    lcd.setCursor(0, 1);
    lcd.print("                ");
    lcd.setCursor(0, 1);
    lcd.print(string);
  }
}

Чем вас не устроил первый вариант?

 

DruKot
Offline
Зарегистрирован: 10.06.2013

Вы не поняли мой вопрос, но я уже сам разобрался, спасибо, а второй вариант я выбрал, так как хочу принимать 32 символа и делать перенос строки, но это уже другая история, спасибо)

maksim
Offline
Зарегистрирован: 12.02.2012

Я то понял ваш вопрос и показал как это исправить. Если именно интересует - почему? То потому что если вы отправляете меньше 16 символов ,то в переменную string читается пустой буфер, то есть 255 что на дисплее отображается как "закрашенный прямоугольник".

DruKot
Offline
Зарегистрирован: 10.06.2013

Почти закончил! Только вот странно 

#include <LiquidCrystal.h>

// RS, E, DB5, DB6, DB7, DB8
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);


void setup()
{
  Serial.begin(9600);
}

void loop()
{  
  if(Serial.available())
  {
    char outString1[16];
    char outString2[16];
    
    for (int i = 0; i < 32; i++)
    {
      if (i<16)
      {
        delay(2);
        outString1[i] = Serial.read();
      }
      else if (i>15 && i<32)
      {
        delay(2);
        outString2[i-16] = Serial.read();
      }
      else
        Serial.flush();
    }
    outString1[16] = 0;
    outString2[16] = 0;

    lcd.begin(16, 2);
    lcd.print(outString1);
    lcd.setCursor(0, 1);
    lcd.print(outString2);
  }
}

вот если выводить и первую и вторую строку - выводит только начиная с 17-го символа, но если вместо lcd.print(outString); написать lcd.print("Hello world"); (и в первом и во втором выводе, то выводит все как надо.

 

Еще я не понял как Вы сделали замену "" на " " в последнем примере.

Спасибо

maksim
Offline
Зарегистрирован: 12.02.2012

Перечитайте сообщение #1 ,затем сообщение #3 и так до тех пор пока не найдете ответ на свой вопрос. Так же почитайте описание Serial.flush().

maksim
Offline
Зарегистрирован: 12.02.2012

DruKot пишет:

Еще я не понял как Вы сделали замену "" на " " в последнем примере.

Перефразируйте?

taraspigo
Offline
Зарегистрирован: 08.04.2014

Здравствуйте Уважаемые! Я тоже интересуюсь подобной темой. А именно у меня по сериал приходят показания датчика, кодом ниже ардуина их выводит на дисплей от нокии. Но проблема следующая - приходит 2 строки. Мне нужно отображение двух. Они отображаются так: сначало одна, потом сразу вместо первой другая, на пару секунд залипнет и дисплей снова чистый. Мне нужно чтоб обе выводились одна ниже другой и оставались пока новые показания не придут. Два дня уже немогу найти как другую строку ниже разместить и оставить их на дисплее. Буду очеь рад подсказке. Заранее благодарен

 

#include <PCD8544.h>

static PCD8544 lcd;

void setup()
{
  lcd.begin(84, 48);
  Serial.begin(9600);
}

 void loop()
{ 
  if(Serial.available())
  {
    char string[17];
        for (int i = 0; i < 16; i++)
        {
      delay(2);
      string[i] = Serial.read(); 
           }
    string[16] = 0;
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print(string);
    
  }
}

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Если Вам нужно, чтобы строки выводились одна под другой, зачем Вы каждый раз устанавливаете курсор в начало верхней строки?

Ну и чтение 16 символов без проверки, что прочиталось все, что пришло, тоже вызывает некоторые сомнения.