7seg на hc595 4digit

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Сообщения: 9570
Зарегистрирован: Вт мар 13, 2012 12:16:13
Откуда: .ru

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

olegue писал(а):ардуинка на Атмега8 уже показывает температуру...
простейший вариант - добавить вторую ардуину на Атмега8... и пачку резисторов... и больше ничего не нужно))
остальноё всё делается программно...
но мы же не ищем лёгких путей))
:tea:
[uquote="roman.com",url="/forum/viewtopic.php?p=4542905#p4542905"]лучше добавить к LED индикатору буфер... типа D-триггер... и писать в буфер...[/uquote]
простейший D-триггер... любителем рассыпухи... и сложных путей))
Screenshot_1.jpg
(5.36 КБ) 68 скачиваний
:))
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Нацарапал прожку с "движком" на прерывании и примитив-тестом (для ардуино-нано на меге328)...
К сожалению НЕ ПРОВЕРЕНО на железе (т.е. возможны и ошибки, особенно в позиционных номерах выходных линий регистров). Исходил из предположения, что время исполнения функции shiftOut (по Гайверу) равно 117 микросекунд...
После компиляции:
"Скетч использует 1846 байт (6%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 46 байт (2%) динамической памяти, оставляя 2002 байт для локальных переменных. Максимум: 2048 байт."...
disp4a.zip
(4.14 КБ) 77 скачиваний
:roll:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

BOB51,


Изображение Изображение


бежит счетчит, только вот 0 незначащий не рисует, может так и задумывалось?

Добавлено after 5 minutes 6 seconds:
Изображение


и на Атмеге8 не хочет работать, нет регистра
disp4a:180:29: error: 'OCIE0A' was not declared in this scope
OCR0A = 100; TIMSK0 |= (1<<OCIE0A);
^~~~~~
C:\Users\KDFX Modes\AppData\Local\Temp\Rar$DIa7032.24454\disp4a\disp4a.ino:180:29: note: suggested alternative: 'OCIE1A'
OCR0A = 100; TIMSK0 |= (1<<OCIE0A);
^~~~~~
OCIE1A
exit status 1
'OCR0A' was not declared in this scope
Можно сделать универсально?
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

А во втором разряде другие циферки высвечиваются?
Там по тесту счетчик от 0 до 9999 - должны все цифирьки на табло высвечиваться.
Частота регенерации 62,5 Гц.
:roll:
Насчет массива и знакогенератора - там всего-то 16 позиций. Добавлять progmem смысла нету - "кейсы" по такому же принципу работают.
Однако ежли там будут не только 0-F, то уже надо без зкогенератора обходиться - это уже "часть теста"(прикладной программы) решать должна.
8)
Чуток тестовый фрагмент подправил (на скору руку)
disp4a.zip
(4.15 КБ) 77 скачиваний
:roll:
Последний раз редактировалось BOB51 Ср фев 14, 2024 20:32:34, всего редактировалось 1 раз.
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

[uquote="BOB51",url="/forum/viewtopic.php?p=4543511#p4543511"]А во втором разряде другие циферки высвечиваются?[/uquote]
конечно, все ок, кроме нулей
Реклама
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Нулями заведует фрагмент теста (преобразование из двоичного в двоично-десятичный):
Спойлер

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

// обработка текущего значения Dcnt и
  // вывод двоично-десятичных значений в массив TrmDat
 temp = Dcnt;
 if (temp == 0)
  { for (byte m = 0; m <= 3; m++){ TrmDat[m] = fnt_0; } }
 else 
  { if (temp >= 1000)
     { TrmDat[0] = temp / 1000; temp = temp % 1000; }
    else if(temp < 1000){ TrmDat[0] = fnt_0; }
    if (temp >= 100)
     { TrmDat[1] = temp / 100; temp = temp % 100; }
    else if(temp < 100){ TrmDat[1] = fnt_0; }
    if (temp >= 10)
     { TrmDat[2] = temp / 10; temp = temp % 10; }
    else if(temp < 10){ TrmDat[2] = fnt_0; }
    TrmDat[3] = temp;
  }
  // перекодировка в сегментный код
  for (byte m = 0; m <= 3; m++)
   { TrmDat[m] = znak(TrmDat[m]); }
  // если флаг запроса сброшен
  // выставить флаг запроса на обноление данных на индикаторе
  if (!QtVrLd){ QtVrLd = 1; }
  // выждать время удержания изображения
  delay (200);
  // приращение демосчетчика Dcnt
  Dcnt++;
  if (Dcnt >= 10000){ Dcnt = 0; }
}
Это уже подправленный вариант.
:roll:
Насчет фокуса с прерыванием по OCR0A - Это поддерживается в 48й, 88й и 328й мегах.
Есть и другой вариант - через TONE и INT1/INT0.
Или смотрим начинку МК и не задействованный в основной программе таймер (функции ШИМ и чего еще может быть). надо вчитываться в документацию и по МК и по IDE...
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3794
Зарегистрирован: Ср дек 24, 2008 09:58:58

Сообщение Ser60 »

BOB51 - а ради интереса, можете проверить сколько места занимает библиотечная (или какая иная) реализация I2C протокола ориентированная на аппаратный драйвер (т.е., без "ногодрыга") на таком МК?
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Библиотеки ориентированы на аппаратные модули с жесткой привязкой к выводам МК.
А вот shiftIn/shiftOut - это встроенные программной реализации функции, работающие с любыми цифровыми выводами МК (по сути вариант протокола SPI).
Касательно библиотек I2C и SPI - я ими пока не пользовался (из-за неудобства по разводке выводов и оставил для тех устройств, где применение оправдано/обязательно) ... Делал только собственный вариант программного I2C для RTC да использовал часть библиотеки OneWire и Adafruit_NeoPixel - их не обойти (быстродействие).
Может когда посмотрю чего там...
:roll:
Кстати... Можете на сайте у Гайвера (https://alexgyver.ru/lessons/)обзоры глянуть - там попадаются довольно неплохие описания и характеристики функционала IDE в дополнение к "референсу" (https://docs.arduino.cc/programming/)...
8)
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

[uquote="BOB51",url="/forum/viewtopic.php?p=4543525#p4543525"]Нулями заведует фрагмент теста (преобразование из двоичного в двоично-десятичный):
Спойлер

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

// обработка текущего значения Dcnt и
  // вывод двоично-десятичных значений в массив TrmDat
 temp = Dcnt;
 if (temp == 0)
  { for (byte m = 0; m <= 3; m++){ TrmDat[m] = fnt_0; } }
 else 
  { if (temp >= 1000)
     { TrmDat[0] = temp / 1000; temp = temp % 1000; }
    else if(temp < 1000){ TrmDat[0] = fnt_0; }
    if (temp >= 100)
     { TrmDat[1] = temp / 100; temp = temp % 100; }
    else if(temp < 100){ TrmDat[1] = fnt_0; }
    if (temp >= 10)
     { TrmDat[2] = temp / 10; temp = temp % 10; }
    else if(temp < 10){ TrmDat[2] = fnt_0; }
    TrmDat[3] = temp;
  }
  // перекодировка в сегментный код
  for (byte m = 0; m <= 3; m++)
   { TrmDat[m] = znak(TrmDat[m]); }
  // если флаг запроса сброшен
  // выставить флаг запроса на обноление данных на индикаторе
  if (!QtVrLd){ QtVrLd = 1; }
  // выждать время удержания изображения
  delay (200);
  // приращение демосчетчика Dcnt
  Dcnt++;
  if (Dcnt >= 10000){ Dcnt = 0; }
}
Это уже подправленный вариант.
:roll:[/uquote]

Не помогло. Все на месте. Нулей нет.

Добавлено after 20 minutes 3 seconds:
[uquote="Ser60",url="/forum/viewtopic.php?p=4543539#p4543539"]BOB51 - а ради интереса, можете проверить сколько места занимает библиотечная (или какая иная) реализация I2C протокола ориентированная на аппаратный драйвер (т.е., без "ногодрыга") на таком МК?[/uquote]

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

#include <OneWire.h>
/*------------------------------------------------*/
#define ONE_WIRE_BUS 4 // вывод, к которому подключён DS18B20
OneWire oneWire(ONE_WIRE_BUS);
void setup(){}
void loop(){}

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

Скетч использует 2068 байт (6%) памяти устройства. Всего доступно 32384 байт.
Глобальные переменные используют 46 байт (2%) динамической памяти, оставляя 2002 байт для локальных переменных. Максимум: 2048 байт.
Добавлено after 6 minutes 26 seconds:
[uquote="BOB51",url="/forum/viewtopic.php?p=4543525#p4543525"]Насчет фокуса с прерыванием по OCR0A - Это поддерживается в 48й, 88й и 328й мегах.
Есть и другой вариант - через TONE и INT1/INT0.
Или смотрим начинку МК и не задействованный в основной программе таймер (функции ШИМ и чего еще может быть). надо вчитываться в документацию и по МК и по IDE...[/uquote]

У гайвера на micros() сделано:

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

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

#include <TM74HC595Display.h>
#include <TimerOne.h>
TM74HC595Display disp(SCLK, RCLK, DIO);
unsigned char SYM[18];
unsigned long dispIsrTimer, countTimer;
float value = 0.0;

void setup() {
  
}

void loop() {
  if (millis() - countTimer > 1000) {   // каждые 50 миллисекунд ("прозрачный" аналог delay)
    value += 0.01;                    // прибавить 0.01
  
  disp.float_dot(therm.getTemp(),1);
    countTimer = millis();            // сбросить таймер
  }

  disp_isr();                         // динамическая индикация
}

void disp_isr() {
  if (micros() - dispIsrTimer > 300) {       // таймер динамической индикации (по-русски: КОСТЫЛЬ!)
    disp.timerIsr();                         // "пнуть" дисплей
    dispIsrTimer = micros();                 // сбросить таймер
  }
}
void disp_isr() {
if (micros() - dispIsrTimer > 300) { // таймер динамической индикации (по-русски: КОСТЫЛЬ!)
disp.timerIsr(); // "пнуть" дисплей
dispIsrTimer = micros(); // сбросить таймер
}
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Основная задача - сделать сканирование самостоятельным процессом.
micros - это также часть основной программы. Рабочая версия, но несколько более простая.
Второе - счетчик не бесконечен - надо переполнение учитывать при длительной работе.
Посмотрю, где там у меня в преобразователе ошибка - но то уже больше вопрос теста, чем самой индикации.
8)
Ну вот и ошибку отловил - причина НЕВНИМАТЕЛЬНОСТЬ - вместо цифирьки запихнул сразу сегментный код! (перекодировка там ниже отдельно выполняется, а инверсия в обработчике прерывания).
Надо было так:
Спойлер

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

temp = Dcnt;
 if (temp == 0)
  { for (byte m = 0; m <= 3; m++){ TrmDat[m] = 0; } }
 else 
  { if (temp >= 1000)
     { TrmDat[0] = temp / 1000; temp = temp % 1000; }
    else { TrmDat[0] = 0; }
    if (temp >= 100)
     { TrmDat[1] = temp / 100; temp = temp % 100; }
    else { TrmDat[1] = 0; }
    if (temp >= 10)
     { TrmDat[2] = temp / 10; temp = temp % 10; }
    else { TrmDat[2] = 0; }
    TrmDat[3] = temp;
  }
:facepalm:
Вот теперича работать точно будет:
disp4a.zip
(4.14 КБ) 60 скачиваний
:hunger:
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

[uquote="BOB51",url="/forum/viewtopic.php?p=4543570#p4543570"]Ну вот и ошибку отловил - причина НЕВНИМАТЕЛЬНОСТЬ - вместо цифирьки запихнул сразу сегментный код!
Надо было так:
Спойлер

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

temp = Dcnt;
 if (temp == 0)
  { for (byte m = 0; m <= 3; m++){ TrmDat[m] = 0; } }
 else 
  { if (temp >= 1000)
     { TrmDat[0] = temp / 1000; temp = temp % 1000; }
    else { TrmDat[0] = 0; }
    if (temp >= 100)
     { TrmDat[1] = temp / 100; temp = temp % 100; }
    else { TrmDat[1] = 0; }
    if (temp >= 10)
     { TrmDat[2] = temp / 10; temp = temp % 10; }
    else { TrmDat[2] = 0; }
    TrmDat[3] = temp;
  }
:facepalm:
Вот теперича работать точно будет:
disp4a.zip
:hunger:[/uquote]

Да!Теперь с нулями бегает , но незначащие нули спереди пишет.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Это уже "вопросы основной программы" - что заложим, то и покажет.
Главное основной сканер динамической индикации работает, а что он будет выводить на индикацию это циферки (или чего другого) из массива TrmDat[5].
Причем ячейки 0-3 там под цифирь, а старшая тетрада 4й ячейки - управление внешними светиками и служебными линиями (младшая тетрада - то позиционные ключи).
Заодно и знакогенератор "кракозябр" семисегментных прилагается.
Запятую или произвольные символы надо вводить после фрагмента перекодировки в сегментный код, перед установкой флага запроса на перенос данных в массив vram.
8)
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Нее...
То уже вопрос основной программы - что напишем, то и выведет на индикацию.
Если напрямую загружать "кракозябрами" массив предподготовки (без преобразования через знакогенератор) то выводить будет все, что загружено. Минимальный интервал между выводом в одну строку развертки со стороны контроллера динамической индикации (раз в 0,016 секунды), а со стороны основной программы - от момента установки флага запроса до точки переноса примерно такой же (или меньше - в зависимости от того, в какой момент относительно работы сканера был установлен флаг запроса).
Собственно это защита от "случайного сбоя" - индикация меняется только по окончании вывода предыдущей строки (нету "разрыва" индикации).
Но... гашения между выводом позиций также нету - это дополнительное время. Понадеемся на эффект быстродействия по переносу из сдвигового регистра в защелку у 595ых. У кого "живьем" - проверьте на "мерцание/паразитную засветку" как ощущение от индикаторов будет (не устают ли глаза при наблюдении).
Хоша... теоретически можно поставить "гасящий вывод" - один из слотов интервала задержки еще свободен... Но то уже если очень припечет...
Вобщем... похоже таки можно применять этот алгоритм...
8)
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

Фото - не то же, что глазом ощущать...
:wink:
Второй нюанс - какова будет реакция устройства при совместном применении критичных по времени (и разрыву протокола обмена) этого варианта динамической индикации и библиотек Adafruit_NeoPixel и OneWire?...
То проверять надо...
:dont_know:
У меня есть подобное применение прерывания по OCR0A совместно с термометром-показометром на DS18B20(проект К145М что на котуинке лежит), но там не столь плотно интервал занят - прерывание только флажок ставит. А тут один из слотов почти полностью заполнен.
Для некритичных ко времени и приостановке протоколов обмена и тех, что основаны на аппаратных модулях МК (UART, SPI, I2C) динамическая индикация на основе прерывания не повлияет.
:roll:
Модератор
Аватара пользователя
Сообщения: 19100
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

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

Сообщение OKF »

Какое там ещё ветвление?)

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

void printInt(uint16_t bin) {
  char chr = ' ';
  for (uint16_t div = 1000; div > 1; div /= 10) {
    uint8_t d = bin / div;
    if (chr != ' ' || d)
      chr = d + '0';
    printChar(chr);
    bin %= div;
  }
  printChar(bin + '0');
}
Исправить под себя.
Собутыльник Кота
Аватара пользователя
Сообщения: 2977
Зарегистрирован: Сб май 21, 2016 11:04:52
Откуда: Беларусь

Сообщение olegue »

[uquote="BOB51",url="/forum/viewtopic.php?p=4543606#p4543606"]У кого "живьем" - проверьте на "мерцание/паразитную засветку" как ощущение от индикаторов будет (не устают ли глаза при наблюдении).

8)[/uquote]

На мой взгляд индикатор засвечен равномерно, индикация спокойная без каких либо артефактов.

Добавлено after 5 minutes 5 seconds:
[uquote="OKF",url="/forum/viewtopic.php?p=4543707#p4543707"]Какое там ещё ветвление?)
Спойлер

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

void printInt(uint16_t bin) {
  char chr = ' ';
  for (uint16_t div = 1000; div > 1; div /= 10) {
    uint8_t d = bin / div;
    if (chr != ' ' || d)
      chr = d + '0';
    printChar(chr);
    bin %= div;
  }
  printChar(bin + '0');
}
Исправить под себя.[/uquote]
Нонешние методики программирования не то что давешние.
Друг Кота
Аватара пользователя
Сообщения: 15778
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

В принципе не так уж сложно незначащие нули в моем тест - примере погасить.
Находим фрагмент:
Спойлер

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

  // перекодировка в сегментный код
  for (byte m = 0; m <= 3; m++)
   { TrmDat[m] = znak(TrmDat[m]); }
Добавляем еще один флажок

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

volatile byte Zflag; // контрольный флаг
и меняем код данного фрагмента на свой.
Примерно вот такой:
Спойлер

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

Zflag = 0;
  if(TrmDat[0] == 0){ TrmDat[0] = fnt_bl; }
   else { TrmDat[0] = znak(TrmDat[0]); Zflag = 1; }
  if(Zflag){ TrmDat[1] = znak(TrmDat[1]); }
   else { if(TrmDat[1] == 0){TrmDat[1] = fnt_bl; }
           else { TrmDat[1] = znak(TrmDat[1]); Zflag = 1; }
        }
  if(Zflag){ TrmDat[2] = znak(TrmDat[2]); }
   else { if(TrmDat[2] == 0){TrmDat[2] = fnt_bl; }
           else { TrmDat[2] = znak(TrmDat[2]); }
        }
  TrmDat[3] = znak(TrmDat[3]);
(Можно тут и символы повставлять -
естественно без использования функции znak :wink: )
8)
Модератор
Аватара пользователя
Сообщения: 19100
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

OKF писал(а):Какое там ещё ветвление?
твой код будет писать незначащие нули спереди.
я тут сделал в протеусе проект с 74hc595, никаких "паразиток" не наблюдаю.
еще "до кучи" сделал в протеусе проект с MAX7219, тоже никаких "паразиток" не наблюдаю.
оба проекта без гашения перед следующим выводом символа.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
OKF
Это не хвост, это антенна
Сообщения: 1452
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="Starichok51",url="/forum/viewtopic.php?p=4543882#p4543882"]твой код будет писать незначащие нули спереди.[/uquote]
Та вроде нет - пробелы.)
Это называется с выравниванием по правому краю.
Можно и по левому, если принт переставить):

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

    if (chr != ' ' || d) {
      chr = d + '0';
      printChar(chr);
    }
Ответить

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