Как исправить мерцающую светодиодную матрицу и экран меню lcd

#c #c #arduino #lcd

#c #c #arduino #ЖК-дисплей

Вопрос:

Я создаю проект, в котором у вас есть светодиодная матрица, ЖК-дисплей и 7 различных датчиков. Каждый датчик будет отображать другое сообщение для матрицы и имеет собственное подменю на ЖК-дисплее.

Я создал меню для переключения между датчиками. Для навигации по меню используется поворотный энкодер. (Вывод имеет прерывание при изменении для выполнения только цикла void при изменении вывода) Также кнопка выбора используется для запуска программы пункта меню.(сенсорная программа, такая как prg_Pong (), prg_Flame ());

Я хочу отображать пункты меню на ЖК-дисплее (без I2C). Теперь моя проблема в том, что мои пункты главного меню отображаются правильно (без мерцания из-за прерывания на выводе поворотного энкодера), но когда я нажимаю кнопку для запуска, например prg_Pong (), на ЖК-дисплее выводится сообщение running pong, но сообщение мерцает, а сообщение на светодиодной матрице хорошее (статическое).

Я нашел решение, добавив задержку (300); в цикле после drawMenu, но когда я делаю это и ввожу prg_Pong(); сообщение на светодиодной матрице начинает мерцать во время задержки, а пункт меню «запуск pong» больше не мерцает.

Функции displayData(), mtx_clear() используются для светодиодной матрицы, и они работают. Потому что, когда я удаляю функциональность ЖК-дисплея, сообщение отображается правильно.

 void loop() {
  drawMenu(RotaryEncoder());
  delay(300);
}


void drawMenu(byte rotaryPosition) {
  stateBtnSelect = digitalRead(BTN_SELECT);
  if (stateBtnSelect == HIGH amp;amp; previousBtnState == LOW amp;amp; millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
    time = millis();
  }
  previousBtnState = stateBtnSelect;

  //Switch the value of the rotary encoder
  switch (rotaryPosition) {
    case 0:
      displayMenuItem(0);
      if (state == HIGH) {
        prg_Pong();
      }
      break;
    case 1:
      displayMenuItem(1);
      if (state == HIGH) {
        prg_Ascroll();
      }
      break;
    case 2:
      displayMenuItem(2);
      if (state == HIGH) {
        prg_Clock();
      }
      break;
    case 3:
      displayMenuItem(3);
      if (state == HIGH) {
        prg_Flame();
      }
      break;
    case 4:
      displayMenuItem(4);
      if (state == HIGH) {
        prg_Heartbeat();
      }
      break;
    default:
      break;
  }
}

//Display a menu item
void displayMenuItem(byte item)
{
  //menu strings (mai n categories)
    String menuItems[MAX_MENU_ITEMS] = {"Pong game", "A. Scroller", "Clock", "Flame/temp", "Heartbeat"};
    lcd.clear();
    lcd.setCursor(6, 0);
    lcd.print("Menu");
    lcd.setCursor(0, 1);
    lcd.write(byte(0));
    lcd.print(menuItems[item]);
}


void prg_Pong()
{
  lcd.clear();
  delay(100);
  lcd.print("run pong");
  mtx_clear();

  //print cirlce once
  MessageEncoder(ReturnLetter(24), BitStream);
  for (int j = 0; j < 8; j  )
  {
    displayData(~BitStream[j] amp; Kolommen[j]);
  }
}
  

Комментарии:

1. 1. Не очищайте дисплей, если вам не нужно, т. Е. Когда ничего не меняется, Не очищайте, 2. рассмотрите возможность использования своего рода буфера кадров, т. Е. Массива или тому подобного, В котором вы поддерживаете и изменяете полное содержимое дисплея, затем переносите весь буфер на дисплей (безочистка) перезапись предыдущего содержимого.

Ответ №1:

вы часто очищаете ЖК-дисплей, поэтому это будет выглядеть как мерцание.

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

 prev_menu=-1;
update_display=true;

void loop() {
  drawMenu(RotaryEncoder());
  delay(300);
}


void drawMenu(byte rotaryPosition) {
  stateBtnSelect = digitalRead(BTN_SELECT);
  if (stateBtnSelect == HIGH amp;amp; previousBtnState == LOW amp;amp; millis() - time > debounce) {
    if (state == HIGH)
        state = LOW;
    else
      state = HIGH;
    time = millis();
    update_display=true;
  }
  previousBtnState = stateBtnSelect;

    if(prev_menu != rotaryPosition)
            update_display=true;
    else
        update_display=false;

  //Switch the value of the rotary encoder
  switch (rotaryPosition) {
    case 0:
      displayMenuItem(0);
      if (state == HIGH) {
        prg_Pong();
      }
      break;
    case 1:
      displayMenuItem(1);
      if (state == HIGH) {
        prg_Ascroll();
      }
      break;
    case 2:
      displayMenuItem(2);
      if (state == HIGH) {
        prg_Clock();
      }
      break;
    case 3:
      displayMenuItem(3);
      if (state == HIGH) {
        prg_Flame();
      }
      break;
    case 4:
      displayMenuItem(4);
      if (state == HIGH) {
        prg_Heartbeat();
      }
      break;
    default:
      break;
  }
}

//Display a menu item
void displayMenuItem(byte item)
{
  //menu strings (mai n categories)
    if(  update_display){

    String menuItems[MAX_MENU_ITEMS] = {"Pong game", "A. Scroller", "Clock", "Flame/temp", "Heartbeat"};
    lcd.clear();
    lcd.setCursor(6, 0);
    lcd.print("Menu");
    lcd.setCursor(0, 1);
    lcd.write(byte(0));
    lcd.print(menuItems[item]);
    prev_menu=item;

    }
}


void prg_Pong()
{
if(update_display){
  lcd.clear();
  delay(100);
  lcd.print("run pong");
    update_display=false;

  }
  mtx_clear();

  //print cirlce once
  MessageEncoder(ReturnLetter(24), BitStream);
  for (int j = 0; j < 8; j  )
  {
    displayData(~BitStream[j] amp; Kolommen[j]);
  }
}