Бинарные часы
- Войдите на сайт для отправки комментариев
Пнд, 10/10/2011 - 20:11
Захотелось сделать бинарные часы. Нарыл схему. Собрал на макете но есть проблема. Необходимые лампочки загораются НО некоторые которые не должны гореть горят очень тускло. Никак не могу от этого избавиться. В чём может быть эта проблема?
int LED1[] = { 0,0,1,0,0,1,1,1,1,1 }; int LED2[] = { 0,0,0,1,0,1,1,1,1,1 }; int LED3[] = { 1,0,0,0,1,0,1,1,1,1 }; int LED4[] = { 0,1,0,0,1,0,1,1,1,1 }; int LED5[] = { 0,0,1,0,1,0,1,1,1,1 }; int LED6[] = { 0,0,0,1,1,0,1,1,1,1 }; int LED7[] = { 0,1,0,0,1,1,0,1,1,1 }; int LED8[] = { 0,0,1,0,1,1,0,1,1,1 }; int LED9[] = { 0,0,0,1,1,1,0,1,1,1 }; int LED10[] = { 1,0,0,0,1,1,1,0,1,1 }; int LED11[] = { 0,1,0,0,1,1,1,0,1,1 }; int LED12[] = { 0,0,1,0,1,1,1,0,1,1 }; int LED13[] = { 0,0,0,1,1,1,1,0,1,1 }; int LED14[] = { 0,1,0,0,1,1,1,1,0,1 }; int LED15[] = { 0,0,1,0,1,1,1,1,0,1 }; int LED16[] = { 0,0,0,1,1,1,1,1,0,1 }; int LED17[] = { 1,0,0,0,1,1,1,1,1,0 }; int LED18[] = { 0,1,0,0,1,1,1,1,1,0 }; int LED19[] = { 0,0,1,0,1,1,1,1,1,0 }; int LED20[] = { 0,0,0,1,1,1,1,1,1,0 }; int LEDPins[] = { 12,11,10,9,8,7,6,5,4,3}; void vivod(int LED[]) { for(int i=0;i<=9; i++) digitalWrite(LEDPins[i], LED[i]); delay(1); } int second=5, minute=5, hour=2; //start the time on 00:00:00 int munit = 4; int hunit = 9; int suc = 5; void setup() { for(int i=0;i<=9; i++) pinMode(LEDPins[i], OUTPUT); } void loop() { if(suc == 1 || suc == 3 || suc == 5 || suc == 7 || munit == 9) vivod(LED20); if(suc == 2 || suc == 3 || suc == 6 || suc == 7) vivod(LED19); if(suc == 4 || suc == 5 || suc == 6 || suc == 7) vivod(LED18); if(suc == 8 || suc == 9) vivod(LED17); //minutes if(second == 1 || second == 3 || second == 5 || second == 7 || second == 9) vivod(LED16); if(second == 2 || second == 3 ) vivod(LED15); if(second == 4 || second == 5 ) vivod(LED14); //minutes units if(munit == 1 || munit == 3 || munit == 5 || munit == 7 || munit == 9) vivod(LED13); if(munit == 2 || munit == 3 || munit == 6 || munit == 7) vivod(LED12); if(munit == 4 || munit == 5 || munit == 6 || munit == 7) vivod(LED11); if(munit == 8 || munit == 9) vivod(LED10); //minutes if(minute == 1 || minute == 3 || minute == 5 || minute == 7 || minute == 9) vivod(LED9); if(minute == 2 || minute == 3 ) vivod(LED8); if(minute == 4 || minute == 5 ) vivod(LED7); //hour units if(hunit == 1 || hunit == 3 || hunit == 5 || hunit == 7 || hunit == 9) vivod(LED6); if(hunit == 2 || hunit == 3 || hunit == 6 || hunit == 7) vivod(LED5); if(hunit == 4 || hunit == 5 || hunit == 6 || hunit == 7) vivod(LED4); if(hunit == 8 || hunit == 9) vivod(LED3); //hour if(hour == 1) vivod(LED2); if(hour == 2) vivod(LED1); }
А менять местами яркие и неяркие светодиоды пробовали? Может просто светодиод бракованный или подпаленный? Можно еще попробовать махнуть местами резистры, мало ли?
Приведите схему подключения светодиодов.
А то светодиодов много, а резисторов мало...
Схема!
Попробуйте в конце функции loop, добавить delay(500); и сообщите перестали-ли гореть "в пол-накала" часть диодов.
Если я не ошибаюсь в своих подозрениях, то должны перестать. Правда часы будут показывать "только час" (минут и секуд не будет), но зато мы будем знать что "на правильном пути".
нет не перестали. диоды которые не должны гореть всё равно загораются. Я заметил что проблема только с нижнем рядом диодов.
> диоды которые не должны гореть всё равно загораются
А характер загорания изменился? Я не совсем правильно выразился что должно "произойти", перестать должны были именно "тускло". Правильно или неправильно, пока вторично. Главное что должны начать горет "четко". Либо горит, либо нет. Наблюдается такое?
А менять местами яркие и неяркие светодиоды пробовали? Может просто светодиод бракованный или подпаленный? Можно еще попробовать махнуть местами резистры, мало ли?
Я прошу прощения, я плохо прочитал сообщение и ответил невпопад.
На всякий случай спрошу. На схеме светодиоды подключаются к выходам 4-13, а в коде у Вас 3-12. Подключили Вы как в коде или как на схеме?
у меня подключено 3-12 как в коде. диоды: если вставить delay(500) в конце как вы говорили то загорается и стабильно горит только один диод. Остальные те которые должны гореть без этой строчки кода загораются и гаснут + загораются и те которые не должны гореть. Все они вспыхивают ярко.
Вопрос: Я работал с Цифровым сегментным индикатором и там не было таких проблем. Может внутри есть схема которая убирает эту проблему? Или там тупо светодиоды.
Светодиоды могут еле еле светиться если где-то есть "недоконтакт" к плюсу или минусу(в моём случае это был не смытый флюс) в вашем может быть некрасивая схема матрицы, перепроверьте всё
OK. Значит "догадка" подтвердилась. Ошибка - в коде. Это не исключает ошибку в схеме подключения, но вначале нужно разобратся с кодом. Задержку delay(500) можно убрать. Она нужна была только "для проверки догадки".
Проблема в том что во время одного прохода loop вызываете несколько раз vivod(...). Не решив до конца "какае диодны должны гореть", вы используя промежуточные результаты вычислений, уже пытаетесь "показать их на диодах". Например для показа часа hunit = 9, у вас выполнится vivod(LED6) и vivod(LED3) . Посмотрим, например, на PIN9. vivod(LED6) его включит, а vivod(LED3) его тут же выключит. Так как looup() крутится быстро, то если нет задержки delay(500), мы получаем на этом пине "мерцание" и диод горит "тускло".
Ну и так же возникает эффект, что более поздние "промежутночные" решения что должно гореть "перекрывают" более ранние.
Если посмотреть изначальную статью в которой описаны эти часы, то там написано примерно так:""I used following calculation....When done, the colum values are passed on to port C ". Что можно перевести как "я выполняют следующие вычисления.... когда они закончены, я отправлю результат в portC (поджигаю светодиоды)".
То есть вам нужно завести некий промежуточный буффер, и все вычисления "что включать, а что нет", должны писать в него и только уже в конце, когда все решения приняты, на основании инормации из буфера, нужно включать/выключать светодиоды. Функция vidod должна вызываться только один раз. И параметром иметь этот буфер. Попробуйте это реализовать, если не получится... попозже может набросаю как это в коде должно выглядет.
Так же, при подключении не забудте следующие: на этой схеме номера выводов это номера ног "микроконтроллера". Которые могут и не совпадать с нумерацией пинов ардуины (которые вы используете в коде). Соответсвие между ними вы можете найти вот тут www.arduino.cc/en/Hacking/PinMapping
Например то что в вашей схеме нарисована как "вывод 5", в коде должно соотвествовать digitalWrite(3,....)
Вообщем посмотрите эту шпаргалку и сверте нумерацию в своем LEDPins. Если там будут значения взятые просто "из схемы", то естествено диоды будут поджигатся неправильно.
>на этой схеме номера выводов это номера ног "микроконтроллера"
Все еще несколько "путаней". На схеме это даже не номера ног котроллера. А номера ног разъема который придумал автор этой статьи. Рядом он там дал еще одну схемку в которой видно соотвествие ног контроллера, пинам этого разъема.
То есть вам нужно "смотреть номер пина на разъеме", выяснить "какой ноге контроллера он соотвествует", потом смотреть в PinMapping и узнавать какой digital-пин ардуины соответсвует этой ноге контроллера.
То есть вам нужно завести некий промежуточный буффер, и все вычисления "что включать, а что нет", должны писать в него и только уже в конце, когда все решения приняты, на основании инормации из буфера, нужно включать/выключать светодиоды. Функция vidod должна вызываться только один раз. И параметром иметь этот буфер. Попробуйте это реализовать, если не получится... попозже может набросаю как это в коде должно выглядет.
Попробую
Что то я не соображу( ведь 2 верхних ряда работают нормально
Это ни о чем не говорит. Значит им повезло. И все множественные вызовы vivod(...) в данном конкретном случае их либо включают, либо все вызовы выключают. А, как только у вас попадается ситуация что одны вызовы включают, а другие выключают - вы получаете мерцание.
Попробуйте как то так:
Далее,
"Мерцания" должны исчезнуть даже без delay(500).
Что-бы дальше было удобней отлаживать логику можно в setup добавить инициализацию порта
Serial.begin(9600); // если необходимо - подправте скорость.
Добавте функцию
И вызов vivod2serial(LEDPinsBuff) в конец loop.
Тогда в окне терминала вы сможете увидеть "какие же пины собиралась включать" ваша логика. Если "не то что вы думали" - ищите ошибку в логике, если "тут все правильно, но горят не правильные диоды" - проверяйте схему подключения держа в уме необходимость маппинга пинов (пин разъема->нога контроллера->пин ардуины).
Блин не знаю даже чо за фигня. Ваш код вообще не работает. Но я решил сделать по другому. И всё равно не нужные диоды тускло горят. Проверил через порт. Всё четко))))
>Ваш код вообще не работает
В чем проявляется "вообще не работает"? Горят "не те" или "не те горят тускло"?
>Проверил через порт.
Всмысле вывели к ком-порт лог "какие пины включаются"? Включаются правильные, но "горят лишние"?
Тогда только проверять схему подключения.
Уже самого "заело". Попробую, чуть позже, в симуляторе воспроизвести вашу схему (нет под руками нужных деталей) и посмотреть "как оно работает". Если у вас получится решить проблему раньше - отпишитесь. Что-бы я не тратил время.
вообще не горят
>Всмысле вывели к ком-порт лог "какие пины включаются"? Включаются правильные, но "горят лишние"?
горят лишнии но в логе только те которые должны гореть написаны.
Я немного видоизменил схему подключения сделал как Цифрового сегментного индикатора. Глюков стало меньше но они есть
Посмотрел сейчас видео в статье. Похоже что "мерцание" это "так задуманно". На видео его тоже видно. Одновременно несколько диодов не зажигаются. Эффект одновременности достигается delay(1); в функции vivod(...) (можно кстати будет поигратся с этим параметром).
Так что буферезирование, наверное таки лишние. Нужно разбиратся только с "зажигаются неправильные".
Что-бы мы копали "в одном направлении". Какие, по вашему, диоды должны зажигатся при при
И какие зажигают в реальности? По нумерации схемы (которые там нарисованы LED1, LED2,LED...)
>Эффект одновременности достигается delay(1); в функции vivod(...) (можно кстати будет поигратся с этим параметром).
я пробовал менять этот параметр. при 0 ненужные светодиоды горят ярко как и все при 1-10 горят тускло при10+++ начинается мерцание.
при данных параметрах горят LED2,4,18
тусклоLED15
Кстати, пока я пробую воспроизвести схему. Можете сделать еще одну проверочку:
Выкинуть все из loop. И написать в него
В результате это должно начать зажигать диоды "по очереди" (как они называются на схеме). Если "зажигает" в правильном порядке - значит схема собрана правильно, если нет, то...
))))) я так уже делал и не раз. последовательно зажигал каждый светодиод. и всё ок. Даже всё схему разобрал и собрал заново таже проблема! И светодиоды менял без результатно(
>последовательно зажигал каждый светодиод. и всё ок
Да быть такого не может. Вот если в loop у вас будет vivod(LED20) неужели зажигается именно LED20? (самый верхний правый на схеме).
Что-бы он зажегся только он должен быть LOW на четвертом PIN-е разъема и HIGH на 13-том.
По коду, по это должны быть (судя из ваших объяснений как вы подключили) 3 PIN арудины и 12-тый.
Смотрим в (первый ваш пример кода)
Как видим "крайние пины" у нас оба LOW. Следовательно LED20 гореть никак не может. На нем с обоих сторон 0. Зато, зачем-то "включили" кучу других пинов 9,8,7,6,5,4.
Вывод: либо пины у вас подключены как-то "совсем не так", либо никакого "LED-ы загораются последовательно нормально" нет и в помине.
Откуда вы брали последовательности LED1,LED2,LED3...?
На эмуляторе собрал упрощеную схему. Игрался именно с LED20. Правда "подключал" я по тому как нарисовано на схеме (то есть LEDPins у меня были свои), но пока не поправил int LED20[] на что-то подобное "int LED20[] = { 1,0,0,0,0,0,0,0,0,0};
vivod(LED20) у меня ничего не включал. Так что перепроверяйте свои включающие последовательности.
Кстати, только что рассмотрел на вашей фотке шпаргалку в клеточку. Если я правильно понял, то это ваша нумерация LED-дов. Сравните ее с нумерацией LED-ов в статье. Они, мягко говоря, отличаются. Возможно отсюда и пошла путаница в LEDxx[] последовательностях?
Что-то мне это уже начало дико напоминать детский водобпроводный ребус "какой шланг к какому крану идет". Вообщем "распутывайте" :)
Получилось у меня в симуляторе воспроизвести "помаргивание лишними диодами".
Подобно уже завтра "распишу".
В двух словах: "собака в том", что пины мы устанавливаем не одновременно, а "по очереди". Между вызовами digitalWrite есть небольшая задержка. Диоды мы зажигаем по такому принципу: подаем HIGH на аноды сразу нескольких диодов (аноды у них соеденены), LOW на катод того который должен гореть, и HIGH на катоды тех которые оказались "лишними" (так сказать лишили их "земли").
Так вот вначале у нас устанавливаются пины 12,11,10,9 - которые отвечают за аноды, и потом уже 8,7,6,5,4,3 которые отвечают за катоды. И вот в этом промежутке когда мы уже установили 12,11,10,9, но еще не успели установить в правильное состояние 8,7,6,5,4,3 (запретить лишние) у нас происходит кратковременное моргание "тех которых не ожидали".
Выход либо отказатся от digitalWrite и устанавливать состояние ног "одновременно". Это можно сделать через прямую запись в порт (как и делается в оригинальность статье). Либо попытатся вначале устанавливать "катоды", а потом "аноды". Как-то так (мне на симуляторе помогло):
Когда вы зажигали LED-ы "по очереди" с большими паузами, этих кратковременных лишних "подмаргиваний" видно небыло (трудно увидеть один милисекундный миг), а когда вы пускаете это в "цикл". И это лишние подмаргивание возникает несколько тысяч раз в секунду - его становится видно как "горит в пол накала".
P.S. А управляющие последовательности проверте.
Я вчера как раз думал об том чтобы все пины сбрасывать в 0. попробовал ваш код. РАБОТАЕТ)))) но они светят тускло. И я изменил и всё стало нормально гореть)))))) Спасибо большое)))
Ну мне мой вариант все-таки кажется более предпочтительным. А с тусклостью в нем я бы преложил бороться небольшим увеличением delay(1)->delay(10).
Какие минусы я вижу в вашем коде: пока идет "вычисление логики" в вашем варинаты леды выключены, в моем - включены. Поэтому, теоретически, мой вариант должен быть ярче (хотя вы говорите что наоборот - непонятно). Так же вы сделали i<=3 вместо i<=4, теоретически, на некоторых комбинациях это опять может привести к "паразитам" (в нижнем ряду, удивляюсь почему не привело, видимо все-таки разные у нас схемы подключения).
Но конечно любой "профи" от нашего решения упал-бы в обморок. "Правильно" это нужно решать прямой записью в порт. И хранить необходимые состояния не в виде массивов, а в виде битовых масок. Тогда сама собой уйдет и проблема "одновременности" и код станет компактней, и прошивка меньше.
Делается "прямая запись", например вот так:
подробнее можно почитать тут:www.arduino.cc/en/Reference/PortManipulation
Кстати прямая запись в порт еще и работает в несколько раз быстрее чем через digitalWrite
>Но конечно любой "профи" от нашего решения упал-бы в обморок. ДААА это точно)))))
Про прямую запись в порт ничего не знал. Так что ща полезу посмотрю. Большое спасибо. что помогли разобраться.)))
>вы сделали i<=3 вместо i<=4
Похоже все-таки в этом вы больше правы. Вчера в три ночи дописывал этот код и прощитался с индексаторами. Ваш вариант более аккуратен.
А прямую запись в порт все-таки попробуйте. Это будет намного более правильное решение.
И пытаясь предугадать дальнейшие действия: вы же будуте кнопки обрабатывать? Возможно ловить их "нажатия" будет лучше через arduino.ru/Reference/AttachInterrupt
>Про прямую запись в порт ничего не знал
Если бы знали, то у нас бы небыло такого увлекательно квеста :) . Суть-то всех подобных хобби в "узнавании чего-то нового". Если бы сразу сделали "на портах", то про такой нюанс как "в каком порядке" включать ноги возможно и не подумали бы никогда.
А я бы так и не попробовал симуляцию-отладку ардуины в протеусе. Знал что "это возможно", но все "руки не доходили". Так что "время потрачено не зря".
Полностью согласен)))
Кстати сказать что вы "все делали неверно" тоже нельзя. С точки зрения ардуино-идеологии digitalWrite более правильно (понятней что происходит, легче переносить на другие контроллеры). Она и создавалась что-бы "скрыть технически детали от чайников".
Но как видите это не всегда благо (поэтому "профи" и называют ардуину "от лукавого"). Работа с портами это больше С/ASM идеология. Когда нужно хоть немного представлять внутренюю архитектуру контроллера на котором "все крутится". И при переходе на другой контроллер код может потребовать "небольшого допиливания".
Про прямую запись в порт ничего не знал. Так что ща полезу посмотрю.
Добавили перевод по использованию регистров микроконтроллера для прямой записи в порты. Читать тут - http://arduino.ru/Tutorial/Upravlenie_portami_cherez_registry
ОООООООООооооо. Спасибо!!!!!
Ура!!! Ура!!! Ура!!! Наконец то, сегодня, Я завершил постройку бинарных часов!
И с радостью показываю их вам.
Сразу хочу выразить благодарность «leshak» за помощь в программировании.
Часы умеют показывать дату и время. На передней стороне имеются (кроме числовых светодиодов) одна кнопка, которая отвечает за переключением между режимами Дата/Время, и два маленьких светодиода (с права) показывающих, что в данный момент показывают числовые светодиоды.
На задней стороне имеются три кнопки настройки. Верхние две отвечают за + и – к времени а нижняя вводит часы в режим настройки. Также в нижнем левом углу есть рычажок выкл/вкл часов.
Ну я думаю что лучше перейти к фото части))))
+ архив с печатной платой
Есть вопрос. Можно ли заменить atmega328 на atmega8? Вроде даже схему переделывать не надо.
P/S/ Думаю можно тему переместить в проекты.
>Можно ли заменить atmega328 на atmega8
Думаю можно. Хотя ответить на это вопрос можете только вы. Переключите в IDE целевую плату на "Ardino NG Older with Atmega8", скомпиляйте скетч, посмотрите какой размер получился, посмотрите влезет ли он в atmega8
Только подумайте еще: "оно вам надо?". Я вначале тоже "тискался" в младшие модели, а потом прикинул и увидел что "смысла нет". У нас на рынке, более страшие модели камня стоят дороже меньше чем на $1. А, иногда, и дешевле (гримасы логистики). Плюс проезд до рынка/обратно разницу точно "скушает". Ну и к тому же, прикинул, что при моех "хобби объемах", в несколько девайсов в год, гнатся за экономией в центы - смысла нет. Проще прикупить пару "жирных камней" и не гадать "влезет/не влезет".
>Думаю можно тему переместить в проекты.
Схема, скетч - было-бы не плохо. Вдруг кто-нибудь захочет повторить вашь подвиг. Все-таки "ардуина" задумывалсь как Open Source ;)
Да схему бы не помешало выложить.))) + плату. Я думаю что скоро добавлю (как только нарисую).
Аккуратно и красиво - молодцом) А корпус можно сделать просто как тонированный наглухо черный кусок стекла с приеклееными сзади часами, приклеете и крепление на стену - будет стильно и красиво.
Идея модернизации на будущие: датчик освещенности (или просто смотреть на текущие время) и ночью уменьшать "яркость", что-бы в темноте "по глазам" не било.
А корпус, можно сделать даже "только сзади" (что-бы прикрыть батарейку, камень), а впереди оставить "как есть". Так оно "гиковей" смотрится. Хотя и предложеный выше вариант - не плох. Дело вкуса.
кстати можно заняться поиском прозрачных/полупрозрачных корпусов и будет всё сразу) Удобно и гиково. Еще есть вариант это лазерная порезка акрила - круто но дорого в наших краях(особенно ломят цену за акрил)
я всё уже прикупил для своего проекта с часами, но нет времени(((( Я буду делать на модулях от dfrobot. и матрица 3216х2 тоесть будет явно 32 на 32, но пока всё лежит в коробочках
Нащет корпуса даже не знаю. Я обычно люблю внутренности видеть )))