Вывод информации на дисплей с millis

dmmmit

✩✩✩✩✩✩✩
4 Ноя 2018
6
0
Здравствуйте, начал увлекаться ардуино. Хочу сделать метеостанцию + управление реле с помощью ИК.
Управление релешками с помощью ИК уже сделал, все работает окей! Есть у меня датчик BME280(давление,влажность,температура,относ.высота) будет у меня на улице стоять. Хочу сделать вывод информации с него на дисплей.
Сначала выводятся температура и влажность, через пять секунд выводится давление и высота. С delay все это получилось, но хочу добавить кнопку, нажав на которую будет показывать информация с других датчиков. Как мне добавить в работу millis??
C++:
if (millis() - time > 5000) {

     time = millis();

lcd.setCursor(0, 0);

    lcd.print (L"Температ.: ");

    lcd.print(bme.readTemperature(),0);

    lcd.print(L"°C");

    lcd.setCursor(0, 1);

    lcd.print (L"Влажность: ");

    lcd.print(bme.readHumidity(),0);

    lcd.print (L"%");
Делал такой вариант, но инфа выводится на дисплей и сразу же потухает и так каждые пять секунд.
Целый день сегодня ищу инфу по поводу этого, в итоге ничего.... Помогите пожалуйста начинающему школьнику-ардуинщику, дайте хотя бы наводки какие-нибудь, буду очень благодарен.
P.S Пробовал разными способами сделать вывод инфы : делать вывод другой информации с датчиков через 10 секунд, и чтобы сначала просто выводилась Температура и влажность, а потом используя millis через 5 сек давление и высота - безуспешно, показывается какая-то ерунда....
 
Последнее редактирование:

Wan-Derer

★★★★✩✩✩
Команда форума
31 Июл 2018
1,440
281
Москва
wan-derer.ru
@dmmmit, Во-первых, у тебя IF не закрыт фигурной скобкой. А во-вторых, ты не показал второй блок, который выводит показания давления и высоты.
А потом возьми и представь себя компьютером. который совсем не понимает чего хочет от него человек, а просто исполняет программу, строчка за строчкой. Пройди по программе с карандашиком и пойми где что не так.
 

dmmmit

✩✩✩✩✩✩✩
4 Ноя 2018
6
0
@Wan-Derer вот мой код :
C++:
#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;

void setup (){
Serial.begin(9600);
    lcd.init(); // иницилизируем ЖК
  lcd.backlight(); // включаем подсветку
bme.begin();
}


  void loop()
{

   lcd.setCursor(0, 0);  
    lcd.print (L"Температ.: ");
    lcd.print(bme.readTemperature(),0);
    lcd.print(L"°C");
    lcd.setCursor(0, 1);
    lcd.print (L"Влажность: ");
    lcd.print(bme.readHumidity(),0);
    lcd.print (L"%");
    delay(5000);
    lcd.clear();
    lcd.setCursor(0, 0);  
    lcd.print (L"Давление: ");
    lcd.print(bme.readPressure() / 100.0F * 0.75006375541921,0);
    lcd.print(L"мм");
    lcd.setCursor(0, 1);  
    lcd.print("Высота: ");
    lcd.print(bme.readAltitude(SEALEVELPRESSURE_HPA),0);
    lcd.print("метр");
    delay(5000);
    lcd.clear();
}
это изначальный код с delay. Когда решил добавить кнопку начал куда-то приписывать
if (millis() - time > 5000) {

time = millis();
, но ничего не выходило. В инете нужной инфы не нашел, там только как просто вывести например в Serial, а как вывести и оставить на 5 сек нету...
 

Wan-Derer

★★★★✩✩✩
Команда форума
31 Июл 2018
1,440
281
Москва
wan-derer.ru
@dmmmit, не надо с делэй. Мы же не его обсуждаем. Давай тот код, который должен работать и описание как он по-твоему должен работать (но не работает)
 

dmmmit

✩✩✩✩✩✩✩
4 Ноя 2018
6
0
@Wan-Derer
Вот код:
C++:
#include <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;
unsigned long timeon;
unsigned long timeoff;
void setup (){
Serial.begin(9600);
    lcd.init(); // иницилизируем ЖК
  lcd.backlight(); // включаем подсветку
bme.begin();
}
void loop()
{
 
   lcd.setCursor(0, 0);   
    lcd.print (L"Температ.: ");
    lcd.print(bme.readTemperature(),0);
    lcd.print(L"°C");
    lcd.setCursor(0, 1);
    lcd.print (L"Влажность: ");
    lcd.print(bme.readHumidity(),0);
    lcd.print (L"%");
  
   if (millis() - timeon > 5000){
    lcd.clear();
    lcd.setCursor(0, 0);   
    lcd.print (L"Давление: ");
    lcd.print(bme.readPressure() / 100.0F * 0.75006375541921,0);
    lcd.print(L"мм");
    lcd.setCursor(0, 1);   
    lcd.print("Высота: ");
    lcd.print(bme.readAltitude(SEALEVELPRESSURE_HPA),0);
    lcd.print("метр");
}
  
   if (millis() - timeoff > 10000){ 
    lcd.clear();
   }
Первые пять секунд после запуска выводит температуру и влажность. Затем начинает выводить два значения и из-за этого текст на экране просто мигает. Мне нужно сделать так: после включения Ардуино выводились показания температуры и влажности на дисплей, затем через пять секунд выводилось давление и высота. И так каждые пять секунд. Нужно сделать именно с millis. Т.к в дальнейшем хочу добавить кнопку и другие датчики. В интернете информацию нашел только по поводу вывода в Сериал, а мне нужно на экран + чтобы вывелась, ждала 5 сек и только потом менялась
P.S Извиняюсь за долгий ответ.
 

dmmmit

✩✩✩✩✩✩✩
4 Ноя 2018
6
0
@Wan-Derer Уже проходился, и не раз. вот в этом коде сделал так как думаю. Хотелось бы хоть узнать где ошибка
 

Wan-Derer

★★★★✩✩✩
Команда форума
31 Июл 2018
1,440
281
Москва
wan-derer.ru
@dmmmit, Ну подумай что случится с твоими IF через 5 и через 10 сек
А чтобы экран не мельтешил, избегай lcd.clear(); внутри циклически повторяющегося вывода.
 

SergeySAS

★✩✩✩✩✩✩
20 Дек 2018
42
10
Москва
sustavov.org
Я бы выделил отдельные функции что-то типа ShowTemperatureAndHumidity(), ShowPressureAndAltitude().
В них уйдут все твои print и основной код займет 5 строк.
Далее в loop ввел бы стандартную state машину. Т.е. ввел переменную режим работы и по ней switch.
А вот эту переменную уже и меняй как угодно. хоть по delay(), хоть по millis().
Получится примерно так:
C++:
int CurrState=0; //текущее состояние
int PreState=1; //предыдущее состояние
// 0 - temp and humidity
// 1 - Pressure and Altitude4

void ShowTemperatureAndHumidity(){
    if (PreState !=CurrState) //чтоб не моргало лишний раз
        lcd.clear();

    lcd.setCursor(0, 0);
    lcd.print (L"Температ.: ");
    lcd.print(bme.readTemperature(),0);
    lcd.print(L"°C");
    lcd.setCursor(0, 1);
    lcd.print (L"Влажность: ");
    lcd.print(bme.readHumidity(),0);
    lcd.print (L"%");
}

void ShowPressureAndAltitude(){
    if (PreState !=CurrState) //чтоб не моргало лишний раз
        lcd.clear();
 
    lcd.setCursor(0, 0);
    lcd.print (L"Давление: ");
    lcd.print(bme.readPressure() / 100.0F * 0.75006375541921,0);
    lcd.print(L"мм");
    lcd.setCursor(0, 1);
    lcd.print("Высота: ");
    lcd.print(bme.readAltitude(SEALEVELPRESSURE_HPA),0);
    lcd.print("метр");
}


unsigned long curtime;
unsigned long lasttime;

void setup (){
  Serial.begin(9600);
  lcd.init(); // иницилизируем ЖК
  lcd.backlight(); // включаем подсветку
  bme.begin();
  lasttime = millis();
}

//сюда вставить обработку кнопки
// в ней ставить CurrState=!CurrState; и менять lasttime на millis();

void loop(){
   currtime = millis();
  if (currtime - lasttime > 5000){
      CurrState=!CurrState;
      lasttime = currtime;
   }

   switch(CurrState){
      case 0:  ShowTemperatureAndHumidity();
                    break;
      case 1: ShowPressureAndAltitude();
               
      default: break;
   }
   delay(200); //чтоб не так часто все дергать.
   PreState = CurrState;
}
 
Последнее редактирование:

dmmmit

✩✩✩✩✩✩✩
4 Ноя 2018
6
0
@SergeySAS Спасибо огромное. в Скором времени попробую код и напишу как что получилось!!!)))
 

MbIKOLA

✩✩✩✩✩✩✩
Здравствуйте.
Ивините что пишу сюда не хочу новую тему создавать идентичную.
У меня такая же ситуация с LCD и millis() только мне надо чтоб на экран с интервалом 5 секунд выдавало с 5 датчиков.
Ваш код работает но на LCD выводить только показание с 2 датчиков те что стоят в первой очереди
case 0 и case 1 и так по кругу хотя все case 2,3,4 сделано по аналоги c case 0,1

switch(CurrState){
case 0: ShowTemperatureAndHumidity();
break;
case 1: ShowPressureAndAltitude();
break;
case 2: мой код 2);
break;
case 3: мой код 3();
break;
case 4: мой код 4();

default: break;
}
Скажете почему не работает case 2,3,4?
 
Последнее редактирование:

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
Да, применение конечных автоматов (программ с состояниями, типа тут CurrState) решает задачу разделения вывода.

Тут: пост №10 выкладывал свою библиотеку и там далее есть развитие в виде драйвера к LCD дисплею и ПО для конечных автоматов разной сложности.. все это решено.

Проблема есть несколько иного плана, а именно:
При выводе на дисплей по I2C, чип-переходник вполне способен работать на скоростях вплоть до 880кГц шины I2C (Атмел позволяет тоже). Но, вот сам дисплей "отрисовывает" символ не шустрее чем за 700-800микросекунд! И это время приходится пропускать в "цикле ожидания", пусть и через delayMicroseconds() .. жаба душит: 800мксек это около 8000 команд МК даже с учетом двухтактного обращения к ОЗУ! :)

В общем, надо как-то реализовать функцию lcd.write() в нотации типовой библиотеки или lcdWrite() в моей нотации, так ..
Чтобы вывод буфера (строки) нескольких символов стал НЕ блокирующим и эти 8000 команд можно было бы "что-то делать ещё"..

Пробовал с наскоку .. получается какая-то фигня. :)
 

Mamkin_teXnik

✩✩✩✩✩✩✩
29 Июл 2020
1
0
Доброго времени суток! Вопрос касаемо вывода данных на дисплей 16х2. проект представляет собой примитивный контроллер полива по заранее установленным временным параметрам. так задумано сделать 2 режима работы, которые выбираются с помощью ключа. Эту часть кода я осилил, но была задумка параллельно выводить на дисплей следующую информацию: Приветствие, после выбор режима, после выбора режима должно отображаться (1, 0) текущее время, (0, 1) состояние реле насоса, (6, 1) зона, на которой ведется полив.
1. Приветсвие - это реализовал в сетапе.
2. Выберите режим - это уже в лупе. и тут начались проблемы. изначально я расписал отдельно функции режимов и потом в лупе через иф запускаю 1-й или 2-й режим. При переводе ключа в один из режимов, режим активируется, но на дисплее происходит вакханалия, фраза "выберите режим" - не исчезает, её частично заменяет реальное время, но часть символов остаётся, так же состояние реле насоса изначально "Pump_off", а когда реле активируется должно писать "Pump_on", а получатеся "Pump_onf". подскажите, как решить данную проблему.

#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Wire.h>


LiquidCrystal_I2C lcd(0x27,16,2); // Указываем I2C адрес (наиболее распространенное значение), а также параметры экрана (в случае LCD 1602 - 2 строки по 16 символов в каждой
//LiquidCrystal_PCF8574 lcd(0x27); // Вариант для библиотеки PCF8574
RTC_DS3231 RTC;

boolean mode_1;
boolean mode_2;
const int pump = 6;
const int zona1 = 7;
const int zona2 = 8;
const int zona3 = 9;
const int zona4 = 10;
const int zona5 = 11;


int Hour; //Данная переменная хранит часы
int Min; //Данная переменная хранит минуты
int Sec; //Данная переменная хранит секунды

void setup() {
Serial.begin (9600);
lcd.init(); // Инициализация дисплея
lcd.backlight(); // Подключение подсветки
lcd.setCursor(5,0); // Установка курсора в начало первой строки
lcd.print("Hello"); // Набор текста на первой строке
delay(2000);
lcd.clear();
Wire.begin(); //Инициируем I2C интерфейс
RTC.begin(); //Инициирум RTC модуль
pinMode (4, INPUT);
pinMode (5, INPUT);
pinMode (6, OUTPUT);
pinMode (7, OUTPUT);
pinMode (8, OUTPUT);
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
pinMode (11, OUTPUT);
digitalWrite (6, LOW);
digitalWrite (7, HIGH);
digitalWrite (8, HIGH);
digitalWrite (9, HIGH);
digitalWrite (10, HIGH);
digitalWrite (11, HIGH);

}

void loop() {
mode_1 = digitalRead(4);
mode_2 = digitalRead(5);
lcd.setCursor(2,0);
lcd.print("Select Mode");
delay(2000);
lcd.clear();
if ( mode_1 == 1){
mode1();
}


}


void timer(){
DateTime now = RTC.now();
lcd.setCursor(0,0);
lcd.print(now.hour(), DEC);
lcd.print(":");
lcd.print(now.minute(), DEC);
lcd.print(":");
lcd.print(now.second(), DEC);
}

void mode1(){
timer();
DateTime now = RTC.now(); //Делаем запрос на дату и время с микросхемы!
int Hour = now.hour(); //Данная переменная хранит часы
int Min = now.minute(); //Данная переменная хранит минуты
int Sec = now.second(); //Данная переменная хранит секунды
lcd.setCursor(0,1);
lcd.print("Pump_Off");
delay(2000);
if (Hour >= 9 && Min >= 36){
lcd.clear();
timer();
digitalWrite (6, HIGH); //вкл насос
lcd.setCursor(0,1);
lcd.print("Pump_on");
}
if (Hour >= 21 && Min >= 0){ //вкл зона1
digitalWrite (7, LOW);
//lcd.setCursor(10,1);
//lcd.print("Zona1");
}
if (Hour >= 22 && Min >= 0){ //выкл зона1
digitalWrite (7, HIGH);
}
if (Hour >= 22 && Min >= 1){ //вкл зона2
digitalWrite (8, LOW);
//lcd.setCursor(10,1);
//lcd.print("Zona2");
}
if (Hour >= 23 && Min >= 0){ //выкл зона2
digitalWrite (8, HIGH);
//lcd.setCursor(0,1);
//lcd.print("Pump_off");
}
if (Hour >= 23 && Min >= 1){ //вкл зона3
digitalWrite (9, LOW);
//lcd.setCursor(10,1);
//lcd.print("Ok");
}
if (Hour >= 23 && Min >= 59){
digitalWrite (9, HIGH);
}
if (Hour >= 0 && Min >= 1){ //вкл зона4
digitalWrite (10, LOW);
//lcd.setCursor(10,1);
//lcd.print("Ok");
}
if (Hour >= 1 && Min >= 0){
digitalWrite (10, HIGH);
}
if (Hour >= 1 && Min >= 1){
digitalWrite (6, HIGH);
}
}
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
Строку требуется очищать от предыдущего содержимого, выводя в нее пробелы или дополнять ими текущий вывод, если он короче предыдущего. Самый простой способ, все выводимые текста собрать в массив строк фиксированной длины дополнив короткие пробелами и выводить их с одной и той же позиции. С числами можно обходиться похожим способом, но чуть сложней.
 

Un_ka

★✩✩✩✩✩✩
13 Июл 2020
87
18
других форумов.
Для вывода изменяющихся числовых значений я написал функцию.
Функция:
void printVal(int val, byte stolb, byte rad, byte prob) {
  lcd.setCursor(stolb, rad);
  for (byte l = prob; l--; prob > 0) {
    lcd.print(" ");
    // prob--;
  }
  lcd.setCursor(stolb, rad);
  lcd.print(val);
}
 
  • Лойс +1
Реакции: Arhat109

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
@Un_ka, а теперь посмотрите на свою функцию: она дважды выводит в каждое знакоместо, сначала пробел, потом число (если оно в него попало).

есть такое чудо как sprintf() которое формирует строку "по правилам" (форматам) .. там можно задать такой формат .. который будет сам дополнять число пробелами, но вот только "спереди" .. или нулями или чем скажете (кажется) до заданной длины.

как вариант, itoa() тоже превращает целое в строку и дополнить ее до заданной длины тоже можно.

В обоих случаях, вывод и позиционирование setCursor() можно выполнять один раз. Это самые медленные и затратные операции тут. ;)

В общем .. полистайте библиотечные функции Си .. там много полезного.
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
@Un_ka, библиотеки строковых функций. Они никуда не выводят, просто преобразуют одно в другое. Выводят разные lcd.print(), Serial.print() .. они вполне нормально выводят подготовленную строку.

Просто "готовить" строку и тупо ее выводить дешевле, чем каждый раз тереть экран и выводить дважды. Ну .. мне так кажется. ;)
 

Un_ka

★✩✩✩✩✩✩
13 Июл 2020
87
18
других форумов.
@Un_ka, библиотеки строковых функций. Они никуда не выводят, просто преобразуют одно в другое. Выводят разные lcd.print(), Serial.print() .. они вполне нормально выводят подготовленную строку.

Просто "готовить" строку и тупо ее выводить дешевле, чем каждый раз тереть экран и выводить дважды. Ну .. мне так кажется. ;)
Смотря как посмотреть, здесь проблема в долгой передаче 32 байта (две строки по 16) + 2 setCursor на каждую строку. Но т.к. дисплей маленький, то вполне возможно держать под него буфер на Ардуино и как в графических библиотеках сначала заполнять видеопамять, а потом посылать её на экран. С другой стороны есть максимальная частота обновления LCD.
 

Arhat109

★★★✩✩✩✩
9 Июн 2019
369
113
Ну вот и надо уйти от долгих передач и перепозиционирований курсора.. Можно и так, но это дороже по памяти, которой не так уж и много и часто тупо не хватает.