Что означает print(char&)?

junior_developer
Offline
Зарегистрирован: 27.11.2017
Пытаюсь вывести на экран lcd1602 массив символов типа char, используя библиотеку https://github.com/ssilver2007/LCD_1602_RUS_ALL
Компилятор ругается на строчку
lcd.print(arr[i]);

Код целиком:

#define _LCD_TYPE 2 // тип подключения дисплея
#include <font_LCD_1602_RUS.h>
#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);

char arr[]= "Проверка вывода!"; // массив символов

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

void loop() {
  lcd.setCursor(0, 0);
 for (int i = 0; i < ((sizeof(arr)/sizeof(char)) - 1); i++)
  { 
  lcd.print(arr[i]);  // вывести символ массива
  // lcd.print(*(arr+i)); // так тоже пробовал
    delay(1000);
  }
 lcd.clear();
}

Сообщение компилятора:
no matching function for call to 'LCD_1602_RUS<LiquidCrystal>::print(char&)

Он не может найти в библиотеке функцию с "char&"? А откуда возле char взялась эта закорючка? Объясните пожалуйста, кто разбирается! 

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

через String попробуйте

junior_developer
Offline
Зарегистрирован: 27.11.2017

Попробовал вот так, используя String, а не char:
 

#define _LCD_TYPE 2 // тип подключения дисплея
#include <font_LCD_1602_RUS.h>
#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);

String stroka = "Проверка вывода!";

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

void loop() {
  lcd.setCursor(0, 0);
 for (int i = 0; i < ((sizeof(stroka)/sizeof(String)) - 1); i++)
  { 
  lcd.print(stroka[i]);  // вывести символ массива
  // lcd.print(*(arr+i)); // так тоже пробовал
    delay(1000);
  }
 lcd.clear();
}

Всё равно компилятор пишет:

no matching function for call to 'LCD_1602_RUS<LiquidCrystal>::print(char&)'
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

в строку 17 выводить переменную собрав её в String

#define _LCD_TYPE 2 // тип подключения дисплея
//#include <font_LCD_1602_RUS.h>
//#include <LCD_1602_RUS_ALL.h>
// LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);

#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);

char arr[]= "Проверка вывода!"; // массив символов
String mysimvol;

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

void loop() {
  lcd.setCursor(0, 0);
 for (int i = 0; i < ((sizeof(arr)/sizeof(char)) - 1); i++)
  { 
  mysimvol = String(arr[i]);  
  lcd.print(mysimvol);  // вывести символ массива
  // lcd.print(*(arr+i)); // так тоже пробовал
    delay(1000);
  }
 lcd.clear();
}

 

junior_developer
Offline
Зарегистрирован: 27.11.2017

Большое спасибо за подсказку! Компилятор перестал ругаться, однако русские буквы не отображаются - вместо них какие-то символы!
Нормальный вывод получается только с массивом такого типа:
 

char *arr[] = {"Т", "е", "с", "т", " ", "д", "и", "с", "п", "л", "е", "я", "!"};

Если я не ошибаюсь, это массив указателей! Интересно можно ли обойтись без него? А может быть есть какая-то функция для преобразования в такой массив обычной строки? Подскажите пожалуйста!

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

Чем не устраивает:
char arr[]=" Hello World";
?

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

junior_developer пишет:
Подскажите пожалуйста!
А посмотреть примеры к библиотеке? Не наш метод?

Откройте пример SerialToLCD_I2C.ino и посмотрите на строки №№41 и 51. А потом делайте также со своим char.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Спасибо за подсказку! Попробовал, следуя Вашей рекомендации, использовать готовую библиотечную функцию
Получилось вот так

#define _LCD_TYPE 2
#include <font_LCD_1602_RUS.h>
#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);


char str[] = "Test! Проверка вывода!";

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

void loop() {
  unsigned char w_str[2];
  //     char w_str[];
  lcd.setCursor(0, 0);
  for (int i = 0; i < (sizeof(str) / sizeof(str[0])); i++)
  {
    w_str[0] = str[i];
    if (w_str[0] > 0x7F) {
      w_str[1] = str[i + 1]; //Если кириллица, то читаем второй байт
    }
    lcd.print(lcd.ascii_utf8(w_str));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
    delay(1000);
  }
  lcd.clear();
}

Но дело в том в том, что символы кириллицы  почему-то выводятся два раза подряд!
Например слово "Привет" выводится так "ППррииввеетт", а вот "Hello" - нормально!
Подозреваю, что ошибка может быть в этой стоке
 

 if (w_str[0] > 0x7F)  w_str[1] = str[i + 1]; //Если кириллица, то читаем второй байт

Я написал там i+1, так как думаю, что для перехода к следующему байту нужно добавить единицу!

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

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

Хотя, в принципе, можно поправить и именно эту строку: str[++i]; - не проверял, но смысл в том, чтобы, встретив символ кириллицы, инкрементировать цикл не на 1, а на 2.

junior_developer
Offline
Зарегистрирован: 27.11.2017

Да! Вы абсолютно правы! Это работает!

#define _LCD_TYPE 2
#include <font_LCD_1602_RUS.h>
#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);


char str[] = "Test! Проверка вывода!";

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

void loop() {
  unsigned char w_str[2];
  lcd.setCursor(0, 0);
  for (int i = 0; i < (sizeof(str) / sizeof(str[0])); i++)
  {
    w_str[0] = str[i];
    if (w_str[0] > 0x7F) {
      w_str[1] = str[++i ]; // вначале увеличиваем индекс, чтобы считать второй байт
    }
    lcd.print(lcd.ascii_utf8(w_str));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
    delay(200);
  }
  lcd.clear();
}

Вот так тоже работает:

if (w_str[0] > 0x7F) { //Если кириллица, то...
      i++; // изменить индекс для перехода
      w_str[1] = str[i]; // считать второй байт
    }

Большое спасибо Вам за подсказку!

Добавил в текст программы ещё автоматический перенос на следующую строку, правда для этого пришлось ввести ещё одну переменную! Чтобы подсчитывались выведенные символы!

#include <LCD_1602_RUS_ALL.h>
LCD_1602_RUS <LiquidCrystal> lcd(12, 11, 5, 4, 3, 2);

const int displayTime = 1000;
const int symbolTime = 300;
char str[] = "abc абв abc абв!";

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

void loop() {
  unsigned char w_str[2];
  lcd.setCursor(0, 0);
  for (int i = 0, symbolCount = 0; i < (sizeof(str) / sizeof(str[0])); i++) //symbolCount для подсчета выведенных символов
  { 
    //Serial.println(symbolCount);
    //Serial.println(c);
    w_str[0] = str[i];
    if (w_str[0] > 0x7F) {
      i++; // вначале увеличиваем индекс, чтобы считать второй байт
      w_str[1] = str[i]; 
    }
    lcd.print(lcd.ascii_utf8(w_str));//Вывод на экран LCD, в т.ч. по-русски. Перевод из ASCII в UTF-8.
    symbolCount++;
    delay(symbolTime);
   //* 
    if ((symbolCount % 16) == 0) {
      lcd.setCursor(0, 1);
    }
    if ((symbolCount) % 32 == 0) {
      delay(displayTime);
      lcd.clear();
      lcd.setCursor(0, 0); 
    } //*/
  }
  delay(displayTime);
  lcd.clear();
}

Всё вроде бы работает нормально. Но вот всё-таки интересно, можно ли было обойтись без этой переменной? Кто разбирается, подскажите пожалуйста!
 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

вапще, 1602 может содержать 40 символов в 1 строке.  Можно выводить всё в одну строку и делать горизонтальный скролл влево и вправо.  

Почитай, мошт поймёшь чо 

https://xn--18-6kcdusowgbt1a4b.xn--p1ai/lcd-1602-%D0%B1%D0%B5%D0%B3%D1%83%D1%89%D0%B0%D1%8F-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B0/