LED часы Arduino Nano 3.0, Ds3231,DHT11,MAX7219

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

И еще, зачем Вы делите код при публикации на две части?
Как при этом ссылаться на номер строки?
Ну и с форматированием в коде полный бардак. Единственная возможность хоть что-то понять, скопировать код к себе в IDE и переформатировать.

Вам надо навести порядок в цикле loop(), разгрузить его.
Зачем постоянно опрашивать датчик температуры и RTC? Достаточно 1 раз в секунду. Кнопки опрашивать 1 раз в 10-20 мс.
В моём примере это как раз есть

Ок. принял к сведению.

Код разбиваю, потому что больше 95 почему-то не отображает здесь.

2 лайка
#include <LedControl.h>
#include <iarduino_RTC.h>
#include <DHT11.h>
#include <Wire.h>
#include <VirtualButton.h>
#define VB_DEB 50
#define VB_CLICK 100
struct MyBtn : public VButton {
  MyBtn(uint8_t pin) {
    _pin = pin;
    pinMode(_pin, INPUT_PULLUP);
  }
  bool tick() {
    return poll(!digitalRead(_pin));
  }
  uint8_t _pin;
};
MyBtn setButt(2);
MyBtn upButt(3);
MyBtn downButt(4);
LedControl LC = LedControl(12, 11, 10, 3);
iarduino_RTC watch(RTC_DS3231);
DHT11 dht11(5);
const int brightSetPin = A0;
const int dividerDotsPin = 6;
int dividerDotsState = LOW;
int mode = 0;
long previousMillis = 0;
unsigned long buttonTimer = 0;
void ButtonSetControl();
void ShowTime();
void Divider();
void setup() {
  delay(300);
  Serial.begin(9600);
  watch.begin();
  Wire.begin();
  for (int ledS = 0; ledS < 3; ledS++) {
    LC.shutdown(ledS, false);
    LC.clearDisplay(ledS);
  }
  pinMode(dividerDotsPin, OUTPUT);
  //watch.settime(0,28,18,10,1,24,2)   ;
}
void loop() {
  static byte tik = 0;
  if (millis() - buttonTimer > 20) {
    buttonTimer = millis();
    setButt.tick();
    upButt.tick();
    downButt.tick();
    ButtonSetControl();
  if (tik >= 30) {
      watch.gettime();
      Divider();
      ShowTime();
      tik = 0;
    }
    tik++;
  }
  Serial.println(mode);
}
void ButtonSetControl() {
  watch.blinktime(mode, 2);
  if ((setButt.click()) || (setButt.step())) {
    mode++;
    if (mode > 7) { mode = 0; }
  }
  if (mode) {

    if ((upButt.click()) || (upButt.step())) {
      switch (mode) {
        /* сек */ case 1:
          watch.settime(0, -1, -1, -1, -1, -1, -1);
          break;
        /* мин */ case 2:
          watch.settime(-1, (watch.minutes == 59 ? 0 : watch.minutes + 1), -1, -1, -1, -1, -1);
          break;
        /* час */ case 3:
          watch.settime(-1, -1, (watch.Hours == 23 ? 0 : watch.Hours + 1), -1, -1, -1, -1);
          break;
        /* дни */ case 4:
          watch.settime(-1, -1, -1, (watch.day == 31 ? 1 : watch.day + 1), -1, -1, -1);
          break;
        /* мес */ case 5:
          watch.settime(-1, -1, -1, -1, (watch.month == 12 ? 1 : watch.month + 1), -1, -1);
          break;
        /* год */ case 6:
          watch.settime(-1, -1, -1, -1, -1, (watch.year == 99 ? 0 : watch.year + 1), -1);
          break;
        /* д.н.*/ case 7:
          watch.settime(-1, -1, -1, -1, -1, -1, (watch.weekday == 6 ? 0 : watch.weekday + 1));
          break;
      }
    }
    if ((downButt.click()) || (downButt.step())) {
      switch (mode) {
        /* сек */ case 1:
          watch.settime(0, -1, -1, -1, -1, -1, -1);
          break;
        /* мин */ case 2:
          watch.settime(-1, (watch.minutes == 0 ? 59 : watch.minutes - 1), -1, -1, -1, -1, -1);
          break;
        /* час */ case 3:
          watch.settime(-1, -1, (watch.Hours == 0 ? 23 : watch.Hours - 1), -1, -1, -1, -1);
          break;
        /* дни */ case 4:
          watch.settime(-1, -1, -1, (watch.day == 1 ? 31 : watch.day - 1), -1, -1, -1);
          break;
        /* мес */ case 5:
          watch.settime(-1, -1, -1, -1, (watch.month == 1 ? 12 : watch.month - 1), -1, -1);
          break;
        /* год */ case 6:
          watch.settime(-1, -1, -1, -1, -1, (watch.year == 0 ? 99 : watch.year - 1), -1);
          break;
        /* д.н.*/ case 7:
          watch.settime(-1, -1, -1, -1, -1, -1, (watch.weekday == 0 ? 6 : watch.weekday - 1));
          break;
      }
    }
  }
}
void ShowTime() {
  int temperature = dht11.readTemperature();
  int humidity = dht11.readHumidity();
  int brightSetVol = analogRead(brightSetPin) / 50;
  if (brightSetVol < 0) { brightSetVol = 2; }
  for (int ledS = 0; ledS < 3; ledS++) {
    LC.setIntensity(ledS, brightSetVol);
  }
  LC.setDigit(0, 0, watch.Hours / 10, false);
  LC.setDigit(0, 1, watch.Hours % 10, true);
  LC.setDigit(0, 2, watch.minutes / 10, false);
  LC.setDigit(0, 3, watch.minutes % 10, true);
  LC.setDigit(0, 4, watch.seconds / 10, false);
  LC.setDigit(0, 5, watch.seconds % 10, false);
  switch (watch.weekday) {
    case 0:  //  ПН
      LC.setRow(0, 6, 0b01110110);
      LC.setRow(0, 7, 0b00110111);
      break;
    case 1:  //  ВТ
      LC.setRow(0, 6, 0b01111111);
      LC.setRow(0, 7, 0b00001111);
      break;
    case 2:  //  СР
      LC.setRow(0, 6, 0b01001110);
      LC.setRow(0, 7, 0b01100111);
      break;
    case 3:  //  ЧТ
      LC.setRow(0, 6, 0b00110011);
      LC.setRow(0, 7, 0b00001111);
      break;
    case 4:  //  ПТ
      LC.setRow(0, 6, 0b01110110);
      LC.setRow(0, 7, 0b00001111);
      break;
    case 5:  //  СБ
      LC.setRow(0, 6, 0b01001110);
      LC.setRow(0, 7, 0b00011111);
      break;
    case 6:  //  НД
      LC.setRow(0, 6, 0b00110111);
      LC.setRow(0, 7, 0b00111101);
      break;
  }
  LC.setDigit(1, 0, watch.day / 10, false);
  LC.setDigit(1, 1, watch.day % 10, true);
  LC.setDigit(1, 2, watch.month / 10, false);
  LC.setDigit(1, 3, watch.month % 10, true);
  LC.setDigit(1, 4, 2, false);
  LC.setDigit(1, 5, 0, false);
  LC.setDigit(1, 6, watch.year / 10, false);
  LC.setDigit(1, 7, watch.year % 10, false);
  if (temperature < 0) {
    LC.setRow(2, 0, 0b0000001);
  }
  LC.setDigit(2, 1, temperature / 10, false);
  LC.setDigit(2, 2, temperature % 10, false);
  LC.setRow(2, 3, 0b01100011);
  LC.setRow(2, 4, 0b01001110);
  LC.setDigit(2, 5, humidity / 10, false);
  LC.setDigit(2, 6, humidity % 10, false);
  LC.setRow(2, 7, 0b00110111);
}
void Divider() {
  unsigned long currentMillis = millis();
  int interval = 500;
  if (mode == 0) {
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      dividerDotsState = !dividerDotsState;
      digitalWrite(dividerDotsPin, dividerDotsState);
    }
    if (mode != 0) {
      digitalWrite(dividerDotsPin, LOW);
    }
  }
}

Если не считать того, что watch.blinktime не работает в любом месте программы, то работа программы меня устраивает. Принимаю замечания и советы, если есть. Спасибо.

Что это значит:

  • watch.blinktime не работает ни в каком месте программы
  • watch.blinktime работает, но не в любом месте программы

?

№1
Мне непонятны Ваши манипуляции с переменной tik. Получается, что Вы обновляете экран каждые 600мс. Зачем? Там же ничего не меняется в половине случаев. А даже когда поменялось, то Вы обновляете не в момент смены секунды, а когда попало. В этих часах есть штатная “функция выдать прерывание в момент смены секунды (минуты)”. Вот тогда и надо обновлять экран. Зачем его обновлять когда ничего не изменилось или, наоборот, пропускать момент, когда изменилось что-то?

№2
Опять, про то же - Вы запрашиваете температуру и влажность каждые 600 мс. Зачем так часто? Хватило раз минут в пять-десять - нет?

1 лайк

Здравствуйте,

  1. При обновлении раз в 600 мс нормально отображается смена секунд, если меньше то секунды сменяются неравномерно;
  2. Про штатную “функцию выдать прерывание в момент смены секунды (минуты)" я не в курсе, опишите, пожалуйста, вкратце или дайте ссылку где можно самому прочитать. В конкретно этой библиотеке есть только функция period(), которая задает период чтения с модуля в минутах, а я хочу чтобы отображалось время непосредственно с RTC.
  3. Функция blinktime в этой библиотеке отвечает за мигание значения настраиваемого параметра(время, дата и т.д.), где я только не пытался ее применить - она не работает, даже когда я прописываю ее в loop с конкретными аргументами без переменных.

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

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

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

Секунды меняются с периодом 1000 мс, 600 при этом ни разу не кратная величина, т.е. у вас секунды обновляются не нормально, а раз в 1,2 секунды, а в какой-то момент перескакивают сразу на две. Если у вас неравномерно отображаются секунды при обновлении раз в 500 мс, значит вы что-то делаете неправильно

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

Смена температуры в помещении - процесс очень медленный, поэтому частые запросы бесполезны. Достаточно запрашивать раз в минуту, а то и реже

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

Сразу на две не перескочат, могут лишь обновиться два раза за секунду, но это не страшно.
Хотя сам делаю по прерыванию от модуля, но это как ТС потянет, на первый то раз…

Проще написать свою функцию: если идёт установка времени, то через определённый промежуток времени выводим на экран “пустое место”,(тоже на определённый промежуток времени), согласно mode

Естественно, не страшно. Просто неравномерно, что ему (ТС) таки не нравится:

Я так понял, наоборот, его всё устраивает( если 600мс) - а там , хозяин - барин))
Для первого скетча неплохо ИМХО, но можно лучше)))

Его не устраивает неравномерность, а то, что раз в пять-шесть секунд секунды проскакивают два раза за секунду, его устраивает? ))
Что-то он просто делает не так.

Я ему сразу сказал, что он взялся за пока неподъемный для себя проект ))

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