Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Станция для самостоятельной паяльной обработки SMD

Компоненты и расходные материалы

SparkFun Arduino Pro Mini 328 - 5 В / 16 МГц
× 1
Стандартный ЖК-экран Adafruit - 16x2, белый на синем
× 1
модуль lcd i2c
× 1
Поворотный энкодер с кнопкой
× 1
Рукоятка термофена
× 1
Держатель рукоятки термофена + сопло
× 1
BTA12-600B
× 1
IRFZ44
× 1
MCP602
× 1
MOC3052
× 1
4N25
× 1
Мостовой выпрямитель
× 1
Зуммер
× 1
быстрый выпрямительный диод FR107
× 1
Конденсатор 0,01 мкФ, 400 В
× 1
Конденсатор 100 нФ
× 6
Резистор в сквозное отверстие, 39 Ом
× 1
Резистор в сквозное отверстие, 33 кОм
× 2
Резистор 330 Ом
× 1
Резистор 220 Ом
× 1
Резистор 1 кОм
× 3
Резистор в сквозное отверстие, 470 Ом
× 1
многооборотный потенциометр 500 кОм
× 1
Резистор 10 кОм
× 3

Необходимые инструменты и машины

Паяльник (универсальный)

Приложения и онлайн-сервисы

IDE Arduino
Autodesk Eagle

Об этом проекте

Введение:паяльная станция DIY SMD

Из этого туториала Вы узнаете, как создать контроллер для термофена, используя Arduino и другие распространенные компоненты. В этом проекте алгоритм PID используется для расчета необходимой мощности и управляется изолированным драйвером симистора.

В этом проекте используется ручка, совместимая с 858D. Он оснащен термопарой типа К, нагревателем на 700 Вт, 230 В переменного тока и вентилятором на 24 В постоянного тока.

Этот контроллер эффективен и надежен по сравнению с коммерческим, и его легко собрать.

Шаг 1. Подключение

Полная схема показана на картинке ниже.


Электропроводка для ЖК-модуля I2C:

Модуль I2C <--------------> Arduino Pro Mini

GND <-----------------------> GND <---------> GND

VCC <------------------------> VCC <---------> 5 В

ПДД <-------------------------------------------> A4

SCL <-------------------------------------------> A5.

Подключение модуля поворотного энкодера:

Кодировщик <----------------------> Arduino

GND <---------------------------> GND

+ <--------------------------------> NC (не подключен, код использует встроенное подтягивание ввода Arduino)

ПО <-----------------------------> D5

DT <------------------------------> D3

CLK <----------------------------> D4.

Подключение ручки: (7-жильный)

3-контактный разъем - (зеленый, черный, красный)

Красный провод <-----------------------> Термопара +

Зеленый провод <--------------------> Геркон

Черный провод <---------------------> Общая масса.

2-х контактный разъем - (синий, желтый)

Синий провод <--------------------------> Вентилятор +0

Желтый провод <------------------------> Вентилятор - (или GND)

2 Большой контактный разъем - (белый, коричневый)

Белый провод <-----------------------> Нагреватель

Коричневый провод <----------------------> Нагреватель (без полярности)

ПРИМЕЧАНИЕ.

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

Шаг 2:принципиальная схема

Схема состоит в основном из 3-х частей.

Интерфейсная часть:

Он состоит из ЖК-дисплея 1602 с модулем I2C и поворотного энкодера с кнопкой. На дисплее отображается заданная температура, текущая температура, скорость вращения вентилятора, подаваемая мощность и текущее состояние ручки. Кодировщик используется для различных входов и для навигации по параметрам и элементам управления.

Сенсорная часть:

Он состоит из термопары типа К для измерения температуры и геркона для определения положения ручки. Напряжение термопары усиливается операционным усилителем до уровня, измеряемого Arduino. Коэффициент усиления операционного усилителя регулируется регулятором 200K.

Контроллер:

В этой схеме в основном 2 контроллера. Один из них - простой ШИМ-контроллер скорости вентилятора с полевым МОП-транзистором. Другой - изолированный контроллер для нагревателя. Он состоит из TRIAC, управляемого DIAC с оптической связью, и осуществляется путем управления количеством волновых циклов, которые поступают в нагреватель. Оптопара 4N25 помогает поддерживать синхронизацию с формой волны переменного тока.

Шаг 3:печатная плата

Схема этого проекта немного сложна, поэтому я рекомендую вам использовать печатную плату, а не точечную печатную плату. Если вы хотите сделать свою собственную печатную плату, я прикрепил файлы орла в конце проекта. Но если вы хотите, чтобы их выполняла компания-производитель печатных плат, вы можете заказать это в JLCPCB

. Вы можете просмотреть проект Easy EDA по этой ссылке:https://easyeda.com/ManojBR/harws1-1

Шаг 4. Код и библиотеки

Программа - самая важная часть проекта, и большое спасибо за sfrwmaker написание программы. Программа использует алгоритм PID для контроля мощности для поддержания заданной температуры. Он работает, контролируя количество волновых циклов, доставляемых на рукоятку в секунду.

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

Пистолет горячего воздуха начинает нагреваться, как только его поднимают из держателя, и показывает Готово и издает короткий звуковой сигнал, когда достигает заданной температуры. Он выключит нагрев, как только он будет возвращен в держатель. Но вентилятор будет продолжать работать, пока не достигнет безопасной температуры. Когда температура упадет ниже 50 C, он издаст короткий звуковой сигнал и отобразит COLD.

Когда термофен выключен, контроллер перейдет в режим настройки . если кодировщик нажато .

В режиме настройки доступны параметры калибровки, настройки, сохранения и отмены, а также сброса конфигурации.

Примечание. Если вы используете печатную плату от easyEDA тогда вы должны изменить номер контакта язычкового переключателя на номер контакта. 8 и штифт зуммера к контакту 6

вам необходимо установить библиотеку Commoncontrols-master и библиотеку time-master для правильной работы кода.

Внимание! Не подключайте контроллер к розетке при прошивке. Неизолированный источник питания вентилятора может повредить ваш ноутбук.

скачать исходный код скетча со страницы проекта.

Шаг 5. Настройка

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

Сначала перейдите в режим настройки и выберите опцию Tune. В режиме настройки внутренняя температура (0-1023) отображается на экране. Поверните энкодер, чтобы вручную выбрать мощность, подаваемую на термофен. Нагрейте пистолет до 400 градусов. Когда температура и дисперсия станут низкими, контроллер подаст звуковой сигнал. Затем настройте триммер, чтобы установить внутреннюю температуру около 900 (во внутренних блоках). Длительное нажатие на энкодер возвращает в меню

Затем перейдите в режим настройки и выберите опцию «Калибровка». Выберите точку калибровки:200, 300 или 400 градусов, нажмите энкодер. Горячий пистолет достигнет желаемой температуры и издаст звуковой сигнал. Вращая энкодер, введите реальную температуру. Затем выберите другую контрольную точку и повторите этот процесс для всех точек калибровки.

После этого длительного нажатия перейдите на главный экран, а затем снова перейдите в режим настройки и выберите «Сохранить».

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

Шаг 6. Видео!

Посмотрите, как работает контроллер на видео.

Спасибо sfrwmaker за написание кода.

Спасибо LCSC за поддержку. LCSC Electronics - один из самых быстрорастущих поставщиков электронных компонентов в Китае. С момента своего основания в 2011 году LCSC стремится предлагать множество оригинальных товаров и товаров на складе. Стремясь обеспечить весь мир более качественными запчастями из Азии. Для получения более подробной информации посетите:https://lcsc.com/

Если вам нужно сделать свою собственную печатную плату дома, ознакомьтесь с этим руководством:https://www.instructables.com/id/PCB-Making-1/

Спасибо.

Код

  • Прошивка 1.4
Прошивка 1.4 C / C ++
Активная / пассивная поддержка зуммера. Пожалуйста, измените параметр BUZZER_ACTIVE
Больше нет увеличенного углового энкодера. Значение изменяется на 1.
 / * * Контроллер термофена на базе микросхемы atmega328 * Версия 1.4 * Выпущена 5 декабря 2020 г. * / # include  #include  #include  #include  #include  #include  #include  const uint16_t temp_minC =100; // Минимальная температура, которую контроллер может точно проверить const uint16_t temp_maxC =500; // Максимально возможное значение температуры uint16_t temp_ambC =25; // Средняя температура окружающей средыconst uint16_t temp_tip [3] ={200, 300, 400}; // Контрольные точки температуры для калибровкиconst uint16_t min_working_fan =100; // Минимально возможная скорость вращения вентилятора uint8_t AC_SYNC_PIN =2; // Вывод синхронизации 220 В. Не изменять! Const uint8_t HOT_GUN_PIN =7; // Управление нагревателем горячего пистолета pinconst uint8_t FAN_GUN_PIN =9; // Штифт управления вентилятором горячего пистолета. Не менять! const uint8_t TEMP_GUN_PIN =A0; // Проверка температуры горячего пистолета pinconst uint8_t R_MAIN_PIN =3; // Главный вывод поворотного энкодера. Не изменять! Const uint8_t R_SECD_PIN =4; // Вторичный контакт датчика вращения uint8_t R_BUTN_PIN =5; // Кнопка поворотного энкодера pinconst uint8_t REED_SW_PIN =8; // константа язычкового переключателя uint8_t BUZZER_PIN =6; // константа зуммера bool BUZZER_ACTIVE =true; // Активный зуммер издает звуковой сигнал при подаче на него + 5В // ------------------------------------- ----- Данные конфигурации ------------------------------------------- ----- / * Конфигурационная запись в EEPROM имеет следующий формат:* идентификатор uint32_t каждый раз, увеличивающийся на 1 * данные конфигурации struct cfg, 8 байт * байтовый CRC контрольная сумма * / struct cfg {uint32_t калибровка; // Упакованные данные калибровки по трем температурным точкам uint16_t temp; // Заданная температура утюга во внутренних блоках uint8_t fan; // Предустановленная скорость вентилятора 0 - 255 uint8_t off_timeout; // Тайм-аут автоматического отключения}; class CONFIG {public:CONFIG () {can_write =false; buffRecords =0; rAddr =wAddr =0; eLength =0; nextRecID =0; uint8_t rs =sizeof (struct cfg) + 5; // Общий размер записи конфигурации // Выберите подходящий размер записи; Размер записи должен быть степенью 2, то есть 8, 16, 32, 64, ... байтов для (record_size =8; record_size  recID) {minRecID =recID; minRecAddr =адрес; } если (maxRecID  eLength) wAddr =0; } еще {wAddr =minRecAddr; } can_write =true;} void CONFIG ::getConfig (struct cfg &Cfg) {memcpy (&Cfg, &Config, sizeof (struct cfg));} void CONFIG ::updateConfig (struct cfg &Cfg) {memcpy (&Config, &Cfg, sizeof ( struct cfg));} bool CONFIG ::saveConfig (struct cfg &Cfg) {updateConfig (Cfg); return save (); // Сохранение новых данных в EEPROM} bool CONFIG ::save (void) {if (! Can_write) return can_write; если (nextRecID ==0) nextRecID =1; uint16_t startWrite =wAddr; uint32_t nxt =nextRecID; uint8_t summ =0; for (uint8_t i =0; i <4; ++ i) {EEPROM.write (startWrite ++, nxt &0xff); сумма <<=2; сумма + =nxt; nxt>> =8; } uint8_t * p =(байт *) &Config; for (uint8_t i =0; i  EEPROM.length ()) wAddr =0; nextRecID ++; // Готовимся к записи следующей записи return true;} bool CONFIG ::load (void) {bool is_valid =readRecord (rAddr, nextRecID); nextRecID ++; return is_valid;} bool CONFIG ::readRecord (адрес uint16_t, uint32_t &recID) {uint8_t Buff [размер_записи]; for (uint8_t i =0; i <размер_записи; ++ i) Buff [i] =EEPROM.read (addr + i); uint8_t summ =0; for (байт i =0; i  =0; --i) {ts <<=8; ts | =Buff [байт (i)]; } recID =ts; memcpy (&Config, &Buff [4], sizeof (struct cfg)); вернуть истину; } return false;} // ------------------------------------------ класс КОНФИГУРАЦИЯ ГОРЯЧЕГО ПИСТОЛЕТА ---------------------------------------------- класс HOTGUN_CFG:общедоступная КОНФИГУРАЦИЯ {общедоступная:HOTGUN_CFG () {} недействительная инициализация (недействительность); uint16_t tempPreset (недействительно); // Заданная температура во внутренних единицах измерения uint8_t fanPreset (void); // Предустановленная скорость вентилятора 0 - 255 uint16_t tempInternal (uint16_t temp); // Преобразуем удобочитаемую температуру во внутреннее значение uint16_t tempHuman (uint16_t temp); // Переводим температуру из внутренних единиц в градусы Цельсия void save (uint16_t temp, uint8_t fanSpeed); // Сохранение заданной температуры во внутренних блоках и скорости вращения вентилятора void applyCalibrationData (uint16_t tip [3]); void getCalibrationData (uint16_t tip [3]); void saveCalibrationData (uint16_t tip [3]); void setDefaults (bool Write); // Устанавливаем значения параметров по умолчанию, если не удалось загрузить данные из EEPROM private:uint16_t t_tip [3]; const uint16_t def_tip [3] ={587, 751, 850}; // Значения по умолчанию показаний внутреннего датчика при эталонных температурах const uint16_t min_temp =50; константа uint16_t max_temp =900; константа uint16_t def_temp =600; // Заданная по умолчанию температура const uint8_t def_fan =64; // Предустановленная скорость вентилятора по умолчанию 0 - 255 const uint16_t ambient_temp =0; const uint16_t ambient_tempC =25;}; void HOTGUN_CFG ::init (void) {CONFIG ::init (); если (! CONFIG ::load ()) setDefaults (false); // Если не удалось загрузить данные из EEPROM, инициализируйте данные конфигурации со значениями по умолчанию uint32_t cd =Config.calibration; t_tip [0] =cd &0x3FF; cd>> =10; // 10 бит на параметр калибровки, поскольку показания АЦП равны 10 битам t_tip [1] =cd &0x3FF; cd>> =10; t_tip [2] =cd &0x3FF; // Проверяем правильность калибровки наконечника if ((t_tip [0]> =t_tip [1]) || (t_tip [1]> =t_tip [2])) {setDefaults (false); для (uint8_t i =0; i <3; ++ i) t_tip [i] =def_tip [i]; } return;} калибровка uint32_t; // Упакованные данные калибровки по трем температурным точкам uint16_t temp; // Заданная температура утюга во внутренних блоках uint8_t fan; // Предустановленная скорость вентилятора 0 - 255 uint8_t off_timeout; // Тайм-аут автоматического отключения uint16_t HOTGUN_CFG ::tempPreset (void) {return Config.temp;} uint8_t HOTGUN_CFG ::fanPreset (void) {return Config.fan;} uint16_t HOTGUN_CFG ::tempInternal (uint16_t t) {// Перевод человекочитаемая температура во внутреннее значение t =constrain (t, temp_minC, temp_maxC); uint16_t left =0; uint16_t right =1023; // Максимальное значение температуры во внутренних единицах измерения uint16_t temp =map (t, temp_tip [0], temp_tip [2], t_tip [0], t_tip [2]); если (темп> (влево + вправо) / 2) {темп - =(вправо-влево) / 4; } еще {темп + =(вправо-влево) / 4; } для (uint8_t i =0; i <20; ++ i) {uint16_t tempH =tempHuman (temp); если (tempH ==t) {вернуть темп; } uint16_t new_temp; если (tempH > 1; } t_tip [0] =подсказка [0]; t_tip [1] =подсказка [1]; если (подсказка [2]> max_temp) подсказка [2] =max_temp; t_tip [2] =tip [2];} void HOTGUN_CFG ::getCalibrationData (uint16_t tip [3]) {tip [0] =t_tip [0]; подсказка [1] =t_tip [1]; подсказка [2] =t_tip [2];} void HOTGUN_CFG ::saveCalibrationData (uint16_t подсказка [3]) {если (подсказка [2]> max_temp) подсказка [2] =max_temp; uint32_t cd =подсказка [2] &0x3FF; cd <<=10; // Упаковка данных калибровки наконечника в одно 32-битное слово:10 бит на значение cd | =tip [1] &0x3FF; cd <<=10; cd | =подсказка [0]; Config.calibration =cd; t_tip [0] =подсказка [0]; t_tip [1] =подсказка [1]; t_tip [2] =tip [2];} void HOTGUN_CFG ::setDefaults (bool Write) {uint32_t c =def_tip [2] &0x3FF; c <<=10; c | =def_tip [1] &0x3FF; c <<=10; c | =def_tip [0] &0x3FF; Config.calibration =c; Config.temp =def_temp; Config.fan =def_fan; если (Запись) {КОНФИГУРАЦИЯ ::сохранить (); }} // ------------------------------------------ класс ЗУММЕР - -------------------------------------------------- --class BUZZER {public:BUZZER (byte buzzerP, bool active =true) {buzzer_pin =buzzerP; this-> active =active; } void init (недействительность); void shortBeep (пусто); void lowBeep (пусто); void doubleBeep (недействительно); void failedBeep (недействительно); частный:байт buzzer_pin; bool active;}; void BUZZER ::init (void) {pinMode (buzzer_pin, OUTPUT); если (активен) {digitalWrite (buzzer_pin, LOW); } еще {noTone (buzzer_pin); }} void BUZZER ::shortBeep (void) {if (active) {digitalWrite (buzzer_pin, HIGH); задержка (80); digitalWrite (buzzer_pin, LOW); } else {тон (buzzer_pin, 3520, 160); }} void BUZZER ::lowBeep (void) {если (активный) {digitalWrite (buzzer_pin, HIGH); задержка (160); digitalWrite (buzzer_pin, LOW); } else {тон (buzzer_pin, 880, 160); }} void BUZZER ::doubleBeep (void) {если (активный) {digitalWrite (buzzer_pin, HIGH); задержка (160); digitalWrite (buzzer_pin, LOW); задержка (150); digitalWrite (buzzer_pin, ВЫСОКИЙ); задержка (160); digitalWrite (buzzer_pin, LOW); } else {тон (buzzer_pin, 3520, 160); задержка (300); тон (buzzer_pin, 3520, 160); }} void BUZZER ::failedBeep (void) {если (активный) {digitalWrite (buzzer_pin, HIGH); задержка (170); digitalWrite (buzzer_pin, LOW); задержка (10); digitalWrite (buzzer_pin, ВЫСОКИЙ); задержка (80); digitalWrite (buzzer_pin, LOW); задержка (100); digitalWrite (buzzer_pin, ВЫСОКИЙ); задержка (80); digitalWrite (buzzer_pin, LOW); } else {тон (buzzer_pin, 3520, 160); задержка (170); тон (buzzer_pin, 880, 250); задержка (260); тон (buzzer_pin, 3520, 160); }} // ------------------------------------------ класс lcd DSPLay для пайка IRON ----------------------------- класс DSPL:protected LiquidCrystal_I2C {public:DSPL (void):LiquidCrystal_I2C (0x27, 16, 2) {} void init (недействительность); пусто очистить (пусто) {LiquidCrystal_I2C ::clear (); } void tSet (uint16_t t, bool Celsius =true); // Показать заданную температуру void tCurr (uint16_t t); // Показать текущую температуру void tInternal (uint16_t t); // Показать текущую температуру во внутренних единицах измерения void tReal (uint16_t t); // Показываем реальную температуру в градусах Цельсия в режиме калибровки void fanSpeed ​​(uint8_t s); // Показать скорость вращения вентилятора void appliedPower (uint8_t p, bool show_zero =true); // Показать приложенную мощность (%) void setupMode (uint8_t mode); void msgON (недействительно); // Показать сообщение:"ON" void msgOFF (void); void msgReady (недействительно); void msgCold (недействительно); void msgFail (недействительно); // Показать сообщение «Ошибка» void msgTune (void); // Показывать приватное сообщение Tune:bool full_second_line; // Заполнена ли вторая строка сообщением char temp_units; const uint8_t custom_symbols [3] [8] ={{0b00110, // Степень 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000}, {0b00100, // Знак вентилятора 0b01100, 0b01100, 0100b1000110, 0b01100, 0b01100, 0100b1000110, 0b01100, 0b01100, 0100b1000110, 0b01100, 0b01100, 0100b1000110 , 0b00000}, {0b00011, // Знак мощности 0b00110, 0b01100, 0b11111, 0b00110, 0b01100, 0b01000, 0b10000}};}; void DSPL ::init (void) {LiquidCrystal_I2C ::begin (); LiquidCrystal_I2C ::clear (); for (uint8_t i =0; i <3; ++ i) LiquidCrystal_I2C ::createChar (i + 1, (uint8_t *) custom_symbols [i]); full_second_line =ложь; temp_units ='C';} void DSPL ::tSet (uint16_t t, bool Celsius) {char buff [10]; если (Цельсия) {temp_units ='C'; } еще {temp_units ='F'; } LiquidCrystal_I2C ::setCursor (0, 0); sprintf (buff, «Набор:% 3d% c% c», t, (char) 1, temp_units); LiquidCrystal_I2C ::print (buff);} void DSPL ::tCurr (uint16_t t) {char buff [6]; LiquidCrystal_I2C ::setCursor (0, 1); если (t <1000) {sprintf (buff, "% 3d% c", t, (char) 1); } else {LiquidCrystal_I2C ::print (F ("xxx")); возвращение; } LiquidCrystal_I2C ::print (бафф); если (full_second_line) {LiquidCrystal_I2C ::print (F ("")); full_second_line =ложь; }} void DSPL ::tInternal (uint16_t t) {char buff [6]; LiquidCrystal_I2C ::setCursor (0, 1); если (t <1023) {sprintf (бафф, "% 4d", t); } else {LiquidCrystal_I2C ::print (F ("xxxx")); возвращение; } LiquidCrystal_I2C ::print (бафф); если (full_second_line) {LiquidCrystal_I2C ::print (F ("")); full_second_line =ложь; }} void DSPL ::tReal (uint16_t t) {char buff [6]; LiquidCrystal_I2C ::setCursor (11, 1); если (t <1000) {sprintf (buff, ">% 3d% c", t, (char) 1); } else {LiquidCrystal_I2C ::print (F ("xxx")); возвращение; } LiquidCrystal_I2C ::print (buff);} void DSPL ::fanSpeed ​​(uint8_t s) {char buff [6]; s =карта (s, 0, 255, 0, 99); sprintf (buff, "% c% 2d% c", (char) 2, s, '%'); LiquidCrystal_I2C ::setCursor (11, 1); LiquidCrystal_I2C ::print (buff);} void DSPL ::applicationPower (uint8_t p, bool show_zero) {char buff [6]; если (p>
 99) p =99; LiquidCrystal_I2C ::setCursor (5, 1); если (p ==0 &&! show_zero) {LiquidCrystal_I2C ::print (F ("")); } else {sprintf (бафф, "% c% 2d% c", (char) 3, p, '%'); LiquidCrystal_I2C ::print (бафф); }} void DSPL ::setupMode (байтовый режим) {LiquidCrystal_I2C ::clear (); LiquidCrystal_I2C ::print (F ("настройка")); LiquidCrystal_I2C ::setCursor (1,1); switch (mode) {case 0:// калибровка наконечника LiquidCrystal_I2C ::print (F ("калибровка")); ломать; case 1:// настройка LiquidCrystal_I2C ::print (F ("tune")); ломать; case 2:// сохранить LiquidCrystal_I2C ::print (F ("save")); ломать; case 3:// отменить LiquidCrystal_I2C ::print (F ("cancel")); ломать; case 4:// установить значения по умолчанию LiquidCrystal_I2C ::print (F ("reset config")); ломать; по умолчанию:перерыв; }} void DSPL ::msgON (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("ON"));} void DSPL ::msgOFF (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("ВЫКЛ"));} void DSPL ::msgReady (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("Готово"));} void DSPL ::msgCold (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("Холодный"));} void DSPL ::msgFail (void) {LiquidCrystal_I2C ::setCursor (0, 1); LiquidCrystal_I2C ::print (F ("- ==Failed ==-"));} void DSPL ::msgTune (void) {LiquidCrystal_I2C ::setCursor (0, 0); LiquidCrystal_I2C ::print (F ("Настроить"));} // ---------------------------------- -------- ИСТОРИЯ класса ---------------------------------------- ------------ # define H_LENGTH 16class HISTORY {public:HISTORY (void) {len =0; } void init (недействительно) {len =0; } uint16_t last (недействительно); uint16_t сверху (недействительно) {очередь возврата [0]; } void put (uint16_t item); // Помещаем новую запись в историю uint16_t average (void); // вычисляем среднее значение дисперсии поплавка (void); // вычисляем математическую дисперсию private:volatile uint16_t queue [H_LENGTH]; изменчивый байт len; // Количество элементов в очереди volatile byte index; // Текущая позиция элемента, использовать кольцевой буфер}; void HISTORY ::put (uint16_t item) {if (len  =H_LENGTH) index =0; // Используем кольцевой буфер}} uint16_t HISTORY ::last (void) {if (len ==0) return 0; uint8_t i =len - 1; if (index) i =index - 1; очередь возврата [i];} uint16_t HISTORY ::average (void) {uint32_t sum =0; если (len ==0) вернуть 0; if (len ==1) очередь возврата [0]; for (uint8_t i =0; i > 1; // округлить среднюю сумму / =len; return uint16_t (сумма);} float ИСТОРИЯ ::дисперсия (void) {если (len <3) return 1000; uint32_t sum =0; uint32_t avg =средний (); для (uint8_t я =0; я > 1; обновление (значение); return (emp_data + round_v) / emp_k;} void EMP_AVERAGE ::update (значение int32_t) {uint8_t round_v =emp_k>> 1; emp_data + =значение - (emp_data + round_v) / emp_k;} int32_t EMP_AVERAGE ::read (void) {uint8_t round_v =emp_k>> 1; return (emp_data + round_v) / emp_k;} // -------------------------------------- ---- class PID algoritm для поддержания температуры ----------------------- / * Алгоритм PID * Un =Kp * (Xs - Xn) + Ki * summ {j =0; j <=n} (Xs - Xj) + Kd (Xn - Xn-1), * где Xs - заданная температура, Xn - температура на шаге n итераций * В этой программе используется интерактивная формула:* Un =Un-1 + Kp * (Xn-1 - Xn) + Ki * (Xs - Xn) + Kd * (Xn-2 + Xn - 2 * Xn-1) * С первым шагом:* U0 =Kp * ( Xs - X0) + Ki * (Xs - X0); Xn-1 =Xn; * * История коэффициентов PID:* 14.10.2017 [768, 32, 328] * 27.11.2019 [2009, 1600, 20] * 27.04.2020 [50, 16, 50] * / class PID { общедоступный:PID (void) {Kp =50; Ki =16; Kd =50; } void resetPID (int temp =-1); // сбросить параметры истории алгоритма PID // Рассчитать мощность, которую нужно применить long reqPower (int temp_set, int temp_curr); int changePID (uint8_t p, int k); // установить или получить (если параметр <0) параметр PID private:void debugPID (int t_set, int t_curr, long kp, long ki, long kd, long delta_p); int temp_h0, temp_h1; // измеренная ранее температура bool pid_iterate; // Используется ли итерационный процесс long i_summ; // Сумма Ki, умноженная на знаменатель long power; // Степенное итеративное умножение на знаменатель long Kp, Ki, Kd; // Коэффициенты алгоритма PID, умноженные на знаменатель const byte denominator_p =11; // The common coefficient denominator power of 2 (11 means divide by 2048)};void PID::resetPID(int temp) { temp_h0 =0; power =0; i_summ =0; pid_iterate =false; if ((temp>
 0) &&(temp <1000)) temp_h1 =temp; else temp_h1 =0;}int PID::changePID(uint8_t p, int k) { switch(p) { case 1:if (k>=0) Kp =k; return Kp; case 2:if (k>=0) Ki =k; return Ki; case 3:if (k>=0) Kd =k; return Kd; default:break; } return 0;}long PID::reqPower(int temp_set, int temp_curr) { if (temp_h0 ==0) { // When the temperature is near the preset one, reset the PID and prepare iterative formula if ((temp_set - temp_curr) <30) { if (!pid_iterate) { pid_iterate =true; power =0; i_summ =0; } } i_summ +=temp_set - temp_curr; // first, use the direct formula, not the iterate process power =Kp*(temp_set - temp_curr) + Ki*i_summ; // If the temperature is near, prepare the PID iteration process } else { long kp =Kp * (temp_h1 - temp_curr); long ki =Ki * (temp_set - temp_curr); long kd =Kd * (temp_h0 + temp_curr - 2*temp_h1); long delta_p =kp + ki + kd; power +=delta_p; // power kept multiplied by denominator! } if (pid_iterate) temp_h0 =temp_h1; temp_h1 =temp_curr; long pwr =power + (1 <<(denominator_p-1)); // prepare the power to delete by denominator, round the result pwr>>=denominator_p; // delete by the denominator return pwr;}//--------------------- High frequency PWM signal calss on D9 pin ------------------------- ---------------class FastPWM_D9 { public:FastPWM_D9() { } void init(void); void duty(uint8_t d) { OCR1A =d; } uint8_t fanSpeed(void) { return OCR1A; }};void FastPWM_D9::init(void) { pinMode(9, OUTPUT); digitalWrite (9, LOW); noInterrupts(); TCNT1 =0; TCCR1B =_BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer TCCR1A =0; ICR1 =256; TCCR1B =_BV(WGM13) | _BV(CS10); // Top value =ICR1, prescale =1 TCCR1A |=_BV(COM1A1); // XOR D9 on OCR1A, detached from D10 OCR1A =0; // Switch-off the signal on pin 9; interrupts();}//--------------------- Hot air gun manager using total sine shape to power on the hardware ---------------class HOTGUN :public PID { public:typedef enum { POWER_OFF, POWER_ON, POWER_FIXED, POWER_COOLING } PowerMode; HOTGUN(uint8_t HG_sen_pin, uint8_t HG_pwr_pin); void init(void); bool isOn(void) { return (mode ==POWER_ON || mode ==POWER_FIXED); } void setTemp(uint16_t temp) { temp_set =constrain(temp, 0, int_temp_max); } uint16_t getTemp(void) { return temp_set; } uint16_t getCurrTemp(void) { return h_temp.last(); } uint16_t tempAverage(void) { return h_temp.average(); } uint8_t powerAverage(void) { return h_power.average(); } uint8_t appliedPower(void) { return actual_power; } void setFanSpeed(uint8_t f) { fan_speed =constrain(f, min_working_fan, max_fan_speed); } uint8_t getFanSpeed(void) { return fan_speed; } uint16_t tempDispersion(void) { return h_temp.dispersion(); } bool isCold(void) { return h_temp.average() =period) { cnt =0; last_period =millis(); // Save the current time to check the external interrupts if (!active &&(actual_power> 0)) { digitalWrite(gun_pin, HIGH); active =true; } } else if (cnt>=actual_power) { if (active) { digitalWrite(gun_pin, LOW); active =false; } } if (!active) { e_sensor.update(analogRead(sen_pin)); } return (cnt ==0); // End of the Power period (period AC voltage shapes)}void HOTGUN::switchPower(bool On) { switch (mode) { case POWER_OFF:if (hg_fan.fanSpeed() ==0) { // Not power supplied to the Fan if (On) // !FAN &&On mode =POWER_ON; } else { if (On) { if (isGunConnected()) { // FAN &&On &&connected mode =POWER_ON; } else { // FAN &&On &&!connected shutdown(); } } else { if (isGunConnected()) { // FAN &&!On &&connected if (isCold()) { // FAN &&!On &&connected &&cold shutdown(); } else { // FAN &&!On &&connected &&!cold mode =POWER_COOLING; } } } } break; case POWER_ON:if (!On) { mode =POWER_COOLING; } ломать; case POWER_FIXED:if (hg_fan.fanSpeed()) { if (On) { // FAN &&On mode =POWER_ON; } else { // FAN &&!On if (isGunConnected()) { // FAN &&!On &&connected if (isCold()) { // FAN &&!On &&connected &&cold shutdown(); } else { // FAN &&!On &&connected &&!cold mode =POWER_COOLING; } } } } else { // !FAN if (!On) { // !FAN &&!On shutdown(); } } ломать; case POWER_COOLING:if (hg_fan.fanSpeed()) { if (On) { // FAN &&On if (isGunConnected()) { // FAN &&On &&connected mode =POWER_ON; } else { // FAN &&On &&!connected shutdown(); } } else { // FAN &&!On if (isGunConnected()) { if (isCold()) { // FAN &&!On &&connected &&cold shutdown(); } } else { // FAN &&!On &&!connected shutdown(); } } } else { if (On) { // !FAN &&On mode =POWER_ON; } } } h_power.init();}// This routine is used to keep the hot air gun temperature near required valuevoid HOTGUN::keepTemp(void) { //uint16_t temp =analogRead(sen_pin); // Check the hot air gun temperature //uint16_t temp =emulateTemp(); uint16_t temp =e_sensor.read(); // Average value of the hot air gun temperature h_temp.put(temp); ...This file has been truncated, please download it to see its full contents.
Github
https://github.com/ManojBR105/ARDUINO-SMD-REWORK-STATIONhttps://github.com/ManojBR105/ARDUINO-SMD-REWORK-STATION

Схема

This is the power supply circuit to provide necessary voltage for the controller. hot_air_gunsch_l627KvauMg.sch

Производственный процесс

  1. Жидкокристаллический дисплей (ЖКД)
  2. Сделайте самодельную термокамеру
  3. Метеостанция Raspberry Pi 2
  4. Метеостанция Raspberry Pi
  5. Портрет одержимого - обновленный
  6. Метеостанция V 2.0
  7. UVC Box - УФ-стерилизатор для самостоятельного изготовления
  8. DIY Простой осциллограф Arduino 20 кГц на ЖК-дисплее Nokia 5110
  9. ЖК-анимация и игры
  10. Осциллограф 10 Гц-50 кГц для самостоятельного изготовления на ЖК-дисплее 128x64