Да, безусловно, как посадить катоды на землю прекрасно понимаю, а будет ли так работать, имею ввиду без програмной смены полярности на выходах мк (порты 0-7) ?
Скетч править -- это само собой. Сейчас глянул, всего придется вносить изменения в три строки. Одна строка (номер 207) в обработчике прерывания COMPA, и две (261-262) в COMPB. Смысл простой -- там, где для общего анода бит выставляется, для общего катода он должен сбрасываться и наоборот.
Dm77 пишет:
Ребят. схема протестирована.
А получилось что-то с экранированием?
Не стал городить поддоны. В принципе кроме как дрожания символов паяние не страдает. А это главное. Думаю просто вынести плату в отдельный маленький корпус (благо не греется ничего) и питаль от ноутбучного БП.
В принципе, если предполагаются тяжелые помеховые условия эксплуатации, как в случае с "фонящим" блоком питания, то можно режим индикации заданной температуры, вместо измеренной, выбрать в качестве основного. Даже если нагреватель будет отрабатывать не совсем точно, то за счет интерности жала температура на кончике будет в значительной степени усредняться близ заданного значения.
Я поставил 0,125Вт, работает. Цвет не поменяли, рукой подлезть потрогать не подлезть. Эти сопротивления работают в короткий промежуток времени , пока не включится симистор, а это происходит в начале полупериода. Так что все гут!
Порядком достало, что плата на проводах по столу ездит, решил прикрутить на общее основнание и закрепить кабель. Основанием послужила какая-то старая и давно распаянная на запчасти плата неизвестно от чего. Вот, что получилось:
Сверху от паялки можно наблюдать плату преобразователя (DC-DC) 12 вольт на 24 вольта. Так как питание от настольного компа у меня основное, а после замеров скорости нагрева выяснилось, что разогрев с 12 вольт получается долгий, то решил дополнить устройство бустером:
Данная повышайка собрана на контроллере UC3843 по схеме близкой к референсной. Дроссель намотан на кольце со старой материнской платы. Материал №52, цвет салатовый с синим, размеры 15,5 х 8,5 х 6 мм. Использовался сложенный вдвое провод диаметром 0,5мм, который наматывался без предварительного расчета из соображений "сколько влезет". Измеренная индуктивность в итоге составила 22мкГн, что вполне устроило. Изначально были представления, что кольцо должно быть существенно больше размерами, т.к. планировалось снимать с него более 50 Ватт мощности, но эксперимент показал, что и это двольно компактное кольцо вполне работоспособно при нагреве до 50-60 градусов во время работы.
Так как микросхема у меня была в корпусе под поверхностный монтаж, то основная часть деталей также размещена на стороне дорожек:
Мосфет с допустимым током до 80 ампер выдран с той же материнки. Большинство деталей надерганы с плат из ящика с радиохламом. В общем, получилось довольно бюджетно и приемлемо по параметрам. Если у кого-то возникнет желание повторить, могу выложить схему и чертеж платы.
Некоторые элементы я забрал в рамку из пунктира, чтобы пометить, что присутствие этих деталей желательно, но если по каким-то причинам нет возможности их раздобыть, то можно не ставить. Единственное уточнение -- резистор R4 не просто не устанавливать, а заменить перемычкой.
Полуваттные резисторы R6-R9 включены в параллель, чтобы набрать общее сопротивление 0.025 ома. Единичных сопротивлений столь малой величины среди запасов и в продаже отыскать не удалось, т.ч. пришлось параллелить то, что оказалось доступно. В принципе, там можно поставить одно сопротивление 0.025 ома мощностью 1-2 ватта. Столь экзотический резистор в схеме присутствует для ограничения максимального тока через ключ. Если поставить резистор с большим номиналом, то преобразователь будет давать просадку напряжения при пиковых нагрузках, если номинал выбрать ниже, то увеличится нагрузка на источник.
Диод D2 -- это Шоттки с рабочим током не ниже 3 ампер (например, B340, SS34, B34, SK34 и т.п.). На самом деле пиковые нагрузки на этот диод в данной схеме существенно выше, но у большинства производителей данные приборы держат в пике по 80-120 ампер, т.ч. их использование вполне тут оправдано. В принципе, величина тока в большинстве случаев ограничивается тепловыделением кристала и если обеспечить должный теплоотвод, то рабочий ток можно смело задирать.
Мосфет лучше выбирать с минимальным значением сопротивления канала в открытом состоянии (Rds) и на напряжение не ниже 30 вольт. Хорошо себя показали мощные мосфеты с материнских плат.
Вообще, данную повышайку можно использовать не только применительно к паялке, но и для любых других надобностей, где возникает потребность повысить напряжение. На вход можно подавать любое напряжение из диапазона 9в..30в, а с выхода получать не ниже, чем входное. По похожим схемам делают бустеры вольт до четырехсот и выше. Разумеется, детали силовой части должны быть расчитаны на подобные напряжения.
Выходное напряжение определяется величинами R10, R11+R12 в резиситвном делителе. Можно их рассчитать по формуле V(out) = 2.5 * (1 + R10/(R11 + R12)), но я как-то привык пользоваться онлайн-калькулятором. Поле "Input Voltage" оставляем пустым, в поле "Output voltage" заносим константу 2.5, а R1 и R2 -- это R10 и R11+R12 с вышеприведенной схемы. "Играя" значениями в полях R1 и R2 можно подобрать номиналы делителя на желаемое выходное напряжение.
Если вникать в тонкости схемы нет желания, а просто хочется повторить устройство, то вот вариант схемы и платы в формате протеуса. Размеры платы специально сделаны попросторнее, т.к. пустые участки меди служат радиатором, отводя тепло от греющихся элементов -- диода и мосфета.
Здравствуйте. Собрал себе паяльную станцию по проекту a5021 (за что ему отдельное большое спасибо). Споткнулся на калибровке. Не могу понять, как (или где) увидеть значения getOversampled(). Может я задаю глупый вопрос, но до этого проекта с ардуиной не имел дела. А после прочтения форума появилось желание для начала просто повторить. Поэтому, если не трудно разъясните более подробно. И после того, как я выясню значения getOversampled(), нужно заново заливать скетч в ардуину?
Я уже где-то выше писал, что, по идее, процедура калибровки должна быть встроенная, но пока у меня так и не хватило сил и времени, чтобы написать ее в полном объеме. Поэтому на данный момент калибровка страдает изрядной горбатостью, когда нужно сначала выяснить эти самые значения getOversampled(), затем внести полученные значения в исходники и перезалить скетч.
О том, как проще выяснить, что там getOversampled() возвращает: мне в голову не пришло ничего лучше, как сделать довольно грубый хак, чтобы скетч показывал эти значения на основном индикаторе. Это не самое лучшее решение, но зато быстрое. В общем, если раскомментировать определение CALIBRATION_BUILD в тексте скетча, что я прикладываю ниже, то после его сборки и заливки паялка потеряет почти весь свой функционал, перестанет включать нагреватель вообще, но зато будет показывать на дисплее три последние цифры значения, возвращаемого функцией getOversampled(). Старшая цифра без сильного нагрева всегда 1, а если греть дальше, то можно отследить смену старшего разряда по переходу значений на индикаторе через ноль.
Тут подумалось, что для калибровки, возможно, удобно будет воспользоваться медицинским термометром, как прибором достаточно точным в рамках некоторого диапазона. Процедура может быть следующей: заливаем в паялку скетч с раскомментированным определением CALIBRATION_BUILD. Наливаем в некую посудину теплой воды, по температуре близкой к температуре человеческого тела. Посудину лучше чем-нибудь укутать, чтобы быстро не остывала. Раскручиваем паяльник, чтобы нагреватель торчал наружу и помещаем его (нагреватель) в воду. В эту же воду помещаем медицинский термометр. Включаем паялку. Ждем некоторое время, пока все прогреется и записываем значения с термометра и дисплея паялки на бумажку. Выливаем воду и убираем медицинский термометр. Теперь берем другой термометр, с помощью которого можно измерять температуту горячей воды, наливаем в посудину кипяток из чайника и схоожим образом фиксируем новые значения. Переносим числа с бумажки в текст скетча, выносим CALIBRATION_BUILD в комментарии и перезаливаем скетч. Вытираем нагреватель, скручиваем паяльник. Все, паялка откалибрована и готова к работе.
Ну и сам скетч в новой версии. Никаких новых фич, кроме возможности сборки калибровочного билда в нем нет, т.ч. тем, кто уже пользуется данной паялкой смысла его заливать никакого нет.
Спасибо, a5021. Все очень доходчиво. Попробовал откалибровать с обычным термометром. На температурах до 300 градусов присутствует погрешность. Ближе к 400 градусов погрешности почти нет. Видимо из-за того, что калибровал обычным термометром. Попробую найти лабораторный термометр с десятыми градусов и еще раз откалибровать.
Я задумывался над тем, чтобы развести еще и smd-версию, но остановило опасение, что она не будет востребована. Трассировка хоть и интересный, но довольно длительный процесс, а времени, как обычно, ни на что не хватает. В принципе, если общественность проявит более активный интерес, может и сподоблюсь. Но тут важным становится вопрос, в каких размерах это все делать. Для себя я делаю все максимально мелко и тонко, но это требует определенной квалификации при изготовлении платы, что может вызвать трудности у начинающих. Еще вопрос конструктивов и размерносей компонентов не совсем однозначен. Если я разведу под свои компоненты, то это наверняка приведет к трудностям с поиском того же самого при повторении кем-то другим.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
А почему сложно? термопарой мультиметра например отлично меряется. Соответственно у каждого жала при одной и тойже температуре разные калибровочные значения. Хранить можно прям в скетче массивом. Выбирать (например) удержанием кнопки + потенциомерт вправо - влево
Термопарой, подключенной к мультиметру, получится измерить только "стреднюю температуру по больнице". Даже не уверен, что она покажет разную температуру для разных жал. Для калибровки "взрослых" паяльных станций в комплекте к ним идут специальные устройства для измерения темпертуры именно жала и существуют требования по организации таких измерений. Кончик жала может изменять температуру на десятки градусов только от одного движения воздуха в помещении. Как я говорил еще в самом первом сообщении, приходится иметь дело лишь с приблизительными температурами в зоне пайке и с этим, по большому счету, ничего не поделать.
Большое спасибо a5021 за данный проект, сделал, запустил (не без проблем, но это из-за своих ошибок) - доволен как слон. НО! В языке программирования я очень начинающий и не смог понять как "раскоментировать" и соответственно не могу откалибровать паяльник. Не мог бы кто нибуть выложить скетч с раскомментированным определением CALIBRATION_BUILD. Буду премного благодарен!
Еще пара вопросов: в каких случаях издается звуковой сигнал? При питании данной схемы от БП компьютера можно обойтись без кренки и питать от +5 вольт БП?
Раскомментировать -- значит убрать знак(и) комментария. В данном случае речь идет о строке № 26. Уберите два слеша ("//") в начале строки и директива будет раскомментирована. Чтобы закомментировать обратно, эти два слеша надо вернуть. Вот и вся премудрость.
Без кренки обойтись можно, но подаваемые +5в от БП не должны иметь больших пульсаций. Шум по линии +5в может плохо влиять на точность измерений температуры и, как следствие, на стабильность показаний на индикаторе.
Подать +5в напрямую от БП можно, если не запаивать эту самую кренку, а припаять провод прямо вместо ее вывода №3. Весьма не лишним в этом случае будет увеличить емкость конденсатора С5 из расчета, чем больше, тем лучше.
Диод там был поставлен исходя из двух соображений: а) шунтировать диодом индуктивную нагрузка (динамик, в данном случае) является хорошим тоном, чтобы потом не разбираться с непонятными переходными процессами; б) динамик может оказаться пьезоэлектрическим (иногда их по виду отличить сложно), который при механическом воздействии на него (удар, падение) может сам являться генератором значительных напряжений, достаточных, чтобы спалить транзистор, нагрузкой для которого он является.
Если по каким-то соображениям вы не хотите устанавливать диод, можно не устанавливать. Непосредственно на функционал это не влияет. Диод выполняет защитные функции и только лишь в некоторых случаях.
Добрый день. Сделал каллибровку по вашей методике, получил значения 36,2 (градуса) - 993 (на дисплее), и 85 - 213. В какие строки кода внести это значения?
Все прошилось, по личным ощущениям температура жала стало грется сильнее, но точнее сказать пока не могу - завтра возьму у знакомого дистанционный термометр - измерю точнее. Есть такая" шероховатость" -при крайнем положении переменика температура на индикаторе скачком снижается к минимальной. Переменик 12 ком. Это можно исправить?
И неплохо бы увеличить время перехода паяльника в "сон", у меня оно около 5 минут. Попутно вопрос - переход в сон происходит когда регулировку не трогаем или при отсутствии резких изменений температуры жала? Типа не паяем - температура почти постоянная, изменения в пару градусов.
С переменником вы сурово поступили. При такой замене вы отрезали 9/10 диапазона регулирования в верхней части. Чтобы использовать переменник величиной 1ком, резисторы R20 и R21 должны быть 270ом и 1ком соответственно.
Переход в сон зависит от температуры жала и составляет 15 секунд при крайне правом положении переменника и один час при крайне левом. Промежуточные положения "размазаны" пропорционально. Крайние значиния для диапазона заданы определениями в тексте скетча:
Условием для перехода в "сон" является отсутствие воздействия на органы управления (переменник, кнопка) или резких изменений температуры. Последнее не является режимом детектирования пайки. Паялка уйдет в сон не зависимо от того, происходит пайка или нет.
Приношу свои извинения, неправильно посчитал значение переменика, на нем обозначение В103 - это все таки 10кОм. Но температура при приближении к крайнему максимальному положению падает до минимальной. Напряжение на среднем выводе переменика меняется от 0 вольт до 0.98.
Для идеального случая оно должно меняться с нуля до 1.1 вольта (величина внутреннего опорного напряжения атмеги), но так как идеального ничего не существует, а существует разброс в величинах сопротивлений R20, R21 и самого переменника, то 0.98 -- это, пусть и не лучший, но вполне допустимый результат. Чуть снизится верхний предел регулировки. А вот почему падает температура на правом краю, тут пока загадка. Покопаюсь на досуге в исходниках. Есть нехорошее подозрение, что это может оказаться переполнением какой-то переменной.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала? Т.е. на индикаторе у меня 439 градусов (больше не устанавливается - сбрасывается) а по ощущениям намного меньше. Измерить температуру времено не могу - приятель только на днях термометр принесет.
Извините что не по теме, но хочу задать один вопрос в сило своей не грамотности в области электроники.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Просто на основе похожей схемы собрал диммер к ESP8266. В режиме реле работает отлично, а вот диммировать лампу накаливания не хочет (хотя замерял сопротивление через BTA16 изменяется от 5кОм и выше). Или MOC3061 с его детектором перехода через 0 тут ни при чем и я просто сделал что-то не так?
Тест на нем проводил - последовательно 2 лампы 12В 100Вт. Зажглись, ток выдал в районе 3,96А, в защиту не ушел, но хорошо гудел. Для паяльника должен подойти (для чего я собственно и заказывал).
Второй вопрос. Ардуины на борту имеют стабилизатор, на моей Мини Про LG50 - 500ма, до 12В. Вместе например с КРЕН 9В можно распределить тепло и уменьшить количество радиаторов. Токи вроде небольшие.
БП симпатичный и по деньгам вполне неплохо. Если он держит заявленные характеристики, то это как раз то, что нужно. Даже если будет срабатывать защита при холодном включении, теперь есть ШИМ-разогрев, который купирует эту проблему.
Насчет набортного регулятора ардуины -- использовать его по предложенной вами схеме проблематично. Помимо самого ардуины есть еще остальная схема, которая так же расчитана на питание от 5 вольт. Если туда подать 9 вольт, то это напряжение через светодиоды индикатора окажется на ногах ардуины и даже если не сожжет сразу, то начнет "поднимать" его, т.к. выходы внутри атмеги через защитные диоды соеденины с шиной +5v.
Насчет разогрева линейного регулятора (7805) хочу заметить, что несмотря на то, что греется он весьма ощутимо, температура прибора не выходит за рамки допустимых эксплуатационных пределов. Монтаж с использованием платы в качестве радиатора в данном случае допускает и большую тепловую нагрузку. Если не смотря на это кому-то хочется, чтобы вообще ничего не грелось, то нет никаих проблем в дырки от 7805 запаять провода с внешнего импульсного преобразователя. Так популярная понижайка на lm2596
вписывается сюда без каких бы то нибыло вопросов.
dobrman пишет:
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Он включается только при переходе волны через ноль и всякий шим в другое время ему по барабану.
Frolv пишет:
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала?
По стабилизатору на борту я имел в виду, что даем 9В (можно даже 12В) на порт Vin или RAW (в зависимости от модели Ардуино), а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Но со step-down конвертером конечно же будет лучше. Только его еще заказать и дождаться нужно.
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Ток через дисплей в пике составляет 7сегментов * 20ма = 140ма. Сам ардуино кушает 30-40ма. Добавим потребление прочих элементов схемы и в сумме получится где-то 200ма. Ток кажется вполне приемлемым. Но это только до того, как начнем считать мощность выделяемую в тепло на линейном стабилизаторе ардуины. А она будет выглядеть так: P= (Vin - Vout) * Iout. Для наших цифр это получится (12-5) * 0.2 = 1.4W, что является трижды запредельной величиной для того типа корпуса, в котором регулятор распаян на ардуине. Регулятору в таких условиях скорее всего захочется выпаяться (с этим у него проблем не возникнет) и убежать. :)
Цитата:
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
По хорошему, надо дописать использование аппаратного ватчдога ардуины в скетче. Только это будет не защита от неконтролируемого нагрева паяльника, а просто от зависания ардуины. Но тут есть подводные грабли, т.к. разработчики ардуины сделали все возможное, чтобы сделать использование ватчдога максимально сложным. Чтобы быстро выпустить рабочую версию скетча, от многих задумок, которые там должны, по-хорошему, присуствовать, мне пришлось, как минимум на время, отказаться.
Использование аппаратной защиты тянет за собой усложнение схемы и вызывает лишние сложности с повторением, особенно начинающими. По своему опыту эксплуатации различных самодельных паялок я знаю, что неконтролируемый разогрев паяльника ситуация довольно редкая. У меня это случалось только во время разработки и исключительно из-за собственной невнимательности. Риск того, что правильно собранная схема при подаче на нее рекомендованных напряжений самопроизвольно выйдет из строя не очень велик, т.ч. взвесив плюсы и минусы, от реализации аппаратной защиты я решил отказаться.
Если кому-то захочется повышенной надежности, то можно добавить в схему компаратор с порогом 1.2в и подключить его параллельно входу АЦП ардуины. На выходе компаратора будет формироваться аварийный сигнал в случае, если нагрев паяльника превысил допустимый диапазон.
Цитата:
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
В этом случае мы поимеем сразу несколько минусов по сравнению с нынешней схемой. Имеются достаточно значимые основания, чтобы так не делать, но чтобы еще больше не загромождать объяснение, просто встаньте осциллографом на шину +5в и посмотрите, что на ней твориться во время работы схемы. Если это употребить в качестве опорного напряжения, то о точности удержания температуры лучше 10-20 градусов можно даже и не заикаться.
Попробую объяснит - это про температуру. У меня по индикатору температура не устанавливается выше 439 градусов. По моим ощущениям (возможно ошибочным) это не соответствует действительности - температура на жале паяльника ниже. Калибровку по вашей методике делал - не сильно помогло. Можно ли поправить код таким образом что бы поднять температуру? Т.е. по индикатору предположим 300, а на жале - 350.
По переходу паяльника в "сон". Как то странно это происходит. На максимальной температуре паяльник лежит на подставке несколько десятка два минут - в "сон" не переключается, начал пользоваться (паять) плату - через полминуты запищал сигнал начала перехода в "сон" Может лучше режим "сон" назначить на кнопку? Нажал - паяльник уснул, через несколько минут (предположим минут 10-15) нагрев вообще выключился.
Мой совет, сначала все-таки установите сколь нибудь более достоверно, что ошибка индикации температуры имеет место. Я бы вот на глаз вряд ли смог различать температуры пяльника 440 и 380 градусов, скажем. И что вы, если не секрет, паяете при такой температуре жала? Я, например, уже не помню, когда последний раз что-то паял с температурой больше 320 градусов.
Если вам непременно хочется, чтобы паяльник грел сильнее, уменьшите значение ADC_CALIBRATION_DATA_HIGH
Режим сна задуман, как средство против забывчивости. Оставлять паяльник включенным на долгое время все-таки не лучшая идея. Если в сон уходить только по кнопке, то велик шанс получить ситуацию, когда и на кнопку забудешь нажать, а паяльник будет сутки барабанить, дожигая жало.
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое заземление?
это защита от поражения электрическим током человека.
Что подключается к заземлению?
Все нетоковедущие части электроустановки, которые могут оказаться под напряжением.
Из этого следует, что к заземлению нужно подключать все металлические части корпуса, которые могут оказаться под напряжением. конденсатор на землю, это не заземление.
Скетч править -- это само собой. Сейчас глянул, всего придется вносить изменения в три строки. Одна строка (номер 207) в обработчике прерывания COMPA, и две (261-262) в COMPB. Смысл простой -- там, где для общего анода бит выставляется, для общего катода он должен сбрасываться и наоборот.
А получилось что-то с экранированием?
Не стал городить поддоны. В принципе кроме как дрожания символов паяние не страдает. А это главное. Думаю просто вынести плату в отдельный маленький корпус (благо не греется ничего) и питаль от ноутбучного БП.
В принципе, если предполагаются тяжелые помеховые условия эксплуатации, как в случае с "фонящим" блоком питания, то можно режим индикации заданной температуры, вместо измеренной, выбрать в качестве основного. Даже если нагреватель будет отрабатывать не совсем точно, то за счет интерности жала температура на кончике будет в значительной степени усредняться близ заданного значения.
Подскажите какой мощности резисторы в цепи управления нагревателем фена в схеме ? - http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino?page=1#comment-86493
Я поставил 0,125Вт, работает. Цвет не поменяли, рукой подлезть потрогать не подлезть. Эти сопротивления работают в короткий промежуток времени , пока не включится симистор, а это происходит в начале полупериода. Так что все гут!
Порядком достало, что плата на проводах по столу ездит, решил прикрутить на общее основнание и закрепить кабель. Основанием послужила какая-то старая и давно распаянная на запчасти плата неизвестно от чего. Вот, что получилось:
Сверху от паялки можно наблюдать плату преобразователя (DC-DC) 12 вольт на 24 вольта. Так как питание от настольного компа у меня основное, а после замеров скорости нагрева выяснилось, что разогрев с 12 вольт получается долгий, то решил дополнить устройство бустером:
Данная повышайка собрана на контроллере UC3843 по схеме близкой к референсной. Дроссель намотан на кольце со старой материнской платы. Материал №52, цвет салатовый с синим, размеры 15,5 х 8,5 х 6 мм. Использовался сложенный вдвое провод диаметром 0,5мм, который наматывался без предварительного расчета из соображений "сколько влезет". Измеренная индуктивность в итоге составила 22мкГн, что вполне устроило. Изначально были представления, что кольцо должно быть существенно больше размерами, т.к. планировалось снимать с него более 50 Ватт мощности, но эксперимент показал, что и это двольно компактное кольцо вполне работоспособно при нагреве до 50-60 градусов во время работы.
Так как микросхема у меня была в корпусе под поверхностный монтаж, то основная часть деталей также размещена на стороне дорожек:
Мосфет с допустимым током до 80 ампер выдран с той же материнки. Большинство деталей надерганы с плат из ящика с радиохламом. В общем, получилось довольно бюджетно и приемлемо по параметрам. Если у кого-то возникнет желание повторить, могу выложить схему и чертеж платы.
Будьте добры выслать схему и чертеж на мыло shakalby@mail.ru
Спасибо большое заранее!!!
Проще будет прямо здесь разместить. Вот схема:
Некоторые элементы я забрал в рамку из пунктира, чтобы пометить, что присутствие этих деталей желательно, но если по каким-то причинам нет возможности их раздобыть, то можно не ставить. Единственное уточнение -- резистор R4 не просто не устанавливать, а заменить перемычкой.
Полуваттные резисторы R6-R9 включены в параллель, чтобы набрать общее сопротивление 0.025 ома. Единичных сопротивлений столь малой величины среди запасов и в продаже отыскать не удалось, т.ч. пришлось параллелить то, что оказалось доступно. В принципе, там можно поставить одно сопротивление 0.025 ома мощностью 1-2 ватта. Столь экзотический резистор в схеме присутствует для ограничения максимального тока через ключ. Если поставить резистор с большим номиналом, то преобразователь будет давать просадку напряжения при пиковых нагрузках, если номинал выбрать ниже, то увеличится нагрузка на источник.
Диод D2 -- это Шоттки с рабочим током не ниже 3 ампер (например, B340, SS34, B34, SK34 и т.п.). На самом деле пиковые нагрузки на этот диод в данной схеме существенно выше, но у большинства производителей данные приборы держат в пике по 80-120 ампер, т.ч. их использование вполне тут оправдано. В принципе, величина тока в большинстве случаев ограничивается тепловыделением кристала и если обеспечить должный теплоотвод, то рабочий ток можно смело задирать.
Мосфет лучше выбирать с минимальным значением сопротивления канала в открытом состоянии (Rds) и на напряжение не ниже 30 вольт. Хорошо себя показали мощные мосфеты с материнских плат.
Вообще, данную повышайку можно использовать не только применительно к паялке, но и для любых других надобностей, где возникает потребность повысить напряжение. На вход можно подавать любое напряжение из диапазона 9в..30в, а с выхода получать не ниже, чем входное. По похожим схемам делают бустеры вольт до четырехсот и выше. Разумеется, детали силовой части должны быть расчитаны на подобные напряжения.
Выходное напряжение определяется величинами R10, R11+R12 в резиситвном делителе. Можно их рассчитать по формуле V(out) = 2.5 * (1 + R10/(R11 + R12)), но я как-то привык пользоваться онлайн-калькулятором. Поле "Input Voltage" оставляем пустым, в поле "Output voltage" заносим константу 2.5, а R1 и R2 -- это R10 и R11+R12 с вышеприведенной схемы. "Играя" значениями в полях R1 и R2 можно подобрать номиналы делителя на желаемое выходное напряжение.
Если вникать в тонкости схемы нет желания, а просто хочется повторить устройство, то вот вариант схемы и платы в формате протеуса. Размеры платы специально сделаны попросторнее, т.к. пустые участки меди служат радиатором, отводя тепло от греющихся элементов -- диода и мосфета.
Здравствуйте. Собрал себе паяльную станцию по проекту a5021 (за что ему отдельное большое спасибо). Споткнулся на калибровке. Не могу понять, как (или где) увидеть значения getOversampled(). Может я задаю глупый вопрос, но до этого проекта с ардуиной не имел дела. А после прочтения форума появилось желание для начала просто повторить. Поэтому, если не трудно разъясните более подробно. И после того, как я выясню значения getOversampled(), нужно заново заливать скетч в ардуину?
Я уже где-то выше писал, что, по идее, процедура калибровки должна быть встроенная, но пока у меня так и не хватило сил и времени, чтобы написать ее в полном объеме. Поэтому на данный момент калибровка страдает изрядной горбатостью, когда нужно сначала выяснить эти самые значения getOversampled(), затем внести полученные значения в исходники и перезалить скетч.
О том, как проще выяснить, что там getOversampled() возвращает: мне в голову не пришло ничего лучше, как сделать довольно грубый хак, чтобы скетч показывал эти значения на основном индикаторе. Это не самое лучшее решение, но зато быстрое. В общем, если раскомментировать определение CALIBRATION_BUILD в тексте скетча, что я прикладываю ниже, то после его сборки и заливки паялка потеряет почти весь свой функционал, перестанет включать нагреватель вообще, но зато будет показывать на дисплее три последние цифры значения, возвращаемого функцией getOversampled(). Старшая цифра без сильного нагрева всегда 1, а если греть дальше, то можно отследить смену старшего разряда по переходу значений на индикаторе через ноль.
Тут подумалось, что для калибровки, возможно, удобно будет воспользоваться медицинским термометром, как прибором достаточно точным в рамках некоторого диапазона. Процедура может быть следующей: заливаем в паялку скетч с раскомментированным определением CALIBRATION_BUILD. Наливаем в некую посудину теплой воды, по температуре близкой к температуре человеческого тела. Посудину лучше чем-нибудь укутать, чтобы быстро не остывала. Раскручиваем паяльник, чтобы нагреватель торчал наружу и помещаем его (нагреватель) в воду. В эту же воду помещаем медицинский термометр. Включаем паялку. Ждем некоторое время, пока все прогреется и записываем значения с термометра и дисплея паялки на бумажку. Выливаем воду и убираем медицинский термометр. Теперь берем другой термометр, с помощью которого можно измерять температуту горячей воды, наливаем в посудину кипяток из чайника и схоожим образом фиксируем новые значения. Переносим числа с бумажки в текст скетча, выносим CALIBRATION_BUILD в комментарии и перезаливаем скетч. Вытираем нагреватель, скручиваем паяльник. Все, паялка откалибрована и готова к работе.
Ну и сам скетч в новой версии. Никаких новых фич, кроме возможности сборки калибровочного билда в нем нет, т.ч. тем, кто уже пользуется данной паялкой смысла его заливать никакого нет.
001
/*
002
**
003
** ARDUINO Soldering Station TH v1.21 (c) a5021
004
** march - september 2015
005
**
006
** <a href="http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino" title="http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino" rel="nofollow">http://arduino.ru/forum/proekty/payalnaya-stantsiya-iz-arduino</a>
007
**
008
** HISTORY
009
** =======
010
** september 2015 -- version 1.21:
011
* - added CALIBRATION_BUILD conditional compilation macro;
012
** august 2015 -- version 1.2:
013
** - improved temperature keeping stability;
014
** - ADC procedure rewritten;
015
** - several code improvements;
016
** july 2015 -- version 1.02:
017
** - fixed some stupid errors in preHeat() pprocedure;
018
** july 2015 -- version 1.01:
019
** - added preheat procedure;
020
** may 2015 -- version 1.00:
021
** - first public release
022
*/
023
024
#include <avr/sleep.h>
025
026
//#define CALIBRATION_BUILD 1
027
028
// use PREHEAT_ENABLE in case the PSU is not powerful enough
029
// this force PWM-mode preheating when soldering iron is cold
030
031
#define PREHEAT_ENABLE 1
032
033
// ohmic value of the upper resistor in the voltage divider
034
#define R1 220.0
035
// external voltage reference (TL431)
036
#define V_REF 2.495
037
// calibrated atmega's internal voltage reference
038
#define REFERENCE_1V1 1.087
039
040
/*
041
** soldering iron's thermal probe calibration data definitions
042
**/
043
044
#define CALIBRATION_TEMP_LOW ((unsigned int) 2950)
045
#define CALIBRATION_TEMP_HIGH ((unsigned int) 18300)
046
#define ADC_CALIBRATION_DATA_LOW ((unsigned int) 1658)
047
#define ADC_CALIBRATION_DATA_HIGH ((unsigned int) 2373)
048
049
/*
050
long map(long x, long in_min, long in_max, long out_min, long out_max)
051
{
052
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
053
}
054
*/
055
056
// low temperature degree (multiplied by 100)
057
#define LOW_TEMP_DEGREE ((unsigned int)18500)
058
// high temperature degree (multiplied by 100)
059
#define HIGH_TEMP_DEGREE ((unsigned int)45800)
060
#define HIGH_TEMP_MARGIN ((unsigned long int)(HIGH_TEMP_DEGREE - CALIBRATION_TEMP_LOW) * \
061
(ADC_CALIBRATION_DATA_HIGH - ADC_CALIBRATION_DATA_LOW) \
062
/ (CALIBRATION_TEMP_HIGH - CALIBRATION_TEMP_LOW) \
063
+ ADC_CALIBRATION_DATA_LOW)
064
#define LOW_TEMP_MARGIN ((unsigned long int)(LOW_TEMP_DEGREE - CALIBRATION_TEMP_LOW) * \
065
(ADC_CALIBRATION_DATA_HIGH - ADC_CALIBRATION_DATA_LOW) \
066
/ (CALIBRATION_TEMP_HIGH - CALIBRATION_TEMP_LOW) \
067
+ ADC_CALIBRATION_DATA_LOW)
068
069
// min timeout in seconds
070
#define MIN_TIMEOUT_SEC 15
071
// max timeout in seconds
072
#define MAX_TIMEOUT_SEC (60 * 60)
073
// low power mode duration in seconds
074
#define LOW_POWER_MODE_DURATION (15 * 60)
075
// num of beeps before go standby
076
#define TICK_TOCK_COUNT 10
077
// time before the display to be dimmed
078
#define TIME_BEFORE_DIM 10
079
080
#ifndef CALIBRATION_BUILD
081
// heater control macros
082
#define TURN_HEATER_ON sbi(PORTB, PORTB1)
083
#else
084
#define TURN_HEATER_ON cbi(PORTB, PORTB1)
085
#endif
086
087
#define TURN_HEATER_OFF cbi(PORTB, PORTB1)
088
// LED signaling
089
#define TURN_LED_ON sbi(PORTB, PORTB5)
090
#define TURN_LED_OFF cbi(PORTB, PORTB5)
091
092
093
// display brightness constants
094
#define MIN_BRIGHTNESS 0xEF
095
#define DEFAULT_BRIGHTNESS 0xB0
096
097
// where segment's cathodes are connected to
098
#define SEG_A (1 << PORTD5)
099
#define SEG_B (1 << PORTD7)
100
#define SEG_C (1 << PORTD0)
101
#define SEG_D (1 << PORTD3)
102
#define SEG_E (1 << PORTD4)
103
#define SEG_F (1 << PORTD6)
104
#define SEG_G (1 << PORTD1)
105
#define SEG_DP (1 << PORTD2)
106
107
// compose digits using separate segments
108
#define SIGN_8 (0xFF - SEG_DP)
109
#define SIGN_0 (SIGN_8 - SEG_G)
110
#define SIGN_1 (SEG_B + SEG_C)
111
#define SIGN_2 (SIGN_8 - SEG_C - SEG_F)
112
#define SIGN_3 (SIGN_8 - SEG_E - SEG_F)
113
#define SIGN_4 (SIGN_1 + SEG_F + SEG_G)
114
#define SIGN_6 (SIGN_8 - SEG_B)
115
#define SIGN_5 (SIGN_6 - SEG_E)
116
#define SIGN_7 (SIGN_1 + SEG_A)
117
#define SIGN_9 (SIGN_8 - SEG_E)
118
#define SIGN_BLANK 0
119
120
// compose some letters
121
#define SIGN_E (SIGN_6 - SEG_C)
122
#define SIGN_F (SIGN_E - SEG_D)
123
#define SIGN_r (SEG_G + SEG_E)
124
#define SIGN_n (SIGN_r + SEG_E)
125
126
// bit manipulation macros
127
#ifndef cbi
128
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
129
#endif
130
131
#ifndef sbi
132
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
133
#endif
134
135
// number-to-7seg code translation table
136
const
unsigned
char
codeTable[] = {~SIGN_0, ~SIGN_1, ~SIGN_2,
137
~SIGN_3, ~SIGN_4, ~SIGN_5,
138
~SIGN_6, ~SIGN_7, ~SIGN_8,
139
~SIGN_9};
140
141
// signs to be displayed
142
volatile unsigned
char
displayBuffer[] = {~SIGN_0, ~SIGN_F, ~SIGN_F},
143
globalEvent = 0,
// bitset for event handling
144
displayUpdateReq = 0,
145
readPotReq = 0,
146
currentDigit = 0;
// active digit at display
147
148
volatile unsigned
int
softTimer = 0,
// software timer downcounter
149
dimCounter = TIME_BEFORE_DIM,
// dim downcounter
150
toCounter1,
// time before low power mode
151
toCounter2,
// low power mode downcounter
152
toneDuration = 0;
// sound duration counter
153
154
/*
155
** application's event flags
156
*/
157
158
// keypress flag
159
#define EVENT_BUTTON_PRESSED (1<<0)
160
// button pressed for a long time
161
#define EVENT_BUTTON_LONG (1<<1)
162
// request tone generation
163
#define EVENT_BEEPER_REQ (1<<2)
164
// warming up or cooling down request
165
#define EVENT_TEMP_CHANGE_REQ (1<<3)
166
// audio alarm request
167
#define EVENT_TICK_TOCK_REQ (1<<4)
168
// attention request
169
#define EVENT_ATTN_REQ (1<<5)
170
// low power mode flag
171
#define EVENT_LOW_POWER_MODE (1<<6)
172
// go standby flag
173
#define EVENT_STANDBY_MODE (1<<7)
174
175
/*
176
** flag manipulation macros
177
*/
178
179
#define SET_EVENT(EVENT) cli(); globalEvent |= (EVENT); sei()
180
#define CLEAR_EVENT(EVENT) cli(); globalEvent &= ~(EVENT); sei()
181
#define CHECK_EVENT(EVENT) (globalEvent & (EVENT))
182
183
184
void
resetTimeout(unsigned
int
temperature) {
185
unsigned
int
m;
186
// calculate new timeout value based on current temperature
187
188
OCR0B = DEFAULT_BRIGHTNESS;
// restore display brightness
189
if
(!CHECK_EVENT(EVENT_TEMP_CHANGE_REQ)) {
// check if warming up flag is active
190
globalEvent = 0;
// reset all event flags
191
}
else
{
// when warming up or cooling dowm process is active
192
globalEvent = EVENT_TEMP_CHANGE_REQ;
// reset all event flags excluding that
193
}
194
195
/* the time before go standby and soldering iron's temperature have an inverse relationship:
196
the higher termerature is, the less time it is allowed. */
197
198
m = map(temperature, LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN, MAX_TIMEOUT_SEC, MIN_TIMEOUT_SEC);
199
200
cli();
201
// set values for timeout variables
202
dimCounter = TIME_BEFORE_DIM;
203
toCounter1 = m;
204
toCounter2 = LOW_POWER_MODE_DURATION;
205
sei();
206
}
207
208
ISR (PCINT0_vect) {
209
// dummy interrupt service routine
210
// called when one of pins D8 to D13 has changed
211
}
212
213
ISR(TIMER0_COMPA_vect){
214
static
unsigned
char
mSec,
// millisecond counter
215
quartSec;
// 1/4 second counter
216
217
PORTC |= (1<<currentDigit);
// turn off current LED tube
218
// ==========================================================================================
219
// Timeout counter routine
220
// ==========================================================================================
221
222
if
(!(globalEvent & EVENT_TEMP_CHANGE_REQ)) {
// count if no TEMP_CHANGE_REQ active
223
if
(++mSec == 250) {
// check for millisecond counter overflow
224
mSec = 0;
// reset msec counter
225
if
(++quartSec == 4) {
// check for 1/4 sec counter overflow
226
quartSec = 0;
// reset 1/4 sec counter
227
228
// timeout counting
229
230
// =======================[ TICK-TOCK Signaling ]==============================================
231
if
(dimCounter > 0)
if
(--dimCounter == 0) OCR0B = MIN_BRIGHTNESS;
// set display brightness to min.
232
233
if
(toCounter1 > 0) {
//decrease timout counter till 0
234
if
(--toCounter1 != 0) {
235
// rise tick-tock flag
236
if
(toCounter1 <= TICK_TOCK_COUNT) globalEvent |= EVENT_TICK_TOCK_REQ;
237
}
else
{
238
// rise 'go low power mode' flag
239
globalEvent |= EVENT_LOW_POWER_MODE | EVENT_ATTN_REQ;
240
}
241
}
else
{
// in case low power mode is active
242
if
(toCounter2 > 0) {
// if timeout counter is greater than zero
243
if
(--toCounter2 != 0) {
// decrease timeout counter
244
if
(toCounter2 <= TICK_TOCK_COUNT) globalEvent |= EVENT_TICK_TOCK_REQ;
245
}
else
{
// if timeout counter is equal zero
246
globalEvent |= EVENT_STANDBY_MODE;
// rise 'go stamdby' flag
247
}
248
}
249
}
250
// ==========================================================================================
251
}
252
}
253
}
254
}
255
256
ISR(TIMER0_COMPB_vect){
257
//
258
// displaying data, debouncing the button, tone generation
259
//
260
261
static
unsigned
char
buttonState,
// current button state
262
prevButtonState;
// saved button state
263
264
static
unsigned
int
keypressDuration,
// button press duration
265
mSec;
// millisecond counter
266
267
//================================================================================================
268
// display routine
269
//================================================================================================
270
if
(++currentDigit == 3) currentDigit = 0;
// for every digit...
271
PORTD = displayBuffer[currentDigit];
// send value
272
PORTC &= ~(1<<currentDigit);
// and switch on
273
274
if
(softTimer != 0) softTimer--;
// decrease software timer
275
276
if
(currentDigit == 0) {
// on every 3rd call
277
//================================================================================================
278
// debouncing routine
279
//================================================================================================
280
buttonState <<= 1;
// prepare to get a new button state bit
281
if
((PINB & (1<<PINB0)) == 0) buttonState |= 1;
// check the button state and save it
282
if
(buttonState == 0 || buttonState == 0xFF) {
// check the button pressed or released
283
if
(buttonState != prevButtonState) {
// check the button state changed
284
if
(buttonState == 0xFF) {
// is it pressed?
285
globalEvent |= EVENT_BUTTON_PRESSED;
// rise 'button pressed' flag
286
}
287
}
288
if
(buttonState == 0xFF) {
// when the button is pressed
289
if
((!(globalEvent & EVENT_STANDBY_MODE))
// and device is not in standby
290
&& (++keypressDuration == 650)) {
// and the button is pressed long enough
291
globalEvent |= EVENT_STANDBY_MODE | EVENT_BUTTON_LONG;
// rise standby flag
292
keypressDuration = 0;
// reset keypress duration counter
293
}
294
}
else
{
295
keypressDuration = 0;
// reset keypress duration counter
296
}
297
}
298
prevButtonState = buttonState;
// save current button state
299
}
300
//================================================================================================
301
// Tone generation
302
//================================================================================================
303
if
(bit_is_set(TCCR1A, COM1B0)) {
// check if the tone generation is active
304
if
(toneDuration > 0) {
// check if duration counter is above zero
305
toneDuration--;
// decrease the counter
306
}
else
{
// in case of durationCounter == 0
307
cbi(TCCR1A, COM1B0);
// stop the tone generation
308
}
309
}
310
311
if
(CHECK_EVENT(EVENT_BEEPER_REQ) != 0) {
// check the tone generation request is appeared
312
CLEAR_EVENT(EVENT_BEEPER_REQ);
// reset request flag
313
sbi(TCCR1A, COM1B0);
// enable tone signal output
314
}
315
316
if
(dimCounter == 0) {
317
if
(++mSec == 150) {
318
readPotReq = 1;
319
}
else
if
(mSec > 299) {
320
mSec = 0;
321
displayUpdateReq = 1;
322
}
323
}
else
{
324
if
(++mSec == 50) {
325
readPotReq = 1;
326
}
else
if
(mSec > 99) {
327
mSec = 0;
328
displayUpdateReq = 1;
329
}
330
}
331
}
332
333
inline
void
setSoftTimer(unsigned
int
tValue) {
334
cli();
335
softTimer = tValue;
336
sei();
337
}
338
339
inline unsigned
int
getSoftTimer(
void
) {
340
// return soft timer downcounter value
341
unsigned
int
t;
342
cli();
343
t = softTimer;
344
sei();
345
return
t;
346
}
347
348
void
playTone(unsigned
int
pitchHz, unsigned
int
duration) {
349
// make sound
350
unsigned
int
pitch = (F_CPU / pitchHz - 2) / 2;
// calculate timer settings to generate desired pitch
351
cli();
// disable interrupts to make atomic assignment
352
OCR1A = pitch;
// set the new counter restart value
353
toneDuration = duration;
// set the new tone duration value
354
sei();
// enable interrupst
355
SET_EVENT(EVENT_BEEPER_REQ);
// send signal to the timer's ISR
356
}
357
358
359
#ifndef CALIBRATION_BUILD
360
void
fillDisplayBuffer(
int
value, unsigned
char
padChar) {
361
// convert int to string and fill the display buffer
362
unsigned
char
i = 3;
// digits at display
363
unsigned
int
dp_req = 0;
// decimal point required flag
364
div_t res;
// conversion divider
365
366
// check if it is the special value to shows the error message
367
if
(-9999 == value) {
368
displayBuffer[0] = ~SIGN_E;
369
displayBuffer[1] = ~SIGN_r;
370
displayBuffer[2] = ~SIGN_r;
371
return
;
372
}
373
374
// if passed value is smaller than 1000
375
if
(value < 1000) {
376
dp_req = 1;
// dot required
377
}
else
{
378
value /= 10;
// devide value to fit to display
379
}
380
381
// padding left
382
if
(value < 100) displayBuffer[0] = padChar;
383
if
(value < 10) displayBuffer[1] = padChar;
384
385
// convert integer to string and place it to the buffer
386
do
{
387
res = div(value, 10);
388
displayBuffer[--i] = codeTable[res.rem];
389
value = res.quot;
390
}
while
(value != 0 && i != 0);
391
// insert dot if required
392
if
(dp_req) displayBuffer[1] &= ~SEG_DP;
393
}
394
#else
395
void
fillDisplayBuffer(
int
value, unsigned
char
padChar) {
396
// convert int to string and fill the display buffer
397
unsigned
char
i = 3;
// digits at display
398
unsigned
int
dp_req = 0;
// decimal point required flag
399
div_t res;
// conversion divider
400
401
// convert integer to string and place it to the buffer
402
do
{
403
res = div(value, 10);
404
displayBuffer[--i] = codeTable[res.rem];
405
value = res.quot;
406
}
while
(value != 0 && i != 0);
407
}
408
#endif
409
410
411
void
setup
() {
412
413
// Input/Output Ports initialization
414
// Port B initialization
415
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=In
416
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (0<<DDB3) | (1<<DDB2) | (1<<DDB1) | (0<<DDB0);
417
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=T Bit2=1 Bit1=0 Bit0=P
418
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (1<<PORTB2) | (0<<PORTB1) | (1<<PORTB0);
419
420
// Port C initialization
421
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=Out Bit1=Out Bit0=Out
422
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (1<<DDC2) | (1<<DDC1) | (1<<DDC0);
423
// State: Bit6=T Bit5=P Bit4=P Bit3=T Bit2=0 Bit1=1 Bit0=1
424
PORTC=(0<<PORTC6) | (1<<PORTC5) | (1<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (1<<PORTC1) | (1<<PORTC0);
425
426
// Port D initialization
427
// Function: Bit7=Out Bit6=Out Bit5=Out Bit4=Out Bit3=Out Bit2=Out Bit1=Out Bit0=Out
428
DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
429
// State: Bit7=1 Bit6=1 Bit5=1 Bit4=1 Bit3=1 Bit2=1 Bit1=1 Bit0=1
430
PORTD=(1<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (1<<PORTD1) | (1<<PORTD0);
431
432
// Timer/Counter 0 initialization
433
// Clock source: System Clock
434
// Clock value: 250,000 kHz
435
// Mode: CTC top=OCR0A
436
// OC0A output: Disconnected
437
// OC0B output: Disconnected
438
// Timer Period: 1 ms
439
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (1<<WGM01) | (0<<WGM00);
440
TCCR0B=(0<<WGM02) | (0<<CS02) | (1<<CS01) | (1<<CS00);
441
OCR0A=0xF9;
442
OCR0B = DEFAULT_BRIGHTNESS;
443
444
// Timer/Counter 0 Interrupt(s) initialization
445
TIMSK0=(1<<OCIE0B) | (1<<OCIE0A) | (0<<TOIE0);
446
447
// Timer/Counter 1 initialization
448
// Clock source: System Clock
449
// Clock value: 16000,000 kHz
450
// Mode: CTC top=OCR1A
451
// OC1A output: Disconnected
452
// OC1B output: Disconnected
453
// Noise Canceler: Off
454
// Input Capture on Falling Edge
455
// Timer Period: 0,5 ms
456
// Output Pulse(s):
457
// Timer1 Overflow Interrupt: Off
458
// Input Capture Interrupt: Off
459
// Compare A Match Interrupt: Off
460
// Compare B Match Interrupt: Off
461
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
462
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
463
OCR1AH=0x1F;
464
OCR1AL=0x3F;
465
466
// ADC initialization
467
// ADC Clock frequency: 125,000 kHz
468
// ADC Voltage Reference: AREF pin
469
// ADC Auto Trigger Source: ADC Stopped
470
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: Off
471
// ADC4: On, ADC5: On
472
DIDR0=(0<<ADC5D) | (0<<ADC4D) | (1<<ADC3D) | (0<<ADC2D) | (0<<ADC1D) | (0<<ADC0D);
473
ADMUX=(1<<REFS1) | (1<<REFS0) | 7;
474
ADCSRA=(1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
475
476
// go standby as soon as power is applied
477
SET_EVENT(EVENT_STANDBY_MODE);
478
}
479
480
#ifndef CALIBRATION_BUILD
481
unsigned
int
getOversampled(
void
) {
482
unsigned
int
sSum = 0;
483
// get 64 samples after the channel has become stable
484
for
(
int
i = 0; i < 64; i++) {
485
sbi(ADCSRA, ADSC);
// Start the AD conversion (it also clears ADIF flag as a side effect of 'sbi')
486
loop_until_bit_is_set(ADCSRA, ADIF);
// wait for conversion complete
487
sSum += ADCW;
488
}
489
return
sSum >> 4;
// return averaged ADC result in 12 bit representation
490
}
491
#else
492
unsigned
int
getOversampled(
void
) {
493
unsigned
int
sSum;
494
unsigned
long
res = 0;
495
for
(
int
i = 0; i < 16; i++) {
496
// get 64 samples after the channel has become stable
497
sSum = 0;
498
for
(
int
j = 0; j < 64; j++) {
499
sbi(ADCSRA, ADSC);
// Start the AD conversion (it also clears ADIF flag as a side effect of 'sbi')
500
loop_until_bit_is_set(ADCSRA, ADIF);
// wait for conversion complete
501
sSum += ADCW;
502
}
503
res += sSum;
504
}
505
return
res >> 8;
// return averaged ADC result in 12 bit representation
506
}
507
#endif
508
509
unsigned
int
filterPot(unsigned
int
rawPot) {
510
static
unsigned
char
potPrev;
511
512
if
(rawPot == 0) {
513
potPrev = 0;
514
return
0;
515
}
516
517
unsigned
char
quot = rawPot / 15;
518
// check if pot's value is nearly the same
519
if
(potPrev == quot) {
520
return
quot + 1;
521
}
522
523
unsigned
char
rem = rawPot % 15;
524
525
if
(rem > 4 && rem < 12) {
526
potPrev = quot;
527
return
quot + 1;
528
}
529
// moving right
530
if
(quot == potPrev + 1) {
531
if
(rem < 5) {
532
return
quot;
533
}
534
}
535
// moving left
536
if
(potPrev = quot + 1) {
537
if
(rem > 11) {
538
return
potPrev + 1;
539
}
540
}
541
542
return
quot + 1;
543
}
544
545
546
/*******************************************************************
547
***
548
*** DEBUG-ONLY SECTION
549
*** NOT USED IN NORMAL CODE FLOW
550
***
551
*******************************************************************/
552
553
#ifdef USE_DEBUG_CODE
554
555
float
dV = REFERENCE_1V1 / 4096.0;
556
557
float
getVoltage(
void
) {
558
return
getOversampled() * dV;
559
}
560
561
float
getSensorResistance(
void
) {
562
// get soldering iron's probe resistance
563
float
v = getVoltage();
564
return
R1 / (V_REF / v - 1.0);
565
}
566
567
#endif
568
/*********************** END OF DEBUG-ONLY SECTION ****************/
569
570
unsigned
int
findDifference(unsigned
int
a, unsigned
int
b) {
571
// compare 'a' and 'b' and return the difference
572
573
if
(a == b)
return
0;
// return zerro in case a = b
574
if
(a > b)
return
a - b;
// self-exlplained code :)
575
return
b - a;
576
}
577
578
unsigned
char
displayMode = 0,
// data display selector
579
tickCounter = TICK_TOCK_COUNT,
// countdown stage counter
580
skipMarker = 0;
// skip counter
581
582
unsigned
int
sensorData,
// soldering iron's temperature probe data
583
targetTemperature,
// the temperature the soldering iron must be heated up to
584
wiperPosition,
// ADC value from pot's middle contact
585
wPosPrev = 0,
// temp wiperPosition var
586
displayValue,
// data to be send to display
587
currentTemperature;
// soldering iron temperature
588
589
#ifdef USE_DEBUG_CODE
590
float
voltage;
// the var for voltage measurement
591
#endif
592
593
#define DELAY(MS) cli(); softTimer = MS; sei(); while(softTimer != 0)
594
595
/*
596
**
597
** Main program loop
598
**
599
*/
600
601
void
loop
() {
602
603
if
(CHECK_EVENT(EVENT_TICK_TOCK_REQ)) {
// check the countdown flag is risen
604
tickCounter++;
// increase stage counter
605
CLEAR_EVENT(EVENT_TICK_TOCK_REQ);
// take down the flag
606
if
(tickCounter < 5) {
// check it is a first half of countdown
607
playTone(8000, 5);
// play short high tone sound
608
}
else
{
// increase loudness
609
if
(tickCounter != TICK_TOCK_COUNT) {
// check if it isn't last tick
610
displayMode = 3;
// set show tick display mode
611
OCR0B = DEFAULT_BRIGHTNESS;
// increase brightness
612
playTone(1000, 100);
// make load beep
613
}
else
{
// if it is last tick
614
playTone(1000, 800);
// play the final beep
615
}
616
}
617
}
618
619
// ======================= STANDBY mode routine ==========================================
620
if
(CHECK_EVENT(EVENT_STANDBY_MODE)) {
// check the standby flag is risen
621
TURN_HEATER_OFF;
// turn heater off
622
TURN_LED_OFF;
// turn LED off
623
displayBuffer[0] = ~SIGN_BLANK;
// blank display
624
displayBuffer[1] = ~SIGN_BLANK;
625
displayBuffer[2] = ~SIGN_BLANK;
626
627
if
(CHECK_EVENT(EVENT_BUTTON_LONG)) {
628
playTone(1000, 800);
// play long beep
629
setSoftTimer(800);
// set soft timer to wait for signaling
630
}
631
632
tickCounter = 0;
// reset tickCounter
633
634
// wait for the button is released and time is out
635
while
((PINB & (1<<PINB0)) || getSoftTimer());
636
TCCR0B &= ~0b111;
// No clock source (Timer/Counter stopped)
637
cbi(TCCR1A, COM1B0);
// disable speaker output
638
toneDuration = 0;
// reset tone duration counter
639
PCMSK0 |= bit (PCINT0);
// set pin 8 as interupt source
640
PCIFR |= bit (PCIF0);
// clear any outstanding interrupts
641
PCICR |= bit (PCIE0);
// enable pin change interrupts for D8 to D13
642
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
// set powerdown sleep mode
643
sleep_enable();
// allow enter into sleep mode
644
645
unsigned
long
int
t = 0;
// local keypress duration counter
646
647
while
(1) {
// go to endless standby loop
648
if
((PINB & (1<<PINB0)) == 0) {
// check for button pressed
649
if
(++t == 0x00300000) {
// count keyperss duration and check it is long enough
650
PCMSK0 &= ~(1<<PCINT0);
// disable pin 8 interrupt
651
PCICR &= ~(1<<PCIE0);
// disable pin change interrupts for D8 to D13
652
break
;
// leave loop
653
}
654
}
else
{
// if no kepress detected
655
t = 0;
// reset keypress duration counter
656
sleep_cpu ();
// go Sleep and wait for the interrupt
657
}
658
}
659
TCCR0B |= (1<<CS01) | (1<<CS00);
// enable TIMER0 clocking
660
resetTimeout(LOW_TEMP_MARGIN);
// reset timeout counters
661
displayMode = 0;
// set display mode
662
targetTemperature = 0;
// reset target temperature
663
playTone(1000, 600);
// play greeting
664
#ifndef CALIBRATION_BUILD
665
#ifdef PREHEAT_ENABLE
666
DELAY(600)
667
preHeat();
668
playTone(6000, 20);
// play greeting
669
DELAY(150);
670
playTone(6000, 20);
// play greeting
671
#endif
672
#endif
673
674
CLEAR_EVENT(EVENT_BUTTON_LONG | EVENT_BUTTON_PRESSED);
675
}
676
// ======================= End of STANDBY mode routine =======================================
677
678
sensorData = getOversampled();
// get data from termal probe
679
680
if
(readPotReq == 1) {
// every 0.1 second
681
readPotReq = 0;
682
// reflect potentiometer's wiper position to temperature scale
683
ADMUX=(1<<REFS1) | (1<<REFS0) | 6;
// set pot's ADC channel
684
685
//wiperPosition = map(getOversampled(), 0, 4095, LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN);
686
wiperPosition = map(filterPot(getOversampled()) + LOW_TEMP_DEGREE / 100,
687
LOW_TEMP_DEGREE / 100, HIGH_TEMP_DEGREE / 100,
688
LOW_TEMP_MARGIN, HIGH_TEMP_MARGIN);
689
ADMUX=(1<<REFS1) | (1<<REFS0) | 7;
// restore thermal probe ADC channel
690
// check if pot's data is different enough from target temperature
691
if
(findDifference(targetTemperature, wiperPosition) > 7) {
692
OCR0B = DEFAULT_BRIGHTNESS;
// increase display brightness
693
displayMode = 0;
// set display mode
694
tickCounter = 0;
// reset countdown var
695
targetTemperature = wiperPosition;
// set new target temperature
696
setSoftTimer(1500);
// set period for displaying target temperature instead of
697
// measured one
698
CLEAR_EVENT(EVENT_LOW_POWER_MODE);
// leave low power mode
699
SET_EVENT(EVENT_TEMP_CHANGE_REQ);
// set temperature changing flag
700
}
701
}
702
703
if
(CHECK_EVENT(EVENT_BUTTON_PRESSED)) {
// check keypress flag is set
704
displayMode = 0;
// force display's main mode
705
CLEAR_EVENT(EVENT_BUTTON_PRESSED);
// resed keypress flag
706
OCR0B = DEFAULT_BRIGHTNESS;
// set display brighter
707
tickCounter = 0;
// reset tickCounter
708
resetTimeout(sensorData);
// re-calc timeout period
709
playTone(8000, 20);
// make short audible 'click'
710
}
711
712
// represent current soldering iron temperature using the calibration data
713
currentTemperature = map(sensorData,
714
ADC_CALIBRATION_DATA_LOW,
715
ADC_CALIBRATION_DATA_HIGH,
716
CALIBRATION_TEMP_LOW,
717
CALIBRATION_TEMP_HIGH) / 10;
718
719
if
(displayUpdateReq == 1) {
// every 0.1 second
720
displayUpdateReq = 0;
// reset flag
721
switch
(displayMode) {
722
case
0:
723
if
(!CHECK_EVENT(EVENT_TEMP_CHANGE_REQ)) {
// if no changing temperature flag is set
724
if
(findDifference(sensorData, targetTemperature) < 8) {
// check the temperature is in the allowed boundaries
725
displayValue = map(targetTemperature,
726
LOW_TEMP_MARGIN,
727
HIGH_TEMP_MARGIN,
728
LOW_TEMP_DEGREE / 10,
729
HIGH_TEMP_DEGREE / 10);
// use target temperature for displaying
730
}
else
{
// in the case of temperature drift is high enough
731
if
(CHECK_EVENT(EVENT_LOW_POWER_MODE)) {
// if low power mode is active
732
if
(findDifference(sensorData, LOW_TEMP_MARGIN) < 10 ) {
733
displayValue = LOW_TEMP_DEGREE / 10;
// display fixed low margin degree value
734
}
else
{
735
displayValue = currentTemperature;
// show real measured temperature
736
}
737
}
else
{
// in main mode
738
#ifndef CALIBRATION_BUILD
739
displayValue = currentTemperature;
// show real measured temperature
740
#else
741
displayValue = sensorData - 1000;
742
#endif
743
/*
744
displayValue = map(targetTemperature,
745
LOW_TEMP_MARGIN,
746
HIGH_TEMP_MARGIN,
747
LOW_TEMP_DEGREE / 10,
748
HIGH_TEMP_DEGREE / 10); // use target temperature for displaying
749
*/
750
}
751
}
752
}
else
{
// in heating up or cooling down stage
753
if
(!getSoftTimer()) {
// if target temperature is not changed recently
754
//displayValue = currentTemperature; // display real measured temperature
755
#ifndef CALIBRATION_BUILD
756
displayValue = currentTemperature;
// show real measured temperature
757
#else
758
displayValue = sensorData - 1000;
759
#endif
760
}
else
{
// target temperature just changed
761
displayValue = map(wiperPosition,
762
LOW_TEMP_MARGIN,
763
HIGH_TEMP_MARGIN,
764
LOW_TEMP_DEGREE / 10,
765
HIGH_TEMP_DEGREE / 10);
// show target temperature
766
}
767
}
768
break
;
769
/******************************************************************
770
***
771
***
772
*** DEBUG ONLY SECTION
773
***
774
***
775
*******************************************************************/
776
#ifdef USE_DEBUG_CODE
777
case
1:
778
displayValue = (getVoltage(3) - 1.0) * 10000;
779
break
;
780
case
2:
781
displayValue = (getSensorResistance()) * 10;
782
break
;
783
#endif
784
/********************* END OF DEBUG CODE **************************/
785
case
3:
786
displayValue = TICK_TOCK_COUNT - tickCounter;
// show countdown values
787
break
;
788
default
:
789
break
;
790
}
791
792
fillDisplayBuffer(displayValue, ~SIGN_BLANK);
// send data to the display
793
}
794
if
(CHECK_EVENT(EVENT_LOW_POWER_MODE)) {
// if low power mode active
795
if
(CHECK_EVENT(EVENT_ATTN_REQ)) {
// check if it is first occurrence
796
CLEAR_EVENT(EVENT_ATTN_REQ);
// down flag
797
tickCounter = 0;
// reset tick counter
798
OCR0B = MIN_BRIGHTNESS;
// lower display brightness
799
displayMode = 0;
// set main display mode
800
}
801
wiperPosition = LOW_TEMP_MARGIN;
// force targed temperature to 185C degree
802
}
803
804
/*****************************************************************
805
**
806
** HEATER CONTROL SECTION
807
**
808
*****************************************************************/
809
810
if
(sensorData < wiperPosition) {
// check if current temperature is lower than target one
811
TURN_HEATER_ON;
// force heating up
812
TURN_LED_ON;
// toggle LED on
813
}
else
{
// the current temperature is equal to target one or above
814
TURN_HEATER_OFF;
// disable heating up
815
TURN_LED_OFF;
// toggle LED off
816
}
817
/*****************************************************************/
818
819
820
// check if it is temperature changing mode
821
if
(CHECK_EVENT(EVENT_TEMP_CHANGE_REQ) != 0) {
822
// check if temperature target has reached
823
if
(findDifference(sensorData, wiperPosition) < 4) {
824
CLEAR_EVENT(EVENT_TEMP_CHANGE_REQ);
825
resetTimeout(sensorData);
// recalculate timeout
826
playTone(4000, 50);
// play 'temperature matched' sound mark
827
}
828
}
829
830
}
831
832
#ifdef PREHEAT_ENABLE
833
834
void
preHeat(
void
) {
835
unsigned
int
sData;
836
// check if current temperatue low enough
837
if
(getOversampled() < LOW_TEMP_MARGIN) {
838
// save current TIM1 settings
839
unsigned
int
sTCCR1A = TCCR1A;
840
unsigned
int
sTCCR1B = TCCR1B;
841
// unsigned int sOCR1AL = OCR1AL;
842
// unsigned int sOCR1AH = OCR1AH;
843
844
// reinit timer in PWM mode
845
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (1<<WGM11) | (0<<WGM10);
846
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10);
847
848
sbi(ADMUX, 1);
849
850
for
(
int
i = 20; i <= 100; i++) {
851
cbi(TCCR1A, COM1A1);
// disable PWM output
852
DELAY(2);
// wait till the probe becomes stable
853
sData = getOversampled();
854
855
OCR1A = 5 * i;
// set new duty cycle ratio (i is equal duty cycle)
856
sbi(TCCR1A, COM1A1);
// enable PWM output
857
858
if
(sData > LOW_TEMP_MARGIN)
break
;
// go away if preheating target is reached
859
fillDisplayBuffer(map(sData,
860
ADC_CALIBRATION_DATA_LOW,
861
ADC_CALIBRATION_DATA_HIGH,
862
CALIBRATION_TEMP_LOW,
863
CALIBRATION_TEMP_HIGH) / 10,
864
~SIGN_BLANK);
// display current temperature
865
for
(
int
k = 0; k < 10; k++) {
866
// show preheating blink
867
TURN_LED_ON;
868
DELAY(3);
869
TURN_LED_OFF;
870
DELAY(7);
871
}
872
}
873
TURN_LED_OFF;
874
// restore timer settings
875
OCR1A = 0;
876
TCCR1A = sTCCR1A;
877
TCCR1B = sTCCR1B;
878
// OCR1AL = sOCR1AL;
879
// OCR1AH = sOCR1AH;
880
881
TURN_HEATER_OFF;
882
}
883
}
884
#endif
Спасибо, a5021. Все очень доходчиво. Попробовал откалибровать с обычным термометром. На температурах до 300 градусов присутствует погрешность. Ближе к 400 градусов погрешности почти нет. Видимо из-за того, что калибровал обычным термометром. Попробую найти лабораторный термометр с десятыми градусов и еще раз откалибровать.
Давно не заходил на форум. А тут уже и новая прошивка.
Прошил, проверил. Стабильнее показывать стало. Раньше в пределах градуса-трех менялось, сейчас стоит как вкопанное.
Спасибо a5021.
По исполнению, запихнул в корпус от внешнего харда, на 2.5" работает уже несколько месяцев. Безумно выручает.
Питание от БП ноубука, 19В 4.5A
Добрый день. Собираю такую станцию и есть просьба - кто-нибуть развел печатную плату под SMD? Не поделитесь?
Я задумывался над тем, чтобы развести еще и smd-версию, но остановило опасение, что она не будет востребована. Трассировка хоть и интересный, но довольно длительный процесс, а времени, как обычно, ни на что не хватает. В принципе, если общественность проявит более активный интерес, может и сподоблюсь. Но тут важным становится вопрос, в каких размерах это все делать. Для себя я делаю все максимально мелко и тонко, но это требует определенной квалификации при изготовлении платы, что может вызвать трудности у начинающих. Еще вопрос конструктивов и размерносей компонентов не совсем однозначен. Если я разведу под свои компоненты, то это наверняка приведет к трудностям с поиском того же самого при повторении кем-то другим.
Интересно было бы сделать "пресеты" с разными калибровками под разные жала. Ведь явно у толстого и тонкого жала температура на кончике будет разной.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
Боюсь это будет весьма проблематично, прежде всего из-за сложностей с измерением этой самой температуры на кончике. Усилий это может потребовать значительно больше, чем полученных таким образом выгод.
А почему сложно? термопарой мультиметра например отлично меряется. Соответственно у каждого жала при одной и тойже температуре разные калибровочные значения. Хранить можно прям в скетче массивом. Выбирать (например) удержанием кнопки + потенциомерт вправо - влево
Термопарой, подключенной к мультиметру, получится измерить только "стреднюю температуру по больнице". Даже не уверен, что она покажет разную температуру для разных жал. Для калибровки "взрослых" паяльных станций в комплекте к ним идут специальные устройства для измерения темпертуры именно жала и существуют требования по организации таких измерений. Кончик жала может изменять температуру на десятки градусов только от одного движения воздуха в помещении. Как я говорил еще в самом первом сообщении, приходится иметь дело лишь с приблизительными температурами в зоне пайке и с этим, по большому счету, ничего не поделать.
Ну тогда ладно :)
Большое спасибо a5021 за данный проект, сделал, запустил (не без проблем, но это из-за своих ошибок) - доволен как слон. НО! В языке программирования я очень начинающий и не смог понять как "раскоментировать" и соответственно не могу откалибровать паяльник. Не мог бы кто нибуть выложить скетч с раскомментированным определением CALIBRATION_BUILD. Буду премного благодарен!
Еще пара вопросов: в каких случаях издается звуковой сигнал? При питании данной схемы от БП компьютера можно обойтись без кренки и питать от +5 вольт БП?
Раскомментировать -- значит убрать знак(и) комментария. В данном случае речь идет о строке № 26. Уберите два слеша ("//") в начале строки и директива будет раскомментирована. Чтобы закомментировать обратно, эти два слеша надо вернуть. Вот и вся премудрость.
Без кренки обойтись можно, но подаваемые +5в от БП не должны иметь больших пульсаций. Шум по линии +5в может плохо влиять на точность измерений температуры и, как следствие, на стабильность показаний на индикаторе.
Подать +5в напрямую от БП можно, если не запаивать эту самую кренку, а припаять провод прямо вместо ее вывода №3. Весьма не лишним в этом случае будет увеличить емкость конденсатора С5 из расчета, чем больше, тем лучше.
a5021, у меня к вам вопрос по схеме. Зачем нужен диод D2 в цепи динамика? И нужен ли он там вообще?
Диод там был поставлен исходя из двух соображений: а) шунтировать диодом индуктивную нагрузка (динамик, в данном случае) является хорошим тоном, чтобы потом не разбираться с непонятными переходными процессами; б) динамик может оказаться пьезоэлектрическим (иногда их по виду отличить сложно), который при механическом воздействии на него (удар, падение) может сам являться генератором значительных напряжений, достаточных, чтобы спалить транзистор, нагрузкой для которого он является.
Если по каким-то соображениям вы не хотите устанавливать диод, можно не устанавливать. Непосредственно на функционал это не влияет. Диод выполняет защитные функции и только лишь в некоторых случаях.
Благодарю за развёрнутый ответ.
Добрый день. Сделал каллибровку по вашей методике, получил значения 36,2 (градуса) - 993 (на дисплее), и 85 - 213. В какие строки кода внести это значения?
Значения нужно занести в строки 44 - 47. Предполагаю, что в вашем случае они будут выглядеть так:
1
#define CALIBRATION_TEMP_LOW ((unsigned int) 3650)
2
#define CALIBRATION_TEMP_HIGH ((unsigned int) 8500)
3
#define ADC_CALIBRATION_DATA_LOW ((unsigned int) 1993)
4
#define ADC_CALIBRATION_DATA_HIGH ((unsigned int) 2213)
Огромнейшее спасибо!
Расскажите потом, что получилось, если не сложно.
Помогите " коллегам" ;)
http://we.easyelectronics.ru/Tools/lukey-702-pechalka-.html
Все прошилось, по личным ощущениям температура жала стало грется сильнее, но точнее сказать пока не могу - завтра возьму у знакомого дистанционный термометр - измерю точнее. Есть такая" шероховатость" -при крайнем положении переменика температура на индикаторе скачком снижается к минимальной. Переменик 12 ком. Это можно исправить?
И неплохо бы увеличить время перехода паяльника в "сон", у меня оно около 5 минут. Попутно вопрос - переход в сон происходит когда регулировку не трогаем или при отсутствии резких изменений температуры жала? Типа не паяем - температура почти постоянная, изменения в пару градусов.
Извиняюсь - переменик 1 (один) кОм!!!
С переменником вы сурово поступили. При такой замене вы отрезали 9/10 диапазона регулирования в верхней части. Чтобы использовать переменник величиной 1ком, резисторы R20 и R21 должны быть 270ом и 1ком соответственно.
Переход в сон зависит от температуры жала и составляет 15 секунд при крайне правом положении переменника и один час при крайне левом. Промежуточные положения "размазаны" пропорционально. Крайние значиния для диапазона заданы определениями в тексте скетча:
1
// min timeout in seconds
2
#define MIN_TIMEOUT_SEC 15
3
// max timeout in seconds
4
#define MAX_TIMEOUT_SEC (60 * 60)
Условием для перехода в "сон" является отсутствие воздействия на органы управления (переменник, кнопка) или резких изменений температуры. Последнее не является режимом детектирования пайки. Паялка уйдет в сон не зависимо от того, происходит пайка или нет.
Приношу свои извинения, неправильно посчитал значение переменика, на нем обозначение В103 - это все таки 10кОм. Но температура при приближении к крайнему максимальному положению падает до минимальной. Напряжение на среднем выводе переменика меняется от 0 вольт до 0.98.
Для идеального случая оно должно меняться с нуля до 1.1 вольта (величина внутреннего опорного напряжения атмеги), но так как идеального ничего не существует, а существует разброс в величинах сопротивлений R20, R21 и самого переменника, то 0.98 -- это, пусть и не лучший, но вполне допустимый результат. Чуть снизится верхний предел регулировки. А вот почему падает температура на правом краю, тут пока загадка. Покопаюсь на досуге в исходниках. Есть нехорошее подозрение, что это может оказаться переполнением какой-то переменной.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала? Т.е. на индикаторе у меня 439 градусов (больше не устанавливается - сбрасывается) а по ощущениям намного меньше. Измерить температуру времено не могу - приятель только на днях термометр принесет.
Извините что не по теме, но хочу задать один вопрос в сило своей не грамотности в области электроники.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Просто на основе похожей схемы собрал диммер к ESP8266. В режиме реле работает отлично, а вот диммировать лампу накаливания не хочет (хотя замерял сопротивление через BTA16 изменяется от 5кОм и выше). Или MOC3061 с его детектором перехода через 0 тут ни при чем и я просто сделал что-то не так?
По поводу БП - можно взять такой http://www.aliexpress.com/item/New-Arrival-AC-Universal-100V-240V-for-DC-24V-4A-96W-Power-Supply-Charger-Converter-Adapter/32281525290.html
Тест на нем проводил - последовательно 2 лампы 12В 100Вт. Зажглись, ток выдал в районе 3,96А, в защиту не ушел, но хорошо гудел. Для паяльника должен подойти (для чего я собственно и заказывал).
Второй вопрос. Ардуины на борту имеют стабилизатор, на моей Мини Про LG50 - 500ма, до 12В. Вместе например с КРЕН 9В можно распределить тепло и уменьшить количество радиаторов. Токи вроде небольшие.
БП симпатичный и по деньгам вполне неплохо. Если он держит заявленные характеристики, то это как раз то, что нужно. Даже если будет срабатывать защита при холодном включении, теперь есть ШИМ-разогрев, который купирует эту проблему.
Насчет набортного регулятора ардуины -- использовать его по предложенной вами схеме проблематично. Помимо самого ардуины есть еще остальная схема, которая так же расчитана на питание от 5 вольт. Если туда подать 9 вольт, то это напряжение через светодиоды индикатора окажется на ногах ардуины и даже если не сожжет сразу, то начнет "поднимать" его, т.к. выходы внутри атмеги через защитные диоды соеденины с шиной +5v.
Насчет разогрева линейного регулятора (7805) хочу заметить, что несмотря на то, что греется он весьма ощутимо, температура прибора не выходит за рамки допустимых эксплуатационных пределов. Монтаж с использованием платы в качестве радиатора в данном случае допускает и большую тепловую нагрузку. Если не смотря на это кому-то хочется, чтобы вообще ничего не грелось, то нет никаих проблем в дырки от 7805 запаять провода с внешнего импульсного преобразователя. Так популярная понижайка на lm2596
вписывается сюда без каких бы то нибыло вопросов.
Я что-то не догоняю или использование ШИМ в регулировке температуры фена по схеме Ильи c MOC3061 не возможно?
Он включается только при переходе волны через ноль и всякий шим в другое время ему по барабану.
А как ФАКТИЧЕСКИ, не отображаемую на индикаторе, увеличить температуру жала?
Если честно, не понял вопроса.
По стабилизатору на борту я имел в виду, что даем 9В (можно даже 12В) на порт Vin или RAW (в зависимости от модели Ардуино), а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Но со step-down конвертером конечно же будет лучше. Только его еще заказать и дождаться нужно.
Мне интересный вопрос - не думали над защитой от зависания Ардуины при открытом полевике? Например, глобальный сброс при достижении критического сопротивления термистора.
Кстати, вспомнил еще один вопрос - зачем использовать опорный источник напряжения, если можно измерить фактическое напряжение приходящих 5В?
а с VCC отй же Ардуины получаем те же стабилизированные 5В до 500ма. Не знаю, как по току дисплей, но ток делителя напряжения примерно 2ма, регулятора еще меньше.
Ток через дисплей в пике составляет 7сегментов * 20ма = 140ма. Сам ардуино кушает 30-40ма. Добавим потребление прочих элементов схемы и в сумме получится где-то 200ма. Ток кажется вполне приемлемым. Но это только до того, как начнем считать мощность выделяемую в тепло на линейном стабилизаторе ардуины. А она будет выглядеть так: P= (Vin - Vout) * Iout. Для наших цифр это получится (12-5) * 0.2 = 1.4W, что является трижды запредельной величиной для того типа корпуса, в котором регулятор распаян на ардуине. Регулятору в таких условиях скорее всего захочется выпаяться (с этим у него проблем не возникнет) и убежать. :)
По хорошему, надо дописать использование аппаратного ватчдога ардуины в скетче. Только это будет не защита от неконтролируемого нагрева паяльника, а просто от зависания ардуины. Но тут есть подводные грабли, т.к. разработчики ардуины сделали все возможное, чтобы сделать использование ватчдога максимально сложным. Чтобы быстро выпустить рабочую версию скетча, от многих задумок, которые там должны, по-хорошему, присуствовать, мне пришлось, как минимум на время, отказаться.
Использование аппаратной защиты тянет за собой усложнение схемы и вызывает лишние сложности с повторением, особенно начинающими. По своему опыту эксплуатации различных самодельных паялок я знаю, что неконтролируемый разогрев паяльника ситуация довольно редкая. У меня это случалось только во время разработки и исключительно из-за собственной невнимательности. Риск того, что правильно собранная схема при подаче на нее рекомендованных напряжений самопроизвольно выйдет из строя не очень велик, т.ч. взвесив плюсы и минусы, от реализации аппаратной защиты я решил отказаться.
Если кому-то захочется повышенной надежности, то можно добавить в схему компаратор с порогом 1.2в и подключить его параллельно входу АЦП ардуины. На выходе компаратора будет формироваться аварийный сигнал в случае, если нагрев паяльника превысил допустимый диапазон.
В этом случае мы поимеем сразу несколько минусов по сравнению с нынешней схемой. Имеются достаточно значимые основания, чтобы так не делать, но чтобы еще больше не загромождать объяснение, просто встаньте осциллографом на шину +5в и посмотрите, что на ней твориться во время работы схемы. Если это употребить в качестве опорного напряжения, то о точности удержания температуры лучше 10-20 градусов можно даже и не заикаться.
Попробую объяснит - это про температуру. У меня по индикатору температура не устанавливается выше 439 градусов. По моим ощущениям (возможно ошибочным) это не соответствует действительности - температура на жале паяльника ниже. Калибровку по вашей методике делал - не сильно помогло. Можно ли поправить код таким образом что бы поднять температуру? Т.е. по индикатору предположим 300, а на жале - 350.
По переходу паяльника в "сон". Как то странно это происходит. На максимальной температуре паяльник лежит на подставке несколько десятка два минут - в "сон" не переключается, начал пользоваться (паять) плату - через полминуты запищал сигнал начала перехода в "сон" Может лучше режим "сон" назначить на кнопку? Нажал - паяльник уснул, через несколько минут (предположим минут 10-15) нагрев вообще выключился.
Мой совет, сначала все-таки установите сколь нибудь более достоверно, что ошибка индикации температуры имеет место. Я бы вот на глаз вряд ли смог различать температуры пяльника 440 и 380 градусов, скажем. И что вы, если не секрет, паяете при такой температуре жала? Я, например, уже не помню, когда последний раз что-то паял с температурой больше 320 градусов.
Если вам непременно хочется, чтобы паяльник грел сильнее, уменьшите значение
ADC_CALIBRATION_DATA_HIGH
Режим сна задуман, как средство против забывчивости. Оставлять паяльник включенным на долгое время все-таки не лучшая идея. Если в сон уходить только по кнопке, то велик шанс получить ситуацию, когда и на кнопку забудешь нажать, а паяльник будет сутки барабанить, дожигая жало.
Достаточно ли будет данного транзистора для управления питанием паяльника?
Достаточно ли будет данного транзистора для управления питанием паяльника?
не могу прочитать что на нем написано.
CEP603AL
CEP603AL
напряжение исток сток 30В. желательно с запасом ставить. Но работать будет. как долго не могу сказать. по остальным параметрам вопросов нет.
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое "заземляющий контур" ?
Подскажите правильно ли будет подключить корпус паяльника на общий минус и потом уже через конденсатор к общему минусу подключить заземляющий контур?
Что такое заземление?
это защита от поражения электрическим током человека.
Что подключается к заземлению?
Все нетоковедущие части электроустановки, которые могут оказаться под напряжением.
Из этого следует, что к заземлению нужно подключать все металлические части корпуса, которые могут оказаться под напряжением. конденсатор на землю, это не заземление.