image

Задумал я как-то купить йогуртницу. Да такую, чтобы йогурт делала хороший и всегда одного качества. Что для этого нужно? Во-первых, сырье, во-вторых, точная и стабильная температура, в-третьих, настройка времени приготовления. Стал я выбирать и столкнулся со следующей засадой: дешевые йогуртницы оказались нерегулируемые. То есть внутри нагревательный провод, и этот провод, по сути, подключается к сети. Какая температура будет при этом внутри йогуртницы, зависит от рук сборщика, температуры окружающей среды, фаз луны и глубины сна Ктулху (Ктулху фхтагн, кстати).

Само собой меня такая ситуация не устраивала. И еще больше меня напрягала ситуация вокруг йогуртниц, которые, меня по своим функциям и параметрам устраивали. Почему-то производители таких йогуртниц считают, что они поставляют на рынок изделия космической отрасли и цены на такие изделия должны быть соответствующие. Сильные душевные муки в процессе выбора довели меня до того, что я высказал любимой супруге свои возмущения по поводу негуманной ценовой политики производителей йогуртниц и в процессе словесных излияний выдал фразу «Да я сам за пятьсот рублей лучше сделаю», после чего в моей голове что-то щелкнуло…

Это была предыстория. А теперь история. В процессе построения чудесного аппарата я столкнулся с багом. При выводе текущей температуры на дисплей контроллер периодически уходил в ребут. То есть иногда он часами работал нормально, а иногда сбрасывался каждые несколько секунд. Так как это начало происходить после внедрения в прошивку функции опроса датчика ds18b20, то естественно, что за поиском бага я обратился к ней. И ничего не нашел. Стек не срывался, не в свои области памяти функция ничего не писала. В общем, работала, так как ей полагается. Причем отключение этой функции убирало баг, что явно указывало (так мне в тот момент казалось) на виновника торжества. Я подумал что всему виной система синхронизации.

Так как камень у меня маленький (attiny2313a) и таймеров на все примочки ну совершенно не хватает я вышел из положения, написав, диспетчер задач, который получает задачи и требуемое время задержки от функций, ставит их в очередь. Затем после отсчета нужного количества времени передает им управление. Минимальное время задержки я установил в 1 милисекунду. Что позволило мне устанавливать задержки от миллисекунды до минуты. Но если вы взглянете в даташит датчика ds18b20, то увидите, что общение с датчиком температуры иногда длится больше 500 микросекунд (reset и ожидание presence).

image

А что если в процессе этого в функцию общения влезет прерывание? Будет смещение тайм слота, из-за чего контроллер не сможет прочитать бит или правильно распознать presence. Выход я нашел в использовании синхронизации. Процесс простой. Когда функция опроса датчика видит что ей предстоит длительное общение с датчиком то она настраивает прерывание в регистре Б таймера 1 одновременно с прерыванием «диспетчера времени» которое расположено в регистре А таймера 1. А так как прерывания обрабатываются в порядке строгого соответствия с адресом вектора прерывания в таблице прерываний, то получается, что после процесса синхронизации функция опроса датчика получит управление сразу за прерыванием «диспетчера времени».

Ну и где тут может быть баг? Да везде. Но лично я подумал, что проблема может быть в пересечении прерываний. То есть в случае, когда в процессе выполнения одного прерывания приходит другое. Чистка кода для решения этой проблемы продолжалась до тех пор, пока я не обнаружил, что мои действия привели к тому, что проблема начала возникать даже при неподключенном датчике. Отключив функцию опроса датчика, я убедился, что теперь сбросы контроллера не зависят от ее работы. И тут меня озарила гениальная догадка. Нужно померить напряжение! Мультиметр бодро отчитался, что на контроллере присутствует 4,2 вольта. «Ну конечно «BOD» подумал я. И подключил к плате внешнее питание (до этого я довольствовался питанием от USB). Мультиметр довольно буркнул, что на плате 4,98 вольта. С чувством победы я включил плату, чтобы узреть невероятное. Баг присутствовал! Причем стал еще ядренее. Теперь контроллер сбрасывался каждые пару секунд, а иногда и за доли секунды. Поиски продолжились с удвоенной силой и привели к функции выводящей информацию на экран.

Как вы, наверное, догадываетесь, с ней все было нормально, тем более что после ее написания она была должным образом оттестирована. И, тем не менее, все говорило о том, что мой неуловимый баг кроется именно в ней. Обнаружилось, что баг возникает только при отображении страницы текущей температуры. Страницы отображения мощности, старта, времени бага не вызывали. Не найдя ничего что могло бы вызывать такое поведение я решил отталкиваться от питания. А именно того факта что при нормальном напряжении баг возникал чаще. Снизив напряжение, я обнаружил, что при 3,8 вольта на контроллере, последний работает стабильно. Ситуация рвала все шаблоны. И тут я вспомнил закон Ома. Ток пропорционален напряжению. Всегда? Нет. На светодиодах этот закон не работает. Точнее работает, но со своими прибамбасами.

Пропорциональность тока через диод не такая же, как на обычном резисторе, ибо полупроводниковые приборы в большинстве своем нелинейны. Вспомните хотя бы тиристор или диод зенера (стабилитрон). Вот для сравнения ВАХ светодиода из даташита (черная линия) и ВАХ резистивной нагрузки (красная линия)

image

Видно, что для резистивной нагрузки закон Ома бог и хозяин. Если напряжение возросло на 10%, то и ток возрастет на те же 10 %. Но светодиоду никто не указ. Если поднять на светодиоде напряжение всего на 10% (с 2 вольт до 2,2 вольт) его ток скаканет на все 100%, то есть в два раза! Но в моем случае главным оказалось то, что увеличение напряжения увеличивало и его просадку в момент включения диода. А таких диодов у меня оказалось 32! Четыре семисегментных индикатора по восемь светодиодов в каждом (семь сегментов и точка). Они у меня подключены не через мультиплексирование, а через сдвиговые регистры потому что:

1. Выводов котроллера attiny2313 катастрофически не хватало.
2. Меня раздражает их мерцание при подключении мультиплексированием(перфекционизм номер раз)
3. На вывод мультиплексированием расходуется много ресурсов контроллера (перфекционизм номер два)

Кроме того я подключил сдвиговые регистры с функцией отключения экрана на время обновления дисплея (перфекционизм номер три). Зачем мне сдалась эта фича — не знаю. Ведь выбранная мною логика может работать вплоть до частоты 100мгц. Соответственно данные в нее можно задвигать на полной частоте работы контроллера, которая у меня равна 10мгц. Ну кто успеет заметить перемещение битов по разрядам индикатора на такой частоте?

Идем дальше. Питание моей схемы обеспечивает регулятор L7805, вот его схема подключения.

image

Регулятор без проблем обеспечивает ток в 1А. На выходе с регулятора стоит конденсатор 0,1 микрофарад, который, по идее должен сглаживать колебания тока. Его заряд при 5 вольтах равен 0,5 микрокулон. При 3,8 вольта заряд соответственно 0,38 микрокулон. При 3,8 вольтах светодиоды кушают около 288мА, а при 5 вольтах около 416мА. Соответственно при поднятии напряжения с 3,8 вольта до 5 вольт заряд запасаемый конденсатором возрастет на 24 % но потребляемый ток в то же время увеличится на 30 с лишним процентов. Расчеты конечно примерные но показывают что просадка по напряжению в такой схеме тем больше чем больше напряжение питания. При 3,8 вольта просадка не являлась критичной для контроллера. А вот при 5 вольтах просадка увеличилась и начала сбрасывать контроллер. А сброс контроллера именно на странице отображения температуры происходил потому, что именно на этой странице были задействованы все индикаторы дисплея.

Решение оказалось простым. В коде нужно было просто закомментить строчки включения и выключения индикаторов sbi displayPort, offDispWire и cbi displayPort, offDispWire.

                ldi XL, videoMem
		cbi displayPort, shiftWire
		cbi displayPort, storageWire
		;sbi displayPort, offDispWire
		ZpushToDisplay:
		ldi temp2, 8
		ld temp, X+
		ZnextbitToDisplay:
		cbi displayPort, dataWire
		sbrc temp, 7
		sbi displayPort, dataWire
		sbi displayPort, shiftWire
		cbi displayPort, shiftWire
		lsl temp
		dec temp2
		cpi temp2, 0
		brne ZnextbitToDisplay

		cpi XL, videoMem+sizeVideoMem
		brne ZpushToDisplay

		sbi displayPort, storageWire
   		cbi displayPort, storageWire
		;cbi displayPort, offDispWire

Сбросы прекратились. И жил контроллер долго и счастливо.

З.Ы. процесс поиска неуловимого бага указал на еще один косяк в схеме. Дело в том что максимальная рассеиваемая мощность сдвиговых регистров около 0,5 ватта, а ток через вывод питания или землю около 70 милиампер. Если на дисплее отображается восьмерка с точкой, то ток через сдвиговый регистр должен составить около 104 милиампер, что, как вы понимаете, является превышением. Дело не в том, что я не учел этот момент. Я учел. Но в процессе расчета резистора для светодиода поддался минутной слабости и забыл, что светодиод является нелинейным элементом и для снижения тока через него в два раза недостаточно в два раза увеличить сопротивление токоограничивающего резистора. В общем, в любой непонятной ситуации смотри ВАХ!

Комментарии (25)


  1. iliasam
    05.11.2015 15:12

    Из текста не сразу понял о каких светодиодах идет речь — только потом дошло, что индикатор светодиодный.

    На выходе с регулятора стоит конденсатор 0,1 микрофарад

    Не помешало бы поставить побольше, микрофарад 10. Были ли поставлены конденсаторы по 0.1 около выводов контроллера? Возможно, тогда баг бы себя и не проявил.
    В общем, в любой непонятной ситуации смотри ВАХ!

    А лучше иметь осциллограф и смотреть, что происходит на шине питания.


    1. bladeser
      05.11.2015 15:51

      Категорически с вами согласен. Но осциллографа у меня к сожалению нет.


      1. flerant
        05.11.2015 16:26
        +2

        Значит, соседний топик вам как раз в тему :)


        1. bladeser
          05.11.2015 17:24
          +1

          Боюсь осциллограф в том топике нельзя назвать таковым. Такой осциллограф я себе делал лет 8 назад и скажу что это не более чем игрушка. Заваливание фронтов, низкая частота дискретизации и откровенно слабый ацп приводит к тому что такое в руки не возьмет ни один человек хоть раз пользовался обычным, даже старым советским осциллографом.


          1. flerant
            05.11.2015 20:09

            Я не случайно поставил в конец своей реплики смайлик


  1. diewindowsdie
    05.11.2015 16:51
    +1

    Возможно также стоит под питание цифровой логики (МК, регистры) и под питание всего остального (в вашем случае, семисегментные индикаторы) выделять отдельные стабилизаторы напряжения.


    1. IronHead
      05.11.2015 17:38
      +1

      Слишком жирно будет, вполне достаточно конденсаторов на различных цепях питания. Ловил похожий глюк, когда делал таймер для засветки фоторезиста UV светодиодами. Причем даже запланировал установку конденсатора, но поленился впаять, опрометчиво посчитав, что ток будет не достаточной силы, чтобы случилась просадка и микроконтроллер сбросился.
      Ну и камень в огород автора:
      1) мультиплексирование не дает мигания при частоте обновления больше 100 Гц (я обычно ставлю 1000)
      2) что за чудо алгоритм у вас заложен в устройство, который не оставляет ресурсов для динамической индикации? там нужно всего лишь несколько байт памяти да прерывание от таймера, которое совместно может обслуживать динамический же опрос клавиатуры и толкание счетчика времени готовки.


      1. bladeser
        05.11.2015 18:06

        1.а. при прямом взгляде не дает, но если вы попробуете взглянуть на индикатор вскользь то сможете увидеть мерцание на достаточно бальших частотах. Не берусь объяснить почему так происходит.
        1.b на мультиплексирование требуется большее количество выводов чем на сдвиговую логику, где по сути можно обойтись тремя.
        1.с мультиплексирование на большом количестве индикаторов неэффективно, так как чем больше индикаторов тем сильнее снижается сила свечения из за увеличения скважности.
        2. Алгоритм я вкратце описал. Диспетчер времени отсчитывающий задержки времени, диспетчер задач передающий управление задачам из очереди и управляющий самой очередью. Восьмибитный таймер отдан под шим управление нагрузкой. 16 битный занят отсчетом времени задержек и частично обслуживает подпрограмму опроса датчика температуры. Все остальное — опрос кнопок, вывод на дисплей, ПИ-регулятор, управление звуковым буззером, менеджер экранов дисплея и перекодирование дисплея находятся в очереди задач вызываясь только в нужное им время. В основном цикле практически один loop и некритичные задачи.


        1. barabanus
          05.11.2015 18:21
          +1

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


          1. bladeser
            05.11.2015 18:42

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


          1. 10s
            06.11.2015 00:25

            На самом деле мерцание динамической индикации дейсвительно заметно когда вскользь смотришь. Делал себе ламповые часы с ее использованием, так вот, к155ид1 через которую катоды ламп подключались к земле, не могла переключаться чаще 400гц (цифры смазываться начинали), и видно было переключение, особенно в темноте.


            1. barabanus
              06.11.2015 10:56

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


      1. diewindowsdie
        05.11.2015 18:10

        У меня был кейс когда нагрузка в примерно 150 мА вызывала достаточную просадку для ресета МК, по питанию стояли 100 мкф, 100 нф, 4700 мкф. Вопрос, жирно или нет — он такой себе… это ведь не серийное устройство, как мне кажется надежность работы гораздо важнее увеличения цены на 20-50 рублей.


  1. barabanus
    05.11.2015 18:16

    Хорошо было бы поставить по 1 мкФ конденсатору на каждый сдвиговый регистр между питанием и землей. И еще было бы хорошо использовать более медленную логику, в вашем случае — HC, поскольку быстрая логика очень быстро переключает свои выводы, вызывая кратковременные большие токи даже при небольшой емкостной нагрузке.


    1. bladeser
      05.11.2015 18:25

      У меня она и стоит. 74hc595.


  1. KivApple
    05.11.2015 19:46

    А можно было бы просто с самого начала поставить нормальный конденсатор по питанию в схему, а не использовать ёмкость впритык. Всегда использую правило «чем больше конденсаторов на питании (в разумных пределах), тем лучше» и оно ни разу меня не подводило.


    1. bladeser
      06.11.2015 07:43

      С другой стороны использование компонентов «впритык» позволяет обнаруживать многие проблемы уже на этапе разработки. Так как чтобы использовать компоненты около предела их возможностей необходим расчет, и если что то не работает как нужно значит ты облажался в расчетах. Это в свою очередь позволяет не только набраться опыта тем самым прокачав скилл «Сделать сразу хорошо» но и наметить для себя проблемные места в системе и сразу оптимизировать их. Это конечно мое личное мнение но метод «чем больше кондеров тем лучше» похож на покупку костылей новорожденному с мыслью «а вдруг ногу сломает».
      И тем не менее в системах где надежность критична я бы скорее всего все делал с троекратным запасом.


      1. KivApple
        06.11.2015 21:33

        Ну в образовательных целях — да, полезно. Однако в конечном устройстве лучше всё равно так не делать. Конденсатор 10 мкФ вместо 1 мкФ не увеличит заметно ни цену, ни размер, зато в каком-нибудь необычном случае может спасти схему от сброса. Грубо говоря, мы ничего не теряем, а надёжность растёт.

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


    1. AlexanderG
      07.11.2015 00:29

      В любой непонятной ситуации ставь конденсаторы на питание…


  1. gleb_l
    08.11.2015 23:06

    хорошо бы еще разводку ПП посмотреть — залепить каждый корпус по питанию парой конденсаторов (керамика + тантал) конечно можно, но это лишние элементы, а внятная разводка земель и питания ничего не стоит :)
    И к слову, брать «медленные» ИС только потому, что быстрые звенят по питанию, когда драйвят мощную нагрузку — это не очень честное решение. Лучше ограничить скорость роста тока, включив в цепь питания светодиодов (надеюсь, индикаторы применены с общим анодом) RC или LC-фильтр — ну и подключить его прямо к выходу ИС стабилизатора напряжения.


    1. bladeser
      09.11.2015 05:18

      Такая логика была взята по двум причинам. Первая — мне ее достаточно. И по току и по быстродействию. Вторая — эта логика была легко доступна для меня только и всего. Индикатор с общим анодом таки да.


  1. Zzzuhell
    09.11.2015 14:33

    А я для разнообразия спрошу про йогурт.
    Чем вас не устраивали фабричные модели? Отсутствием регулировки температуры? Так это же регулируется временем приготовления вроде.
    У меня самая «дубовая» модель, без таймера. Включаю ее в механический суточный таймер (типа таких, как применяются для освещения растений). Два «пристрелочных» раза пробовал разное время, на третий все пошло на лад.
    Или вы какой-то особый йогурт готовите, с определенным числом бактерий на единицу объема :)? /сарказм/


    1. bladeser
      10.11.2015 20:25

      <режим зануды>Бактерии одного конкретного вида (а иногда и штамма) чувствуют себя максимально хорошо при определённой температуре. Отклонения температуры от этого значения меняет соотношение числа бактерий разных видов. Если учесть что бактерии разных видов продуцируют разные продукты своей жизнедеятельности то и вкус конечного продукта зависит от температуры. Причём он зависит и от времени так как после переработки одной составляющей продукта одним видом бактерий за обработку продукта берётся другой вид. <\режим зануды>


      1. Zzzuhell
        10.11.2015 22:21

        Вот это я называю — по настоящему заморочиться! Супер!
        А где закваску (чистые штаммы) берете? Какие предпочитаете?
        Я сам экспериментировал как с собственно йогуртами, так и с т.н. простоквашей. Ну и ацидофилин, конечно.


        1. bladeser
          11.11.2015 08:13

          В аптеке конечно. Иногда можно воспользоваться свежим даноном :-)