Непредсказуемое поведение TM1637

Всем здравствуйте.
Написал второй свой скетч, прошил. Ардуино нано с алика, олд бутлоадер и 4разрядный дисплей на TM1637. Простой таймер обратного остчета с одной кнопкой.

Наблюдаю вот такую картину:
При запуске все нормально(01мин:00сек), но при начале отсчета времени по короткому клику, секунды не убывают как задумано, а кратковременно вспыхивают все сегменты 4го разряда , и при этом прибавляется по одной минуте.

При удержании кнопки секунды начисляются - а потом, при отпускании кнопки, отсчет идет как положено, вычитает по одной секунде, но цифры не соответствуют реальным значениям переменных(минуты перед этим начислялись и пришли в беспорядок). По этой причине сигнал получается не по нулям.

С другими библиотеками то же самое. disp.clear(); перед отображением только мерцание вызывает, а значения как были так и остаются неверные.
Посмотрите, кому не лень, пожалуйста. И если нетрудно, порекомендуйте более правильно компоновать код, чтобы было красиво и экономично. Намеренно выбросил ненужный антидребезг в обработчике кнопки, и старался объявлять переменные внутри функций. Не знаю, правильно это или нет. Писал на телефоне, может где-то некрасиво выглядит, не видно толком.

#define btnPin 5  //кнопка
//#define ledPin 8
#define buzPin 4  //пищалка

#define CLK 6
#define DIO 7

#include <GyverTM1637.h>
GyverTM1637 disp(CLK, DIO);



bool longClick, shortClick = false; //флаги кнопок
bool alarm = false; //флаг сигнала
uint8_t secund = 0; 
uint8_t minut = 1;


void setup() {
  pinMode(btnPin, INPUT_PULLUP);
 // pinMode(ledPin, OUTPUT);
  pinMode(buzPin, OUTPUT);
  disp.clear(); 
  disp.brightness(0); //яркость минимум
 

}

void loop() {
  Button(); 
  setupTimer(); //установка времени
  goTime(); //отсчет времени
  Signal(); 
  DispTimer (); //показываем время
}
//показываем время
void DispTimer () {
  byte dispTime[] = {(byte)minut / 10, (byte)minut % 10, (byte)secund / 10, (byte)secund % 10}; //массив значений каждого разряда дисплея
  disp.display(dispTime); //показываем
}
//сигналим по истечению времени перывистым сигналом и встаем на отсчете 1мин , чтоб не уйти в минус при повторном запуске
void Signal() {
  if (alarm) {
  static unsigned long timeled;
  int i {16};
  do {
   if((millis()-timeled)>=500ul) {
  // digitalWrite(ledPin,!digitalRead(ledPin));
   digitalWrite(buzPin,!digitalRead(buzPin));
   timeled = millis();
   i--;
   }
  }
   while (i>0);
   alarm = false;
   minut = 1;
 }
}
//обратный отсчет времени
  void goTime() {
   static unsigned long timerGo; //отсчет сек
   static bool points; //флаг точек дисплея
   if (shortClick) {
   if (millis()-timerGo >1000) {
    points = !points;
     disp.point(points); //мигаем точками
    timerGo = millis();
    secund--;  
   }
   if (secund < 0) {
    secund = 59;
    minut--; }
   if (minut == 0 && secund == 0) {
    alarm = true; //включаем сигнал
    shortClick = false; //останавливаем отсчет
     }
   }
 }
 
//установка времени
 void setupTimer() {
  if (longClick) {
    secund += 10; }
  if (secund >= 60) {
    secund = 0; 
    minut++; }
  if (minut >= 100) {
    minut = 0;
    secund = 0;
  }
  longClick = false;
}
//кнопка
  void Button() {
  static unsigned long pressTime;
  static bool button;
  static bool push = false;
  button = digitalRead(btnPin);
  
 if (!button && !push) {
  pressTime = millis();
  push = true;
  }
 if (!button && push && millis()-pressTime >= 400ul) {
  pressTime = millis();     
  longClick = true; //флаг на установку времени
  alarm = false;
  }    
 if (button && push) {
  push = false;
  shortClick = !shortClick; //флаг на паузу и пуск отсчета
  alarm = false;
  }
 }

Если дадите полную схему и прямую ссылку на библиотеку, то, возможно, посмотрю.

1 лайк

бэкдоры уже и в микроконтроллеры заложили, кошмаррр!!!

Спасибо.
Библиотека

https://github.com/GyverLibs/GyverTM1637

Схему нарисовал, но не нашел как картинку вставить. Напрямую к плате сопли из МГТФ 3см примерно, кнопка приклеена к дисплею, от нее на землю дисплея сопля и другая на пин5 платы. +5в и земля дисплея берется с платы, от USB запитывается вся схема. Без подтяжек сделано, по такой же схеме часы на кухне работают, но там скетч не мой. Я думал про наводки, но в часах тоже соплями и кнопок там больше. Да и срабатывать корректно все же он может, только не сразу.

Библиотека тут вообще не при чём. Она выводит ровно то, что ей подсовывают.
Для наглядности предлагаю выводить данные в монитор порта.
В обработчике кнопки фигня какая то.

Виноват, сразу не написал. Этот же скетч выводит на oled 128*32, корректно и все нормально работает. При замене дисплея, конечно, мог накосячить, но не нашел, где. А нужен семисегметник.
Обработчик сам лепил, и мне он нравится. Только антидребезг выкинул. Нормально он работает и на 100 байт меньше библиотечных, и короткое и длинное нажатие есть. Придумаю лучше- поменяю. Я только в нем логические состояния поначалу написал, и потом нормально не придумал как их переименовать.
Вот он полный, я понимаю что косячный и все такое. Но лучше пока не умею. Короткое нажатие составляющее длинного. Не придумал еще, как совсем разделить. Для тини85 задумывался, экономил память. Переменную pressTime только переделал в unsigned long, изначально была uint16_t и глючила по переполнению. Опять же в библиотеках вроде используется, но почему не глючит, я самостоятельно не разобрался. Но это другая история.

  #define btnPin 4

void setup() {
  pinMode(1, OUTPUT);
  pinMode(0, OUTPUT);
  pinMode(btnPin, INPUT_PULLUP);
}

void Button() {
  static uint32_t pressTime;
  static bool button, longClick, shortClick;
  static bool push = false;
  button = digitalRead(btnPin);
 if (!button && !push) {
  pressTime = millis();
  push=true;
  }
  else if (!shortClick && push && millis()-pressTime >= 80ul) {
  shortClick = true;
  digitalWrite(0,!digitalRead(0));
  }
  else if (!longClick && push && millis()-pressTime >= 2000ul) {
  longClick = true;
  digitalWrite(1, !digitalRead(1));
  }
  if (button && push) {
  pressTime = millis();
  push = false;
  shortClick = false;
  longClick = false;
 }
}

void loop() {
  Button();
}

Она везде…

и вообще, код написаный не ИИ полная фигня получается
PS полез в свой код, там чуток более 1600 строк, чё я тут понаписал, ногу сломать можно

1 лайк

Скетч часов из примеров на этом дисплее работает. Т.е. дисплей вроде целый. Не могу поймать причину, почему все же кратковременно на еле заметный глазу момент все же вспыхивает 4й разряд, но прибавляется второй.

Ищите, без схемы это не дело.

Разве что так
IMG20241128111903

Не, ну Вы извините, но так не делается. Я Вас просил дать мне полный скетч и схему, чтобы я мог просто собрать это, запустить у себя и посмотреть что там и как. А Вы мне что дали? Где матрица? Как она подключена? Мне самому придумывать как там и что может быть подключено? Чтобы потратить полдня а потом услышать от Вас: “не, у меня тут по-другому всё”. Оно мне надо? Если Вам лень нарисовать схему для решения своей проблемы, то неужели Вы думаете, что кому-то не лень делать это за Вас для решения чужой?

1 лайк

какая матрица, Евгений?
Модуль ТМ1637 это уже готовый дисплей, он подключается по 4м проводам

1 лайк

@Yurik
Похоже что проблема с кнопкой - она и подключена неправильно

и обработчик кривой

Хотя извиняюсь, судя по коду подтяжка на кнопке есть… Что ж Вы сами на себя наговариваете?

Тогда надо смотреть обработчик. Кроме того, что вы “выкинули антидребезг” - в коде видно, что вы неверно определяете короткое и длинное нажатие.
Короткое нажатие надо определять не просто по времени, а по отпусканию кнопки. У вас короткое нажатие фиксируется одновременно с длинным, причем много раз.

1 лайк

Извините, что так нарисовал. МММ прояснил картину. Скетч часов из примеров по этой схеме работает.

Да, подтяжка в коде. Дополнительно не паял.
По поводу обработчика- shortClick фиксируется по отпускании кнопки. Вернее, должен был фиксироваться. И тогда получается либо один раз, либо из-за дребезга много, но тогда это было бы видно- отсчет либо стоял бы на паузе, либо нормально бы работал. А вот длинное да, без короткого отсутствует…

Что-то я никакой проверки на отпускание в этом коде не вижу:

расшифровка этого условия - если кнопка была нажата и от нажатия прошло более 80мс - считаем нажатие коротким.ВСЕ.
Отпущена кнопка или все еще удерживается - на это условие никак не влияет.

Это я ув. kakmyc отвечал, другой вариант. В первом сообщении актуальный.

Изменено позже: Ссылка удалена, т.к. причина ошибки найдена

Положил Ваш код на wokwi.com. Что там не так?
Timer Arduino.ru SHARED - Wokwi ESP32, STM32, Arduino Simulator

1 лайк