проблема с выводом значения переменных на lcd 16X2

DimaP.
Offline
Зарегистрирован: 21.04.2013

Вопрос собственно вот в чемЖ

Имеется LCD дисплей 16 символов 2 строки подключенный через переходник I2C

вот такой вот

библиотеку скачал вот по этой ссылочке

http://www.dfrobot.com/index.php?route=product/product&path=48&product_id=593#.UIWxs6fjb4K

Вообщемм железо то работает хорошо.

Проблема возникает когда я пытаюсь выводить в одной строке з разных переменных

   

   lcd.setCursor(0, 1);
   lcd.print("A=");
   lcd.print(real_U_A);
  
  
  
   lcd.setCursor(5, 1);
   lcd.print("B=");
   lcd.print(real_U_B);
  
 
   lcd.setCursor(10, 1);
   lcd.print("C=");
   lcd.print(real_U_C);  

Переменные int типа!

они хранят в себе напряжение с 3 разных каналов ADC

если это напряжение имеет 3 знака к примеру 100Вольт то все хорошо, но если оно изменится и станет <= 99 то число от последнего разряда не сотрется а так и останется на дисплее и он напечатает

Подскажите как можно избежать данного явления?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013
Я просто добавляю пробелов в зависимости от выводимого числа, может у кого поинтересней есть вариант?)
lcd.print (value);
if (value <10) lcd.print ("   "); // 3 пробела
if (value >=10 && value <100) lcd.print ("  ");// 2 пробела
if (value >=100 && value <1000) lcd.print (" "); // 1 пробел

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Да я тоже применял этот метод!!! Но получается многократные вызовы Lcd.printчто приведет к росту объема занимаемой памяти в МК.

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

Делается примерно так:

  char str[] = "A=   B=   C=   ";
  IntToStr(real_U_A, &str[2]);
  IntToStr(real_U_B, &str[7]);
  IntToStr(real_U_C, &str[12]);
  lcd.setCursor(0, 1);
  lcd.write(str);


void IntToStr(int num, char *text)
{
  text[0] = (num/100) + '0';
  text[1] = ((num/10)%10) + '0';
  text[2] = (num%10) + '0';
}

Если нужно убрать незначащие нули, то функция IntToStr() должна выглядеть так:

void IntToStr(int num, char *text)
{
  if(num >= 100)
  {
    text[0] = (num/100) + '0';
    text[1] = ((num/10)%10) + '0';
    text[2] = (num%10) + '0';
  }
  else if(num >= 10)
  {
    text[0] = ((num/10)%10) + '0';
    text[1] = (num%10) + '0';
  }
  else
  {
    text[0] = (num%10) + '0';
  }
}

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Спасибо за подсказку!! 

Вызов функции и ее имя разные, наверное это банальная опечатка.

char str[] = "A=   B=   C=   ";
  IntToChar(real_U_A, &str[2]);
  IntToChar(real_U_B, &str[7]);
  IntToChar(real_U_C, &str[12]);
  lcd.setCursor(0, 1);
  lcd.write(str);


void IntToChar(int num, char *text)
{
  text[0] = (num/100) + '0';
  text[1] = ((num/10)%10) + '0';
  text[2] = (num%10) + '0';
}

 

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

Да, поправил.

melvladimir
Offline
Зарегистрирован: 08.03.2013

А насколько проигрывает вот такой метод? (повторный вызов "lcd.setCursor();" и добавление пробелов к именам)

lcd.setCursor(0, 1);
lcd.print("A=   ");
lcd.setCursor(2, 1);
lcd.print(real_U_A);

lcd.setCursor(5, 1);
lcd.print("B=   ");
lcd.setCursor(7, 1);
lcd.print(real_U_B);

lcd.setCursor(10, 1);
lcd.print("C=   ");
lcd.setCursor(12, 1);
lcd.print(real_U_C);  

Или вообще дергать очистку экрана и все ставить (все равно имена переустанавливаются каждый раз).

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

Да кто ж его знает на сколько... и в чем это сколько измеряется...

Скомпилируйте и так и так и посмотрите хотя бы по разнице в размере прошивки.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Жалко, что стандартная программа не показывает загрузку ОЗУ, т.к. размер прошивки - это не всегда самое главное :)
Извращался и так и сяк (мог в первом коде напутать).

А разве lcd.write сможет вывести всё? Это ж вроде только для вывода одного символа... Или я туплю?

Скомпилировал:
1) предобаботка. Размер скетча в двоичном коде: 2 800 байт (из 258 048 байт максимум)



#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int real_U_A=0;
int real_U_B=0;
int real_U_C=0;

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

void loop() {
char str[] = "A=   B=   C=   ";
  IntToChar(real_U_A, &str[2]);
  IntToChar(real_U_B, &str[7]);
  IntToChar(real_U_C, &str[12]);
  lcd.setCursor(0, 1);
  lcd.write(str);
}

void IntToChar(int num, char *text)
{
  text[0] = (num/100) + '0';
  text[1] = ((num/10)%10) + '0';
  text[2] = (num%10) + '0';
}

2) доп. пробелы и повторная установка курсора. Размер скетча в двоичном коде: 3 196 байт (из 258 048 байт максимум)



#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int real_U_A=0;
int real_U_B=0;
int real_U_C=0;

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

void loop() {
lcd.setCursor(0, 1);
lcd.print("A=   ");
lcd.setCursor(2, 1);
lcd.print(real_U_A);

lcd.setCursor(5, 1);
lcd.print("B=   ");
lcd.setCursor(7, 1);
lcd.print(real_U_B);

lcd.setCursor(10, 1);
lcd.print("C=   ");
lcd.setCursor(12, 1);
lcd.print(real_U_C);
}

 

step962
Offline
Зарегистрирован: 23.05.2011

melvladimir пишет:

Жалко, что стандартная программа не показывает загрузку ОЗУ, т.к. размер прошивки - это не всегда самое главное :)

Объем свободной памяти RAM

DimaP.
Offline
Зарегистрирован: 21.04.2013


melvladimir пишет:

Жалко, что стандартная программа не показывает загрузку ОЗУ, т.к. размер прошивки - это не всегда самое главное :)
Извращался и так и сяк (мог в первом коде напутать).

А разве lcd.write сможет вывести всё? Это ж вроде только для вывода одного символа... Или я туплю?

Скомпилировал:
1) предобаботка. Размер скетча в двоичном коде: 2 800 байт (из 258 048 байт максимум)







#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int real_U_A=0;
int real_U_B=0;
int real_U_C=0;

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

void loop() {
char str[] = "A=   B=   C=   ";
  IntToChar(real_U_A, &str[2]);
  IntToChar(real_U_B, &str[7]);
  IntToChar(real_U_C, &str[12]);
  lcd.setCursor(0, 1);
  lcd.write(str);
}

void IntToChar(int num, char *text)
{
  text[0] = (num/100) + '0';
  text[1] = ((num/10)%10) + '0';
  text[2] = (num%10) + '0';
}

2) доп. пробелы и повторная установка курсора. Размер скетча в двоичном коде: 3 196 байт (из 258 048 байт максимум)







#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int real_U_A=0;
int real_U_B=0;
int real_U_C=0;

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

void loop() {
lcd.setCursor(0, 1);
lcd.print("A=   ");
lcd.setCursor(2, 1);
lcd.print(real_U_A);

lcd.setCursor(5, 1);
lcd.print("B=   ");
lcd.setCursor(7, 1);
lcd.print(real_U_B);

lcd.setCursor(10, 1);
lcd.print("C=   ");
lcd.setCursor(12, 1);
lcd.print(real_U_C);
}

 

но ведь просто дбавление пробелов здесь не поможет!

если значение переменой будет на границе 3 знаков от100 до999 то нужно будет использовать 3 сегмета, если оно же изменится и станет 2 значное т.е от 10 до 99 то нужно будет 2 сегмента, а если 1 значение значит один сегмент. Так вот для того чтобы обеспечить правильный вывод этих значений с пробелами надо будет применить вот такой код(псевдокод)



#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int real_U_A=0; //переменная от 0 до 999

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

void loop() {
lcd.setCursor(0, 1);
lcd.print("A=");
if(real_U_A=<99){
lcd.setCursor(2, 1);
lcd.print(real_U_A);
lcd.print(" "); // один пробел
}
else if(real_U_A=<9){
lcd.setCursor(2, 1);
lcd.print(real_U_A);
lcd.print("  "); // два пробела
}
else{
lcd.setCursor(2, 1);
lcd.print(real_U_A);
}
}

 

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

DimaP. пишет:

но ведь просто дбавление пробелов здесь не поможет!

Поможет, проверте. Данной конструкции ,если не важен размер прошивки, более чем достаточно:

lcd.setCursor(0, 1);
lcd.print("A=   ");
lcd.setCursor(2, 1);
lcd.print(real_U_A);

lcd.setCursor(5, 1);
lcd.print("B=   ");
lcd.setCursor(7, 1);
lcd.print(real_U_B);

lcd.setCursor(10, 1);
lcd.print("C=   ");
lcd.setCursor(12, 1);
lcd.print(real_U_C);

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

счас попробую))

melvladimir
Offline
Зарегистрирован: 08.03.2013

плюсанул за сообщение :)
У меня в авто так и работает. Есть переменные, которые все время увеличиваются, а есть те, которые прыгают то "0" то "65000". И все отлично работает. Вот сейчас заинтересовал метод с формированием строки и то, насколько выгодней его использовать (и выгодно ли вообще).

Мне не понятен момент с lcd.write, по-моему я неправильно написал код в первом случае (используя преобразование).
Что-то мне подсказывает, что такая конструкция не выведет на экран всю строку:



void loop() {
char str[] = "A=   B=   C=   ";
  IntToChar(real_U_A, &str[2]);
  IntToChar(real_U_B, &str[7]);
  IntToChar(real_U_C, &str[12]);
  lcd.setCursor(0, 1);
  lcd.write(str);
}

т.к. вместо "lcd.write" надо "lcd.print". А если так, то вариант с пробелами будет меньше по размеру на 50-150 байт.

Гуру, развейте, пожалуйста, сомнения :)

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

Все должно выводиться нормально, так как write() наследуется от Stream, так же как в Serial.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

DimaP. пишет:

счас попробую))

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

lcd.print("A=   B=   C=   ");

А потом уже двигать курсор и подставлять  значения. Кстати, заодно вопрос. У вас как я понимаю вольтметр, а последние цифры не бегают? Меня интересует кто как с этим явлением борется..

DimaP.
Offline
Зарегистрирован: 21.04.2013

вот ведь тема я писал про него

http://arduino.ru/forum/proekty/voltmetr-peremennogo-napryazheniya

sartam
Offline
Зарегистрирован: 27.09.2015

Подскажите пожалуйста, как вводить строку русских букв в дисплее на контроллере  hd44780 с помощью ардуино? Дисплей русифицирован.

Клапауций 070
Offline
Зарегистрирован: 26.09.2015
depecher
Offline
Зарегистрирован: 01.02.2018

Здраствуйте!
Arduino, да и вообще программирование, начинаю только изучать, поэтому не судите строго) И так кратко и схеме - имеются 4 кнопки: 2 меняют один параметр вверх/вниз, 2 меняют второй параметр вверх/вниз. Все работает, все хорошо, но на экране при смене параметра с двухзначного на однозначный, например с 10 на 9, девятка отображается неккоректно. Помогите разобратся из-за чего это и как решить.
Часть кода, видео прилагаю.

https://www.youtube.com/watch?v=QFmDDGEOO-4

//Turn down the work time
  worktime = constrain(worktime, 5, 60);
  if (lastDownWorkButton== LOW && currentDownWorkButton == HIGH)
  {
    worktime--;
  }
  //Turn up the work time
  else if (lastUpWorkButton== LOW && currentUpWorkButton  == HIGH)
  {
    worktime++;
  }
  //Print work time
  lcd.setCursor(10,1);
  lcd.print(worktime);
  lastDownWorkButton = currentDownWorkButton;
  lastUpWorkButton = currentUpWorkButton;

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

Все она корректно отображается ) либо форматируйте вывод чтобы всегда было две цифры (т.е. 09) либо сначала печатайте два пробела а потом уже значение

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

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

depecher
Offline
Зарегистрирован: 01.02.2018

Нашел, спасибо, добавил одну строку и все получилось

ildarmustafin
Offline
Зарегистрирован: 11.04.2014

Свой вопрос упорядочивания данных по левому краю я решил следующим образом:

String convertValue(String curValue, byte maxLengthValue) {
  char* probel[5] = {"", " ", "  ", "   ", "    "};
  String result = curValue + probel[maxLengthValue - curValue.length()];
  return result;
}

где curValue - это строка для вывода на экран, maxLengthValue - макс количество символов для вывода

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

Такое себе решение, что не попадя а String перегонять и с ним работать.
Куда как дешевле и быстрее:
if(val<100){lcd print(" ");}
if(val<10){lcd.ptint(" ");}
lcd.print(val);