Мерцание (переключение) 7 сегментных индикаторов
- Войдите на сайт для отправки комментариев
Привет всем, задавал этот вопрос в песочнице, но не был компетентен вообще, закидали меня и нечего не понял.. Сейчас рядом друг который больше меня шарит, но в моём вопросе помочь не смог, по-этому надеюсь очень на великие Ваши умы и отзывчивость.
Итак предистория: Пришла в голову идея на подарок жене - рамка которая показывает сколько лет, месяцев и дней мы вместе, и на этой же плате второй счётчик который показывает сколько дней в сумме вместе. По идее всё просто, часики на DS1307 и разницу в датах вывести на дисплей 7-ми сегментный.
Ссылки на видео работы готового устройства:
1) https://www.youtube.com/watch?v=mg2ACzUWGNM
2) https://www.youtube.com/watch?v=eJ8YNu5g6b8
Заказал платы, напечатал корпус, всё огонь и дальше слабое место = прошивка. Тут я копипастил всё с любых примеров, пытался разобраться и объединить всё в одно, и как не странно с моими знаниями которые были равны нулю я реализовал задуманное, но с одной проблемой - это видимое переключение между индикаторами, то есть меняя значения delay в конце кода я наглядно вижу как быстрее или медленнее они переключаются. Если я ставлю значение уже в delayMicroseconds начинает тускнеть дисплей и ничего не разобрать и горит одна цифра отчетливо.
Собирал всё в протеусе, там так же в симуляции тестил.
Получается индикаторы с общим анодом, всё на транзисторах.
Плата получилась такая:
Вот готовая с jlcpcb, качество отличное!
Вот и сам мой несчастный код:
#include <Wire.h> //Libraries to communicate with RTC #include "RTClib.h" RTC_DS1307 rtc; //create rtc object int segs[] = {0, 1, 2, 3, 4, 5, 6, 7}; //abcdefg. segments int digits[] = {12, 13, 10, 11, 8, 9}; //number of digits byte num[] = { B11000000, B11111001, B10100100, B10110000, B10011001, B10010010, B10000010, B11111000, B10000000, B10010000 }; int t, dm, Y, M, D; DateTime dob = DateTime(2010, 6, 27, 0, 0, 0); int t0 = dob.year() * 12 + dob.month() - 1; void setup() { rtc.begin(); //begin rtc communication //rtc.adjust(DateTime(2019, 12, 23, 20, 04, 0)); for (int i = 0; i < 8; i++) { pinMode(segs[i], OUTPUT);//set segment pins output } for (int i = 0; i < 6; i++) { pinMode(digits[i], OUTPUT);//set digts as outputs } } void loop() { DateTime now = rtc.now(); t = now.year() * 12 + now.month() - 1; dm = t - t0; if (now.day() >= dob.day()) { Y = floor(dm / 12); M = dm % 12; D = now.day() - dob.day(); } else { dm--; t--; Y = floor(dm / 12); M = dm % 12; DateTime tmp = DateTime(floor(t / 12), (t % 12) + 1, dob.day(), 0, 0, 0); D = (now.unixtime() - tmp.unixtime()) / 60 / 60 / 24; } printTime(D, M, Y); } void printNum(int number) //function to print number { byte data = num[number]; for (int i = 0; i < 8; i++) { if (data & 0x01) digitalWrite(segs[i], HIGH); else digitalWrite(segs[i], LOW); data >>= 1; } } void printTime(int D, int M, int Y) { int d[] = { floor(D / 10), D - 10 * floor(D / 10), floor(M / 10), M - 10 * floor(M / 10), floor(Y / 10), Y - 10 * floor(Y / 10) }; for (int i = 0; i < 6; i++) { if (i == 0) digitalWrite(digits[5], LOW); if (i != 0) digitalWrite(digits[i - 1], LOW); digitalWrite(digits[i], HIGH); printNum(d[i]); delayMicroseconds(200); } }
1. вызовы floor - выкинуть, они бесполезны, т.к. используется целочисленная арифметика;
2. вместо digitalWrite - прямая работа с портами;
3. смысла дёргать часы чаще, чем раз в секунду - нету.
Это так, навскидку - предложения по первичной оптимизации.
Ну и динамическая индикация на форах, не самое умное. Таймеры. ИМХО.
Полностью присоединяюсь к коллегам Выше, но хочу добавить.
Вы принципиально неверно походите к динамической индикации. При динамической индикации обновления сегментов должны происходить через равные промежутки времени такие, что полное обновление экрана происходило бы за 20 мс. Тогда экран у Вас будет обновляться с частотой 50Гц и никакого мерцания не будет. Хотите обновлять с частотой 100Гц - никто не запрещает, замените 20 на 10 в вышесказанном, но в любом случае "обновления сегментов должны происходить через равные промежутки времени".
Вы же за временем вообще не следите, а обновляете "когда получится".
а почему вы не хотите использовать для работы с индикаторами специально сделанные для этого драйвера?? например тот же МАХ7219 / МАХ7221 ???... работает по SPI... легко и без мерцаний будет обновлять все ваши экраны... (2 микрухи придется заюзать разве что....)
и код совсем простой получится - подключили библиотеку и просто её отправлять то, что надо отображать...
Вы принципиально неверно походите к динамической индикации. При динамической индикации обновления сегментов должны происходить через равные промежутки времени такие, что полное обновление экрана происходило бы за 20 мс. Тогда экран у Вас будет обновляться с частотой 50Гц и никакого мерцания не будет. Хотите обновлять с частотой 100Гц - никто не запрещает, замените 20 на 10 в вышесказанном, но в любом случае "обновления сегментов должны происходить через равные промежутки времени"
Не было.
Практически у всех было 60 Гц. (кроме случаев когда вместо мониторов использовались отечественные телевизоры и рассчитанные на работу именно с ними компьютеры)
Потом требования к комфортной частоте обновления экрана увеличились до 72-85 Гц. (были и маркетинговые 100+ Гц)
А потом появились ЖК и частота обновления вернулась к 60 Гц.
Но, строго говоря, важна не сама частота обновления, а длительность паузы. В CRT мониторах длительность паузы практически равнялась периоду кадровой частоты. При 60 Гц она примерно равна 17 мс. Но если у нас, скажем 4-разрядный дисплей с динамической индикацией, то при 50 Гц (20 мс период) на длительность гашения каждого разряда будет приходиться по 15 мс (а 5 мс - на время горения). Т.е. реально уровень мерцания такого индикатора примерно такой же, как и у CRT дисплея с частотой обновления 67 Гц.
Для 8-разрядного, естественно, хуже: 17.5 мс и эффективные 57 Гц.
В общем, для прибора, на который не планируется смотреть постоянно, 50 Гц, конечно, достаточно, хотя никто не мешает сделать и чуть-чуть побольше.
В общем, для прибора, на который не планируется смотреть постоянно, 50 Гц, конечно, достаточно, хотя никто не мешает сделать и чуть-чуть побольше.
О чём я и написал ТС в #3
Давайте попробуем реже вызывать часы для начала
Давайте попробуем реже вызывать часы для начала
И в строке 33 - опять. Интересно, когда-нибудь это закончится?