산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

DIY SMD 재작업 스테이션

구성품 및 소모품

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Adafruit Standard LCD - 파란색 바탕에 16x2 흰색
× 1
lcd i2c 모듈
× 1
푸시 버튼이 있는 로터리 인코더
× 1
열풍총 손잡이
× 1
열풍기 손잡이 홀더 + 노즐
× 1
BTA12-600B
× 1
IRFZ44
× 1
MCP602
× 1
MOC3052
× 1
4N25
× 1
브리지 정류기
× 1
부저
× 1
FR107 고속 정류기 다이오드
× 1
0.01uF 커패시터, 400V
× 1
커패시터 100nF
× 6
스루 홀 저항기, 39옴
× 1
스루 홀 저항기, 33kohm
× 2
저항 330옴
× 1
저항 220옴
× 1
저항 1k 옴
× 3
스루 홀 저항기, 470옴
× 1
500k 다중 회전 전위차계
× 1
저항 10k 옴
× 3

필요한 도구 및 기계

납땜 인두(일반)

앱 및 온라인 서비스

Arduino IDE
Autodesk Eagle

이 프로젝트 정보

소개:DIY SMD 재작업 스테이션

이 튜토리얼에서는 Arduino 및 기타 일반적인 구성 요소를 사용하여 열풍 총 컨트롤러를 만드는 방법을 배울 수 있습니다. 이 프로젝트에서 PID 알고리즘은 필요한 전력을 계산하는 데 사용되며 격리된 Triac 드라이버에 의해 제어됩니다.

이 프로젝트는 858D와 호환되는 핸들을 사용합니다. K형 열전대, 700와트 230VAC 히터 및 24VDC 팬이 있습니다.

이 컨트롤러는 상용 컨트롤러에 비해 효율적이고 안정적이며 구축하기 쉽습니다.

1단계:배선

아래 그림에 표시된 전체 도식.


I2C LCD 모듈용 배선:

I2C 모듈<--------------> Arduino Pro Mini

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

VCC<------------------------>VCC<--------->5V

SDA<------------------------------------------->A4

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

로터리 인코더 모듈용 배선:

인코더<---------------------->Arduino

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

+<-------------------------------->NC(연결되지 않음, 코드는 arduino의 내장 입력 풀업을 사용함)

SW<----------------------------->D5

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

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

핸들 배선: (7 와이어)

3핀 커넥터 - (녹색, 검정색, 빨간색)

빨간색 와이어<----------------------->열전대 +

녹색 와이어<-------------------->리드 스위치

검은색 와이어<--------------------->공통 접지.

2핀 커넥터 - (파란색, 노란색)

파란색 와이어<--------------------------> 팬 +0

노란색 와이어<------------------------>팬 -(또는 GND)

2 큰 핀 커넥터 -(흰색, 갈색)

흰색 와이어<-----------------------> 히터

갈색 와이어<----------------------> 히터(무극성)

참고:

열풍총 손잡이의 배선은 봉의 종류에 따라 다를 수 있습니다. 따라서 사진의 배선도를 참고하여 배선의 경로를 따라 각각의 핀을 찾으시면 됩니다.

2단계:회로도

회로는 크게 3부분으로 구성되어 있습니다.

인터페이스 부분:

I2C 모듈이 있는 1602 LCD 디스플레이와 푸시 버튼이 있는 로터리 인코더로 구성됩니다. 디스플레이는 설정 온도, 현재 온도, 팬 속도 및 인가 전력 및 핸들의 현재 상태를 보여줍니다. 인코더는 다양한 입력과 옵션 및 컨트롤을 탐색하는 데 사용됩니다.

센서 부분:

온도 감지를 위한 K형 열전대와 손잡이의 위치를 ​​결정하기 위한 리드 스위치로 구성되어 있습니다. 열전쌍의 전압은 연산 증폭기에 의해 arduino에서 측정할 수 있는 전압 레벨로 증폭됩니다. 연산 증폭기의 이득은 200K 트림 포트에 의해 제어됩니다.

컨트롤러 부분:

이 회로에는 주로 2개의 컨트롤러가 있습니다. 하나는 MOSFET이 있는 간단한 PWM 팬 속도 컨트롤러입니다. 다른 하나는 히터용 절연 컨트롤러입니다. 이것은 광 결합 DIAC에 의해 구동되는 TRIAC으로 구성되며 히터에 전달되는 웨이브 사이클 수를 제어하여 수행됩니다. 4N25 광커플러는 AC 파형과의 동기화를 유지하는 데 도움이 됩니다.

3단계:PCB

이 프로젝트의 회로는 약간 복잡하므로 도트 PCB보다 인쇄 기판을 사용하는 것이 좋습니다. 나만의 PCB를 만들고 싶다면 프로젝트 마지막에 독수리 파일을 첨부했습니다. 그러나 PCB 제조 회사에서 작업을 수행하려면 JLCPCB에서 주문할 수 있습니다.

. 이 링크를 통해 Easy EDA 디자인을 볼 수 있습니다:https://easyeda.com/ManojBR/harws1-1

4단계:코드 및 라이브러리

이 프로그램은 프로젝트에서 가장 중요한 부분이며 sfrwmaker에 감사드립니다. 프로그램 작성. 프로그램은 PID 알고리즘을 사용합니다. 설정 온도를 유지하기 위해 전원을 제어합니다. 초당 핸들에 전달되는 웨이브 사이클 수를 제어하여 작동합니다.

컨트롤러가 켜지면 완드는 OFF 상태가 됩니다. 엔코더 회전 온도와 팬 속도를 조정할 수 있습니다. 짧게 누르기 인코더의 팬 속도와 설정 온도 조정 사이를 전환합니다.

핫에어건을 홀더에서 들어올리면 가열이 시작되며 설정온도에 도달하면 'Ready'가 표시되고 짧은 경고음이 울립니다. 홀더에 다시 넣으면 가열이 꺼집니다. 그러나 팬은 안전한 온도에 도달할 때까지 계속 불게 됩니다. 온도가 50C 아래로 떨어지면 짧은 경고음이 울리고 COLD가 표시됩니다.

열풍총이 꺼지면 컨트롤러가 설정 모드로 들어갑니다. 인코더를 길게 누른 경우 .

설정 모드에는 보정, 조정, 저장 및 취소 및 구성 재설정 옵션이 있습니다.

참고: easyEDA의 PCB를 사용하는 경우 그런 다음 reed 스위치의 핀 번호를 핀 번호로 변경해야 합니다. 86번 핀에 부저 핀

코드가 제대로 작동하려면 Commoncontrols-master 라이브러리와 time-master 라이브러리를 설치해야 합니다.

주의: 펌웨어를 플래싱할 때 컨트롤러를 전원 콘센트에 연결하지 마십시오. 팬의 비절연 전원 공급 장치는 노트북을 손상시킬 수 있습니다.

프로젝트 페이지에서 스케치 소스 코드를 다운로드하십시오.

5단계:설정

합리적인 판독값을 얻으려면 온도 판독값을 원래 값으로 보정해야 합니다. 따라서 그렇게 하려면 다음 단계를 따라야 합니다.

먼저 설정 모드로 이동하여 Tune 옵션을 선택합니다. Tune 모드에서 내부 온도(0-1023)가 화면에 표시됩니다. 인코더를 회전하여 열풍 총에 인가되는 전원을 수동으로 선택합니다. 건을 400도까지 가열합니다. 온도와 분산이 낮아지면 컨트롤러에서 신호음이 울립니다. 그런 다음 내부 온도를 약 900도로 설정하도록 트림 포트를 조정합니다(내부 장치에서). 인코더를 길게 누르면 메뉴로 돌아갑니다.

그런 다음 설정 모드로 이동하여 보정 옵션을 선택합니다. 보정 포인트를 선택하십시오:200, 300 또는 400도, 인코더를 누르십시오. 핫 건이 원하는 온도에 도달하고 경고음이 울립니다. 인코더를 돌려 실제 온도를 입력합니다. 그런 다음 다른 기준점을 선택하고 모든 보정점에 대해 이 과정을 반복합니다.

이 길게 누르고 메인 화면으로 와서 다시 설정 모드로 이동하여 저장을 선택합니다.

이제 열풍 재작업 스테이션이 완료되었습니다.

6단계:비디오!

영상에서 컨트롤러의 동작을 살펴보세요.

코드를 작성해 주신 sfrwmaker에게 감사드립니다.

LCSC의 지원에 감사드립니다. LCSC Electronics는 중국에서 가장 빠르게 성장하는 전자 부품 공급업체 중 하나입니다. LCSC는 2011년 설립된 이래로 다양한 정품 및 재고 품목을 제공하기 위해 최선을 다하고 있습니다. 아시아의 더 우수한 부품을 전 세계에 제공하는 것을 목표로 하고 있습니다. 자세한 내용은 https://lcsc.com/

을 참조하십시오.

집에서 자신만의 PCB를 만들어야 한다면 이 튜토리얼을 확인하십시오:https://www.instructables.com/id/PCB-Making-1/

감사합니다.

<섹션 클래스="섹션 컨테이너 섹션 축소 가능" id="코드">

코드

<울>
  • 펌웨어 1.4
  • 펌웨어 1.4C/C++
    능동/수동 부저 지원. BUZZER_ACTIVE 매개변수를 변경하십시오.
    더 이상 증가된 로터리 인코더가 없습니다. 값이 1.
    /* 변경됨 * atmega328 IC 기반 열풍총 컨트롤러 * 버전 1.4 * 2020년 12월 5일 출시 */#include #include #include  #include #include #include #include const uint16_t temp_minC =100; // 컨트롤러가 정확하게 확인할 수 있는 최소 온도const uint16_t temp_maxC =500; // 가능한 최대 온도 const16_t temp_ambC =25; // 평균 주변 온도const uint16_t temp_tip[3] ={200, 300, 400}; // 보정을 위한 온도 기준점const uint16_t min_working_fan =100; // 가능한 최소 팬 속도const uint8_t AC_SYNC_PIN =2; // 콘센트 220v 동기화 핀. 변경하지 마십시오! const uint8_t HOT_GUN_PIN =7; // 핫건 히터 관리 pinconst uint8_t FAN_GUN_PIN =9; // 핫건 팬 관리 핀. 바뀌지 않는다! 상수 uint8_t TEMP_GUN_PIN =A0; // 핫 건 온도 확인 pinconst uint8_t R_MAIN_PIN =3; // 로터리 엔코더 메인 핀. 변경하지 마십시오! const uint8_t R_SECD_PIN =4; // 로터리 인코더 2차 pinconst uint8_t R_BUTN_PIN =5; // 로터리 인코더 버튼 pinconst uint8_t REED_SW_PIN =8; // 리드 스위치 pinconst uint8_t BUZZER_PIN =6; // 부저 pinconst bool BUZZER_ACTIVE =true; // +5v가 공급되면 활성 부저가 울립니다. //---------------------------------------- ------ 구성 데이터 ------------------------------------------- -----/* EEPROM의 구성 레코드 형식은 다음과 같습니다. * uint32_t ID는 매번 1씩 증가합니다. * struct cfg 구성 데이터, 8바이트 * 바이트 CRC 체크섬*/struct cfg { uint32_t 보정; // 3개의 온도 포인트로 포장된 보정 데이터 uint16_t temp; // 내부 단위로 IRON의 사전 설정 온도 uint8_t fan; // 사전 설정된 팬 속도 0 - 255 uint8_t off_timeout; // 자동 종료 시간 제한};class CONFIG { public:CONFIG() { can_write =false; 버프 레코드 =0; rAddr =wAddr =0; e길이 =0; nextRecID =0; uint8_t rs =sizeof(구조체 cfg) + 5; // 전체 구성 레코드 크기 // 적절한 레코드 크기를 선택합니다. 레코드 크기는 (record_size =8; record_size  recID) { minRecID =recID; minRecAddr =addr; } if (maxRecID  eLength) wAddr =0; } else { 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); 반환 저장(); // 새 데이터를 EEPROM에 저장}bool CONFIG::save(void) { if (!can_write) return can_write; if (nextRecID ==0) nextRecID =1; uint16_t startWrite =wAddr; uint32_t nxt =nextRecID; uint8_t 합계 =0; for (uint8_t i =0; i <4; ++i) { EEPROM.write(startWrite++, nxt &0xff); 합계 <<=2; 합계 +=nxt; nxt>>=8; } uint8_t* p =(바이트 *)&구성; 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 addr, uint32_t &recID) { uint8_t 버프[record_size]; for (uint8_t i =0; i <레코드 크기; ++i) Buff[i] =EEPROM.read(addr+i); uint8_t 합계 =0; for (byte i =0; i =0, --i) { ts <<=8; ts |=버프[byte(i)]; } recID =ts; memcpy(&Config, &Buff[4], sizeof(struct cfg)); true를 반환합니다. } return false;}//------------------------------------------ 클래스 핫건 구성 ----------------------------------------------------------- 클래스 HOTGUN_CFG :공개 CONFIG { 공개: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]); 무효 getCalibrationData(uint16_t 팁[3]); 무효 saveCalibrationData(uint16_t 팁[3]); 무효 setDefaults(bool 쓰기); // EEPROM에서 데이터 로드에 실패한 경우 기본 매개변수 값을 설정합니다. private:uint16_t t_tip[3]; const uint16_t def_tip[3] ={587, 751, 850}; // 참조 온도에서 내부 센서 판독값의 기본값 const uint16_t min_temp =50; const uint16_t max_temp =900; 상수 uint16_t def_temp =600; // 기본 사전 설정 온도 const uint8_t def_fan =64; // 기본 사전 설정 팬 속도 0 - 255 const uint16_tambient_temp =0; const uint16_tambient_tempC=25;}; 무효 HOTGUN_CFG::초기화(무효) { 구성::초기화(); if (!CONFIG::load()) setDefaults(거짓); // EEPROM에서 데이터 로드에 실패한 경우 구성 데이터를 기본값으로 초기화합니다. uint32_t cd =Config.calibration; t_tip[0] =CD &0x3FF; cd>>=10; // ADC 판독값이 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); for (uint8_t i =0; i <3; ++i) t_tip[i] =def_tip[i]; } 반환;} uint32_t 보정; // 3개의 온도 포인트로 포장된 보정 데이터 uint16_t temp; // 내부 단위로 IRON의 사전 설정 온도 uint8_t fan; // 사전 설정된 팬 속도 0 - 255 uint8_t off_timeout; // 자동 종료 시간outuint16_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 왼쪽 =0; uint16_t 오른쪽 =1023; // 내부 단위의 최대 온도 값 uint16_t temp =map(t, temp_tip[0], temp_tip[2], t_tip[0], t_tip[2]); if (온도> (왼쪽+오른쪽)/ 2) { 온도 -=(오른쪽-왼쪽) / 4; } else { 온도 +=(오른쪽-왼쪽) / 4; } for (uint8_t i =0; i <20; ++i) { uint16_t tempH =tempHuman(temp); if (tempH ==t) { 반환 온도; } uint16_t new_temp; if (tempH > 1; } t_tip[0] =팁[0]; t_tip[1] =팁[1]; if (tip[2]> max_temp) tip[2] =max_temp; t_tip[2] =tip[2];} 무효 HOTGUN_CFG::getCalibrationData(uint16_t tip[3]) { tip[0] =t_tip[0]; 팁[1] =t_tip[1]; tip[2] =t_tip[2];} HOTGUN_CFG::saveCalibrationData(uint16_t tip[3]) { if (tip[2]> max_temp) tip[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];} 무효 HOTGUN_CFG::setDefaults(bool 쓰기) { uint32_t c =def_tip[2] &0x3FF; c <<=10; c |=def_tip[1] &0x3FF; c <<=10; c |=def_tip[0] &0x3FF; 구성 보정 =c; Config.temp =def_temp; Config.fan =def_fan; if (쓰기) { CONFIG::save(); }}//------------------------------------------ 클래스 BUZZER -- -------------------------------------------------- --class BUZZER { 공개:BUZZER(바이트 버저P, 부울 활성 =true) { 버저_핀 =버저P; 이->활성 =활성; } 무효 초기화(무효); 무효 shortBeep(무효); 무효 lowBeep(무효); 무효 doubleBeep(무효); 무효 실패 경고음(무효); 개인:바이트 버저_핀; 부울 활성;}; 무효 BUZZER::init(void) { pinMode(buzzer_pin, OUTPUT); if (활성) { digitalWrite(buzzer_pin, LOW); } else { noTone(buzzer_pin); }} 무효 BUZZER::shortBeep(무효) { if (활성) { digitalWrite(buzzer_pin, HIGH); 지연(80); digitalWrite(buzzer_pin, LOW); } else { 톤(buzzer_pin, 3520, 160); }} 무효 BUZZER::lowBeep(void) { if (활성) { digitalWrite(buzzer_pin, HIGH); 지연(160); digitalWrite(buzzer_pin, LOW); } else { 톤(buzzer_pin, 880, 160); }} 무효 BUZZER::doubleBeep(무효) { if (활성) { digitalWrite(buzzer_pin, HIGH); 지연(160); digitalWrite(buzzer_pin, LOW); 지연(150); digitalWrite(buzzer_pin, HIGH); 지연(160); digitalWrite(buzzer_pin, LOW); } else { 톤(buzzer_pin, 3520, 160); 지연(300); 톤(buzzer_pin, 3520, 160); }} 무효 BUZZER::failedBeep( 무효) { if (활성) { digitalWrite(buzzer_pin, HIGH); 지연(170); digitalWrite(buzzer_pin, LOW); 지연(10); digitalWrite(buzzer_pin, HIGH); 지연(80); digitalWrite(buzzer_pin, LOW); 지연(100); digitalWrite(buzzer_pin, HIGH); 지연(80); digitalWrite(buzzer_pin, LOW); } else { 톤(buzzer_pin, 3520, 160); 지연(170); 톤(buzzer_pin, 880, 250); 지연(260); 톤(buzzer_pin, 3520, 160); }}//------------------------------------------ 클래스 lcd DSPLay 납땜 인두 ------------------------------------------ 클래스 DSPL :보호된 LiquidCrystal_I2C { 공개:DSPL(void) :LiquidCrystal_I2C(0x27, 16, 2) { } 무효 초기화(무효); 무효 clear(void) { LiquidCrystal_I2C::clear(); } 무효 tSet(uint16_t t, 부울 섭씨 =true); // 미리 설정된 온도 표시 void tCurr(uint16_t t); // 현재 온도 표시 void tInternal(uint16_t t); // 현재 온도를 내부 단위로 표시 void tReal(uint16_t t); // 보정 모드에서 실제 온도를 섭씨로 표시 void fanSpeed(uint8_t s); // 팬 속도 표시 void applyPower(uint8_t p, bool show_zero =true); // 적용된 전력(%) 표시 void setupMode(uint8_t mode); 무효 msgON(무효); // 메시지 표시:"ON" void msgOFF(void); 무효 msgReady(무효); 무효 msgCold(무효); 무효 메시지 실패(무효); // '실패' 메시지 표시 void msgTune(void); // 'Tune' 메시지 표시 private: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, 0b00110, 0b01011, 0b11001, 0b10000 , 0b00000 }, { 0b00011, // 전원 기호 0b00110, 0b01100, 0b11111, 0b00110, 0b01100, 0b01000, 0b10000 } voidL }:init:(C voidL ):};void LiquidCrystal_I2C::clear(); (uint8_t i =0; i <3; ++i) LiquidCrystal_I2C::createChar(i+1, (uint8_t *)custom_symbols[i]); full_second_line =거짓; temp_units ='C';} 무효 DSPL::tSet(uint16_t t, bool 섭씨) { 문자 버프[10]; if (섭씨) { temp_units ='C'; } else { temp_units ='F'; } LiquidCrystal_I2C::setCursor(0, 0); sprintf(버프, "설정:%3d%c%c", t, (char)1, temp_units); LiquidCrystal_I2C::print(buff);} 무효 DSPL::tCurr(uint16_t t) { 문자 버프[6]; LiquidCrystal_I2C::setCursor(0, 1); if (t <1000) { sprintf(버프, "%3d%c", t, (문자)1); } else { LiquidCrystal_I2C::print(F("xxx")); 반품; } LiquidCrystal_I2C::print(버프); if (full_second_line) { LiquidCrystal_I2C::print(F(" ")); full_second_line =거짓; }} 무효 DSPL::tInternal(uint16_t t) { 문자 버프[6]; LiquidCrystal_I2C::setCursor(0, 1); if (t <1023) { sprintf(버프, "%4d", t); } else { LiquidCrystal_I2C::print(F("xxxx")); 반품; } LiquidCrystal_I2C::print(버프); if (full_second_line) { LiquidCrystal_I2C::print(F(" ")); full_second_line =거짓; }} 무효 DSPL::tReal(uint16_t t) { 문자 버프[6]; LiquidCrystal_I2C::setCursor(11, 1); if (t <1000) { sprintf(버프, ">%3d%c", t, (문자)1); } else { LiquidCrystal_I2C::print(F("xxx")); 반품; } LiquidCrystal_I2C::print(buff);} 무효 DSPL::fanSpeed(uint8_t s) { 문자 버프[6]; s =지도(들, 0, 255, 0, 99); sprintf(버프, " %c%2d%c", (char)2, s, '%'); LiquidCrystal_I2C::setCursor(11, 1); LiquidCrystal_I2C::print(buff);} 무효 DSPL::appliedPower(uint8_t p, bool show_zero) { 문자 버프[6]; 만약 (p>
     99) p =99; LiquidCrystal_I2C::setCursor(5, 1); if (p ==0 &&!show_zero) { LiquidCrystal_I2C::print(F(" ")); } else { sprintf(버프, " %c%2d%c", (문자)3, p, '%'); LiquidCrystal_I2C::print(버프); }} 무효 DSPL::setupMode(바이트 모드) { LiquidCrystal_I2C::clear(); LiquidCrystal_I2C::print(F("설정")); LiquidCrystal_I2C::setCursor(1,1); switch (mode) { case 0:// 팁 보정 LiquidCrystal_I2C::print(F("calibration")); 부서지다; 사례 1:// LiquidCrystal_I2C::print(F("tune"))를 조정합니다. 부서지다; 사례 2:// LiquidCrystal_I2C::print(F("save"))를 저장합니다. 부서지다; 사례 3:// 취소 LiquidCrystal_I2C::print(F("cancel")); 부서지다; 사례 4:// 기본값 설정 LiquidCrystal_I2C::print(F("reset config")); 부서지다; 기본값:중단; }} 무효 DSPL::msgON(무효) { LiquidCrystal_I2C::setCursor(10, 0); LiquidCrystal_I2C::print(F(" ON"));} 무효 DSPL::msgOFF(void) { LiquidCrystal_I2C::setCursor(10, 0); LiquidCrystal_I2C::print(F(" OFF"));} 무효 DSPL::msgReady(무효) { LiquidCrystal_I2C::setCursor(10, 0); LiquidCrystal_I2C::print(F(" 준비"));} 무효 DSPL::msgCold(void) { LiquidCrystal_I2C::setCursor(10, 0); LiquidCrystal_I2C::print(F(" Cold"));} 무효 DSPL::msgFail(void) { LiquidCrystal_I2C::setCursor(0, 1); LiquidCrystal_I2C::print(F(" -==실패 ==- "));}void DSPL::msgTune(void) { LiquidCrystal_I2C::setCursor(0, 0); LiquidCrystal_I2C::print(F("Tune"));}//------------------------------------------------ -------- 클래스 역사 ---------------------------------------- ------------#define H_LENGTH 16class HISTORY { 공개:HISTORY(무효) { len =0; } 무효 초기화(무효) { 렌 =0; } uint16_t 마지막(무효); uint16_t top(void) { 반환 큐[0]; } 무효 넣기(uint16_t 항목); // 기록에 새 항목을 넣습니다. uint16_t average(void); // 평균값 계산 float dispersion(void); // 수학 분산 계산 private:volatile uint16_t queue[H_LENGTH]; 휘발성 바이트 len; // 큐의 요소 수 volatile byte index; // 현재 요소 위치, 링 버퍼 사용};void HISTORY::put(uint16_t item) { if (len =H_LENGTH) 인덱스 =0; // 링 버퍼 사용 }}uint16_t HISTORY::last(void) { if (len ==0) return 0; uint8_t 나는 =len - 1; if (인덱스) i =인덱스 - 1; 반환 큐[i];}uint16_t 역사::average(void) { uint32_t 합계 =0; if (len ==0) 반환 0; if (len ==1) return queue[0]; for (uint8_t i =0; i > 1; // 평균 합을 반올림합니다. // len; return uint16_t(sum);}float HISTORY::dispersion(void) { if (len <3) return 1000; uint32_t 합계 =0; uint32_t 평균 =평균(); for (uint8_t i =0; i > 1; 업데이트(값); return (emp_data + round_v) / emp_k;} 무효 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;}//---------------------------------------------------- ---- 온도를 유지하기 위한 클래스 PID 알고리즘 -----------------------/* PID 알고리즘 * Un =Kp*(Xs - Xn) + Ki*sum{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 계수 기록:* 2017년 10월 14일 [768, 32, 328] * 2019년 11월 27일 [ 2009, 1600, 20] * 2020년 4월 27일 [ 50, 16, 50] */class PID { 공개:PID(무효) { Kp =50; 기 =16; Kd =50; } 무효 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); 정수 temp_h0, temp_h1; // 이전에 측정된 온도 bool pid_iterate; // 반복 프로세스가 사용되는지 여부 long i_summ; // Ki 요약에 분모 긴 거듭제곱을 곱합니다. // 거듭제곱 곱한 분모 long Kp, Ki, Kd; // The PID algorithm coefficients multiplied by denominator 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); 디지털 쓰기(9, 낮음); 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.
    깃허브
    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. 액정 디스플레이(LCD)
    2. DIY 써모캠 제작
    3. Raspberry Pi 2 기상 관측소
    4. 라즈베리 파이 기상 관측소
    5. 소지된 초상화 – 업데이트됨
    6. Weather Station V 2.0
    7. UVC 상자 DIY UV 살균기
    8. Nokia 5110 LCD의 DIY Simple 20kHz Arduino 오실로스코프
    9. LCD 애니메이션 및 게임
    10. 128x64 LCD 디스플레이의 DIY 10Hz-50kHz 오실로스코프