Задать вопрос
Nihhilistum
@Nihhilistum

Как сделать последовательный вывод информации на lcd с millis( )?

Пишу код для метеостанции. Использую lcd 1602 (16x2) с I2C и кнопку для активации дисплея. Решил каждыe блоки кода, отвечающие за работу каких-либо модулей, раскидать в функции. Все действия, привязанные ко времени, прописал не через delay(), а с помощью millis(), дабы не тормозить микроконтроллер. Когда написал скетч и запустил на Ардуине, выявились две проблемы:
1) Экран выводил только приветствие, не убирая по истечении времени текст и не выводя затем другую информацию.
2) Если экран затухал, то повторное нажатие кнопки не включало его (задумывалось, что при выключении дисплея повторное нажатие на кнопку заставит его включиться и снова вывести сначала приветствие, а потом информацию, и так до бесконечности).
Вот сей ужас начинающего горе-ардуинщика:

#include <Arduino.h>
#include <DHT_U.h>
#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>

//РАСПИНОВКА
#define DHTTYPE DHT11 //указание модели датчика DHT
#define DHTPIN 7      //пин датчика
#define button 2      //пин кнопки

//ТАЙМЕРЫ
uint16_t meteoTimer;         //таймер периодичности замера показаний датчика
uint16_t screenWelcomeTimer; //таймер приветствия экрана
uint16_t screenDataTimer;    //таймер вывода инфы с экрана

//ПЕРЕМЕННЫЕ:
byte temp; //значение температуры
byte hum;  //значение влажности

//ФУНКЦИИ
void meteo_current(); //функция замера температуры и влажности
void my_clear();      //библиотечный clear() не работает, этот костыль делает то же самое
void screen_inform(); //функция экрана

//ИНИЦИАЛИЗАЦИИ
DHT dht(DHTPIN, DHTTYPE);        //иициализвция датчика
LiquidCrystal_PCF8574 lcd(0x27); //инициализация экрана

void setup()
{
  dht.begin();      //начало работы датчика
  lcd.begin(16, 2); //начало работы экрана
  lcd.setBacklight(0);
  pinMode(button, INPUT_PULLUP); //подтяжка кнопки (сигнал будет инвертирован)
}

void loop()
{
  while (1) //в loop много проверок от дурака. Этот цикл немного ускорит МК
  {
    meteo_current();                //функция датчика
    if (digitalRead(button) == LOW) //сигнал инвертирован из-за подтяжки
    {
      screen_inform(); //функция экрана
    }
  }
}

void meteo_current() //функция датчика
{
  if (millis() - meteoTimer == 1000)
  {
    meteoTimer = millis();        //обновление таймера
    temp = dht.readTemperature(); //чтение температуры
    hum = dht.readHumidity();     //чтение влажности
  }
}

void my_clear() // библиотечный clear() не работает, этот костыль делает то же самое
{
  lcd.setCursor(0, 0);
  lcd.print("                "); //ввод 16 пробелов для очистки строки
  lcd.setCursor(0, 1);
  lcd.print("                "); //офигеть какой костыль, но работает как надо
}

void screen_inform()
{
  while (millis() - screenWelcomeTimer < 7000) //приветствие в течение 7с
  {
    screenWelcomeTimer = millis(); //обновление таймера
    lcd.setBacklight(100);
    lcd.setCursor(5, 0);
    lcd.print("Hello");
    lcd.setCursor(2, 1);
    lcd.print("Nihillist");
  }
  my_clear();                                 //функция очистки экрана
  while (millis() - screenDataTimer < 420000) //вывод инфы в течение 7 мин
  {
    screenDataTimer = millis(); //обновление таймера
    lcd.setCursor(0, 0);
    lcd.print("Temperature  ");
    lcd.print(temp); //вывод температуры
    lcd.print("  *C");
    lcd.setCursor(0, 4);
    lcd.print("Humilty  ");
    lcd.print(hum); //вывод влажности
    lcd.print("  *");
  }
  my_clear();          //функция очистки экрана
  lcd.setBacklight(0); //потушить подсветку экрана
}
  • Вопрос задан
  • 1046 просмотров
Подписаться 2 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 3
@kalapanga
Для начала уберите while(1) - не смешите людей, в комментарии там написан полный бред.
Далее, Ваш комментарий про инвертированный сигнал не говорит абсолютно ничего о том, когда кнопка нажата, а когда нет - только путает. Сделайте функцию ButtonPressed. В ней проверяйте пин на что нужно. А в программе будет только if ButtonPressed .... Ведь читабельнее так, правда? Ну и наконец надо более чётко сформулировать желаемый алгоритм:
- Начальное состояние после включения - кнопка отжата на экране ничего.
- Кнопка нажата и отпущена (или нажата и удерживается?) происходит следующее...
- Если во время этого следующего.... то...
Тогда можно будет сказать что-то более определённое. А может и сами за это время увидите, что у Вас алгоритму не соответствует.
Ответ написан
@vanyamba-electronics
420000 - это 19 бит, переменная должна иметь тип unsigned long - uint32_t.
Ответ написан
Комментировать
Tomasina
@Tomasina
Инженер-разработчик
#define LCD_UPDATE_TIME 40 // интервал переключения между экранами, сек
#define LCD_SCREENS 4 // количество экранов с информацией
...
loop()
{
static byte screenPage = 1; // счетчик текущего номера экрана
static unsigned long prevScreenUpdateTime;
...
if (millis() - prevScreenUpdateTime > LCD_UPDATE_TIME * 1000) // кнопка не нажата более N сек
{
screenPage++;
if (screenPage > LCD_SCREENS) screenPage = 1;
my_clear(); //функция очистки экрана
switch (screenPage)
{
case 1:
{
.....
break;
}
case 2:
{
.....
break;
}
{
}
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы