7seg на hc595 4digit

Обсуждаем контроллеры компании Atmel.
Ответить
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

Martian, значит пока я не во всем досконально разобрался. Буду дальше измерять наблюдать.
Starichok51 писал(а):может хватит оффтопит про терморезисторы в этой теме?
ок, так вот теперь по теме

прибавил в код еще кнопку, что бы переключать режимы на индикаторе: температуру , гадзинник, хвилины, год и так по кругу и заметил странную особенность, четыре сегмента в режиме часов горят одинаково и с хорошей яркостью, а вот минуты - 2 правых сегмента, яркость почему то снизилась вдвое, год - первый сегмент слева с хорошей яркостью (2), а вот сегменты 024 уже более низкой яркости, в чем может быть загвоздака
привожу код:
Спойлер

Код: Выделить всё

#include "RTClib.h"
RTC_DS1307 rtc;

#include <GyverNTC.h>
GyverNTC therm(0, 10000, 3950);
//---- ПИНЫ ----
byte SCLK = 7;
byte RCLK = 6;
byte DIO = 5;
//---- ПИНЫ ----

#include <TM74HC595Display.h>
#include <TimerOne.h>
#include <Button.h>
TM74HC595Display disp(SCLK, RCLK, DIO);

unsigned long dispIsrTimer, countTimer, countSerial;

const int buttonPin = 2;
Button button(buttonPin);
int buttonPressCount = 0;

void setup() {
  Serial.begin(57600);
  rtc.begin();
  button.begin(); 
}

void loop() {


    // Обновляем состояние кнопки
  button.read();

  // Проверяем, было ли нажатие кнопки
  if (button.pressed()) {
    // Увеличиваем счетчик нажатий на кнопку
    buttonPressCount++;
    disp.clear(); 
}
    // Выполняем действие в зависимости от значения счетчика нажатий
    switch (buttonPressCount) {
      case 1:
        
        Serial.println("Выполняется действие 1");
        if (millis() - countTimer > 500) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)         
             DateTime now = rtc.now();
             int displaytime = (now.second());
             disp.digit4(displaytime); 
         
  
             countTimer = millis();            // сбросить таймер
            }       
        break;
      case 2:
        Serial.println("Выполняется действие 2");
     if (millis() - countTimer > 1000) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)         
             DateTime now = rtc.now();
             int displaytime = now.year();
             disp.digit4(displaytime); 
             countTimer = millis();            // сбросить таймер
            }        
        break;
      case 3:
        Serial.println("Выполняется действие 3");
        if (millis() - countTimer > 1000) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)         
             DateTime now = rtc.now();
             int displaytime = ((now.month() * 100) + now.day());
             disp.float_dot(therm.getTempAverage(), 1);  
             //disp.digit4(displaytime); 
             countTimer = millis();            // сбросить таймер
            }        
        break;
      // Если было больше трех нажатий, счетчик сбрасывается
      default:
       if (millis() - countTimer > 1000) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)         
             DateTime now = rtc.now();
             int displaytime = ((now.hour() * 100) + now.minute());
             disp.digit4(displaytime); 
             countTimer = millis();            // сбросить таймер
            }
        buttonPressCount = 0;
        break;
    }
  
  
  disp_isr();                         // динамическая индикация
 
}

void disp_isr() {
  if (micros() - dispIsrTimer > 300) {       // таймер динамической индикации (по-русски: КОСТЫЛЬ!)
    disp.timerIsr();                         // "пнуть" дисплей
    dispIsrTimer = micros();                 // сбросить таймер
  }
}
описание библиотеки:
Спойлер

Код: Выделить всё

/*
   Пример работы с дисплеем на микросхеме TM74HC595
   Динамическая индикация осуществляется "вручную" таймером на micros()
   AlexGyver Technologies http://alexgyver.ru/
*/

/*
  Основные методы библиотеки:
  disp.set(X, port);             // вывести 16 ричный код X в порт port (либо элемент массива SYM!!!)

  // вывести двухзначное число value на порт port (0 - первый и второй порт, 2 - 2 и 3, 3 - 3 и 4 порты))
  disp.digit2(value, port);

  disp.digit4(value);            // вывести число value
  disp.digit4showZero(value);    // вывести число value с нулями СЛЕВА

  disp.float_dot(value, pos);    // вывести float число value с точкой СПРАВА по счёту pos
  disp.int_dot(value, pos);      // вывести int число value с точкой СПРАВА по счёту pos

  disp.clear();                  // очистить дисплей
  *порты идут справа налево! (3 2 1 0)
*/
Реклама
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

если вернуть предыдущий вариант, яркость в норме? Ну, аппаратный вариант причины исключить чтоб
Контактная информация:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

Martian, яркость в норме тольок если показывает время, даже в этом варианте.
Друг Кота
Аватара пользователя
Сообщения: 15592
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Динамическая индикация обычно увязана и со сканированием кнопок.
Для удобства используем кнопки на позиционных ключах плюс контрольный вход.
В данном случае теоретически 4 кнопы прицепить можно (и варианты с одновременным нажатием группы кнопок).
Основная программа получает уже готовый результат от сканера в виде байтика данных (плюс флаг запроса - то уж на усмотрение).
:roll:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

Вряд ли тут дело в кнопках.
Надо обновление дисплея всё-таки отделить от тела основной программы, без всяких костылей.

У того же alexgyver есть же пример: https://alexgyver.ru/lessons/timer-isr/

Вот и сделать так:

Код: Выделить всё

void setup()
{
  ....
  // запустим второй таймер
  Timer2.setPeriod(10000);       // Устанавливаем период таймера 10000 мкс -> 100 гц
  Timer2.enableISR(CHANNEL_A);   // Или просто .enableISR(), запускаем прерывание на канале А таймера 2
}

ISR(TIMER2_A)
{  
  disp.digit4(displaytime);
}
Что в итоге получаем:
1. переменная displaytime станет глобальной и объявлена один раз. Может это и невыгодно, зато наглядно, а не разбросано по всему коду int display
2. вызов функции disp.digit4(displaytime) теперь один раз, нет нужды его вызывать в куче мест и думать о ней, и если захотим изменить (например, выводить точку) - это тоже делается в одном месте.
3. гарантированную частоту обновления дисплея, а значит, теперь доступна регулировка яркости.

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

И в итоге, должно получится что-то такое:
Спойлер

Код: Выделить всё

#include "RTClib.h"
RTC_DS1307 rtc;

#include <GyverNTC.h>
#include "GyverTimers.h"
#include <TM74HC595Display.h>
#include <TimerOne.h>
#include <Button.h>

GyverNTC therm(0, 10000, 3950);
//---- ПИНЫ ----
byte SCLK = 7;
byte RCLK = 6;
byte DIO = 5;
//---- ПИНЫ ----

TM74HC595Display disp(SCLK, RCLK, DIO);

unsigned float displaytime ;
Button button(2);
unsigned char buttonPressCount = 0;

void setup()
{
   Serial.begin(57600);
   rtc.begin();
   button.begin();
   // запустим второй таймер
   Timer2.setPeriod(10000);       // Устанавливаем период таймера 10000 мкс -> 100 гц
   Timer2.enableISR(CHANNEL_A);   // Или просто .enableISR(), запускаем прерывание на канале А таймера 2
}

void loop()
{
   button.read();// Обновляем состояние кнопки   
   if (button.pressed())// Проверяем, было ли нажатие кнопки
   {   
      buttonPressCount++;// Увеличиваем счетчик нажатий на кнопку
   }
   DateTime now = rtc.now();
   switch (buttonPressCount)   // Выполняем действие в зависимости от значения счетчика нажатий
   {
      case 1: 
         Serial.println("Выполняется действие 1");    
         displaytime = now.second();    
         break;
      case 2:
         Serial.println("Выполняется действие 2");          
         displaytime = now.year();
         break;
      case 3:
         Serial.println("Выполняется действие 3");
         displaytime  = therm.getTempAverage();
         break;     
      default:     
          displaytime  = ((now.hour() * 100) + now.minute());
          buttonPressCount = 0;// Если было больше трех нажатий, счетчик сбрасывается
          break;
    }
}

/*** Дисплей ***/
ISR(TIMER2_A)
{  
   if (buttonPressCount  == 3)
   {
      disp.float_dot(displaytime, 1);
   }
   else
   {
      disp.digit4((unsigned int)displaytime);
   }
}
Как-то так. Компактно, просто, читабельно и логично.
Может быть, даже заработает :)
Контактная информация:
Реклама
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

olegue писал(а):бы и сам показывал и на web-сервер передавал.
в соседней теме делали...
дом_2.jpg
(196.83 КБ) 46 скачиваний
olegue писал(а):хотелось бы разбросать их по дому, котел, гараж и через nrf24 соединить их с базой
тоже делали...
Схема_5.jpg
(62.78 КБ) 47 скачиваний
есть и другие модули... у них потребление меньше... аккума на дольше хватает...
Схема_6.jpg
(70.25 КБ) 54 скачивания
короче... всё уже делали))
:tea:

Добавлено after 5 minutes 10 seconds:
olegue писал(а):яркость в норме тольок если показывает время, даже в этом варианте.
связался ты с динамической индикацией))
у статической таких проблем нет...
динамическая индикация оправдана только когда много пикселей... типа больших панелей... и т.д.
1.jpg
(93.27 КБ) 46 скачиваний
а делать динамическую индикацию для простенького LED индикатора... не вижу никакого смысла))
:tea:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

[uquote="Martian",url="/forum/viewtopic.php?p=4546086#p4546086"]Может быть, даже заработает :)[/uquote]

Не заработало. Где -то в районе таймера проблема.
1. переменная displaytime станет глобальной и объявлена один раз. Может это и невыгодно, зато наглядно, а не разбросано по всему коду int display
Но эта идея очень правильная , как минимум не задваивается код
Но я нашел из за чего яркость у меня глючит.
убрал строки отладочные строки :

Код: Выделить всё

// Serial.println("Выполняется действие 2");
и все стало ОК

Добавлено after 41 minute 38 seconds:
[uquote="olegue",url="/forum/viewtopic.php?p=4546386#p4546386"]
1. переменная displaytime станет глобальной и объявлена один раз. Может это и невыгодно, зато наглядно, а не разбросано по всему коду int display
Но эта идея очень правильная , как минимум не задваивается код[/uquote]

но после переделки кода
Спойлер

Код: Выделить всё

#include "RTClib.h"
RTC_DS1307 rtc;

#include <GyverNTC.h>
GyverNTC therm(0, 10000, 3950);
//---- ПИНЫ ----
byte SCLK = 7;
byte RCLK = 6;
byte DIO = 5;
//---- ПИНЫ ----

#include <TM74HC595Display.h>
#include <TimerOne.h>
#include <Button.h>
TM74HC595Display disp(SCLK, RCLK, DIO);

unsigned long dispIsrTimer, countTimer;

const int buttonPin = 2;
Button button(buttonPin);
int buttonPressCount = 0;

int displaytime;
float displaytemp;

void setup() {
  Serial.begin(57600);
  rtc.begin();
  button.begin(); 
}

void loop() {


    // Обновляем состояние кнопки
  button.read();
  DateTime now = rtc.now();
  // Проверяем, было ли нажатие кнопки
  if (button.pressed()) {
    // Увеличиваем счетчик нажатий на кнопку
    buttonPressCount++;
    disp.clear(); 
    
}
    // Выполняем действие в зависимости от значения счетчика нажатий
    switch (buttonPressCount) {
      case 1:
              displaytime = (now.second());break;
      case 2:
              displaytime = now.year();break;        
      case 3:
              displaytemp = therm.getTempAverage();break;        
      // Если было больше трех нажатий, счетчик сбрасывается
      default: 
             displaytime = ((now.hour() * 100) + now.minute());
        buttonPressCount = 0;
        break;
    }

     if (millis() - countTimer > 1000) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)         

                 if (buttonPressCount  == 3)  {disp.float_dot(displaytemp, 1); }
                 else
                 {disp.digit4(displaytime);}
                 countTimer = millis();            // сбросить таймер
            }        
  
  disp_isr();                         // динамическая индикация
 
}

void disp_isr() {
  if (micros() - dispIsrTimer > 300) {       // таймер динамической индикации (по-русски: КОСТЫЛЬ!)
    disp.timerIsr();                         // "пнуть" дисплей
    dispIsrTimer = micros();                 // сбросить таймер
  }
}
полчил те же проблемы с неоднородной яркостью. чудеса!!!
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

С динамической индикацией никаких проблем нет. Мало того. Статика это потребление большего тока по сравнению с динамикой. А это немаловажно. При выборе источника питания.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 15592
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Это если нет взаимоперекрывающихся процессов (обработка дисплея идет на прерываниях или остальные части программы заметно меньше, чем время индикации одной позиции с учетом интервалов обработки и вывода данных).
Если чего-то или неравномерно высвечивает или "мерцает" - где-то программная ошибка.
В случае самостоятельно написанной прожки разобраться легче, а при использовании нескольких библиотек - то покопаться придется...
Serial.println(val, format) ведь немало времени занимает (учитывать скорость передачи).
:roll:
Друг Кота
Сообщения: 9175
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

Сообщение roman.com »

Demiurg писал(а):С динамической индикацией никаких проблем нет.
С динамической индикацией проблемы есть - портится зрение)).
Demiurg писал(а):Мало того. Статика это потребление большего тока по сравнению с динамикой. А это немаловажно. При выборе источника питания.
чё ?
:shock:
закон сохранения энергии уже отменили ? ))
:))
Модератор
Аватара пользователя
Сообщения: 19055
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

roman.com, и чё?
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

Del
Последний раз редактировалось Demiurg Вс фев 25, 2024 19:57:21, всего редактировалось 1 раз.
Контактная информация:
Модератор
Аватара пользователя
Сообщения: 19055
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

Demiurg, 1. не надо обзываться. оскорбления запрещены правилами форума.
2. не надо портить сделанную цитату. у тебя получилось, что это были твои слова, а не его. выглядит так, что ты обозвал себя самого.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4547575#p4547575"]Demiurg, 1. не надо обзываться. оскорбления запрещены правилами форума.
2. не надо портить сделанную цитату. у тебя получилось, что это были твои слова, а не его. выглядит так, что ты обозвал себя самого.[/uquote]
Пардон...

Добавлено after 8 minutes 27 seconds:
Статика. Это потребление всех сегментов и знакомест. В отдельно взятый момент времени. А динамика это потребление сегментов одного знакоместа в отдельно взятый момент времени. И что ты хотел сказать про закон сохранения энергии. Я совсем не понил.
Последний раз редактировалось Demiurg Вс фев 25, 2024 20:02:45, всего редактировалось 1 раз.
Контактная информация:
Друг Кота
Сообщения: 12867
Зарегистрирован: Сб дек 18, 2021 19:25:32

Сообщение Martian »

То, что количество энергии, необходимое для обеспечения приемлемой яркости, может оказаться достаточно близким в обоих случаях. Однако, roman.com всё равно ляпнул чушь про вред динамической индикации (притом, глядя в монитор с той самой динамической индикацией, смотря в детстве телевизор с той самой динамической индикацией...) и не учитывает то, что инерция человеческого глаза не требует прямой пропорциональности, особенно для зелёного цвета. Зелёный индикатор с динамической индикацией при той же видимой (человеческим глазом) яркостью будет экономичнее, чем со статической индикацией. Потерями в переходных процессах ключей здесь можно пренебречь.
С жёлтыми светодиодами у меня был небольшой выигрыш в экономичности, но всё-таки был. А ещё roman.com не понимает, что с ростом числа светодиодов общее потребление всей системы уменьшается при динамической индикации, а статическая может оказаться вообще невозможной.
Но другого от него сложно ожидать.
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1405
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

Так мы, глядишь, и до вечного двигателя дойдём.)
Модератор
Аватара пользователя
Сообщения: 19055
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

на самом деле при 4 разрядах при динамике не нужно увеличивать ток в 4 раза по сравнению со статикой.
даже можно оставить тот же ток, как и при статике - инерция глаз даст практически ту же яркость.
у меня в термометрах ток сегмента 4-7 мА, в зависимости от напряжения на аккумуляторе, а видно прекрасно.
так что, статика при 4 разрядах по потреблению проигрывает в 4 раза против динамики.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Друг Кота
Аватара пользователя
Сообщения: 3784
Зарегистрирован: Ср дек 24, 2008 09:58:58

Сообщение Ser60 »

О - пока писал опередили. Полностью согласен с предыдущим постом.
На примере индикаторов с 4 цифрами, при динамической индикации глаз видит каждую отдельную цифру в течении 1/4 части всего времени. Соответственно, яркость цифры будет меньше, чем при статической индикации при том же токе через сегменты. Учитывая, что зависимость яркости большинства светодиодов от тока близка к логарифмической (с неким коэффициентом, может быть даже близка к линейной в зависимости от модели), для получения той же яркости цифр при динамической индикации следует увеличивать ток через светодиоды экспоненциально (или, как минимум, также линейно). Но тут ещё накладывается нелинейность самого глаза (эта зависимость также близка к логарифмической) и зависимость его чувствительности от цвета. В результате токопотребление дисплея за период развёртки всех цифр может быть как больше, так и меньше чем при статической. Однако, скорее больше, чем меньше.
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44

Сообщение Demiurg »

[uquote="Ser60",url="/forum/viewtopic.php?p=4547804#p4547804"]...[/uquote]
Тьфу, йопт. Пардон. Не сдержался....
4 разряда. 7 сегментов. Про точку я уже молчу. Пусть 10 мА. Это уже 280 мА. Статика. Динамика. Один разряд. 70 мА. На конкретно взятый момент времени. И я уже могу выбирать другой источник питания. Это вопрос цены.
Если мы говорим о самоделках. Ну тогда да. Там вопрос цены не стоит.
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

Вот есть у меня 3 одинаковых индикатора по 4 цифры каждый. Как к ардуине подключить что бы они показывали одноверменно 3 температуры от трех разных датчиков?
Ответить

Вернуться в «AVR»