Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Estação de retrabalho DIY SMD

Componentes e suprimentos

SparkFun Arduino Pro Mini 328 - 5 V / 16 MHz
× 1
Adafruit LCD padrão - 16x2 branco em azul
× 1
módulo lcd i2c
× 1
Codificador rotativo com botão de pressão
× 1
Cabo da pistola de ar quente
× 1
Suporte do cabo da pistola de ar quente + bico
× 1
BTA12-600B
× 1
IRFZ44
× 1
MCP602
× 1
MOC3052
× 1
4N25
× 1
Retificador de ponte
× 1
Buzzer
× 1
diodo retificador rápido FR107
× 1
Capacitor 0,01 uF, 400V
× 1
Capacitor 100 nF
× 6
Through Hole Resistor, 39 ohm
× 1
Resistor de furo passante, 33 kohm
× 2
Resistor 330 ohm
× 1
Resistor 220 ohm
× 1
Resistor 1k ohm
× 3
Resistor de furo passante, 470 ohm
× 1
Potenciômetro multivoltas de 500 k
× 1
Resistor 10k ohm
× 3

Ferramentas e máquinas necessárias

Ferro de soldar (genérico)

Aplicativos e serviços online

Arduino IDE
Autodesk Eagle

Sobre este projeto





Introdução:Estação de retrabalho DIY SMD


Neste tutorial, você pode aprender como fazer um controlador de pistola de ar quente usando Arduino e outros componentes comuns. Neste projeto, o algoritmo PID é usado para calcular a potência necessária e é controlado por um driver Triac isolado.

Este projeto usa um identificador compatível com 858D. Ele tem um termopar tipo K, aquecedor de 700 watts 230 VAC e um ventilador de 24 VDC.

Este controlador é eficiente e confiável em comparação com o comercial e é fácil de construir.





Etapa 1:Fiação


O schematis completo mostrado na figura abaixo.




Fiação para módulo I2C LCD:

Módulo I2C <--------------> Arduino Pro Mini

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

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

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

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

Fiação para módulo codificador rotativo:

Codificador <----------------------> Arduino

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

+ <--------------------------------> NC (não conectado, o código usa pull-up de entrada embutido do arduino)

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

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

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

Fiação da alça: (7 fios)

Conector de 3 pinos - (Verde, Preto, Vermelho)

Fio vermelho <-----------------------> Termopar +

Fio verde <--------------------> Reed Switch

Fio preto <---------------------> Terra comum.

Conector de 2 pinos - (Azul, Amarelo)

Fio azul <--------------------------> Ventilador +0

Fio amarelo <------------------------> Ventilador - (ou GND)

Conector de 2 pinos grandes - (branco, marrom)

Fio branco <-----------------------> Aquecedor

Fio marrom <----------------------> Aquecedor (sem polaridade)

NOTA:

A fiação do cabo da pistola de ar quente pode ser diferente para diferentes tipos de hastes. Portanto, consulte o diagrama de fiação na foto e siga o caminho do fio para encontrar os respectivos pinos.





Etapa 2:Diagrama de circuito


O circuito consiste principalmente em 3 partes.

A parte da interface:

Consiste em um display LCD 1602 com módulo I2C e um codificador rotativo com botão de pressão. O visor mostra a temperatura definida, a temperatura atual, a velocidade do ventilador, a potência aplicada e o status atual da manopla. O codificador é usado para várias entradas e para navegar pelas opções e controles.

A parte do sensor:

Consiste em um termopar tipo K para detecção de temperatura e uma chave reed para determinar a posição da manopla. A voltagem do termopar é amplificada pelo amplificador operacional para um nível de voltagem mensurável pelo Arduino. O ganho do op-amp é controlado pelo trim pot de 200K.

A parte do controlador:

Existem principalmente 2 controladores neste circuito. O primeiro é um controlador de velocidade de ventilador PWM simples com um MOSFET. O outro é um controlador isolado para aquecedor. Consiste em um TRIAC acionado por um DIAC opto-acoplado e é feito controlando o número de ciclos de onda que são entregues ao aquecedor. O optoacoplador 4N25 ajuda a manter a sincronização com a forma de onda CA.





Etapa 3:PCB


O circuito desse projeto é um pouco complicado, então recomendo que você use uma placa impressa ao invés de um dot PCB. Se você quiser fazer seu próprio PCB, anexei os arquivos Eagle no final do projeto. Mas, se você quiser que eles sejam feitos por uma empresa de fabricação de PCB, você pode encomendá-los da JLCPCB

. Você pode visualizar o design Easy EDA por meio deste link:https://easyeda.com/ManojBR/harws1-1





Etapa 4:o código e as bibliotecas


O programa é a parte mais importante do projeto e muito obrigado por sfrwmaker escrever o programa. O programa usa o algoritmo PID para controlar a energia para manter a temperatura definida. Ele funciona controlando o número de ciclos de onda entregues à alça por segundo.

Quando o controlador é ligado, o bastão fica no estado DESLIGADO. girando o codificador a temperatura e a velocidade do ventilador podem ser ajustadas. Imprensa curta do codificador alternará entre a velocidade do ventilador e o ajuste de temperatura definida.

A pistola de ar quente começa a aquecer assim que é retirada do suporte e mostra Pronto e emite um breve sinal sonoro quando atinge a temperatura definida. Ele irá desligar o aquecimento assim que for colocado de volta no suporte. Porém, o ventilador continuará a soprar até atingir a temperatura segura. Depois que a temperatura cair abaixo de 50 C, ele emitirá um bipe curto e exibirá COLD.

Quando a pistola de ar quente estiver desligada, o controlador entrará no modo Configuração se o codificador for pressionado por muito tempo .

O modo de configuração possui as opções Calibrar, Ajustar, Salvar e Cancelar e Redefinir configuração.

Nota: Se você estiver usando PCB de easyEDA então você deve alterar o número do pino do interruptor de palheta para o pino no. 8 e Buzzer pin para pin no.6

você precisa instalar a biblioteca Commoncontrols-master e a biblioteca time-master para que o código funcione corretamente.

Cuidado: Não conecte o controlador à tomada quando estiver atualizando o firmware. A fonte de alimentação não isolada do ventilador pode danificar seu laptop.

baixe o código-fonte do esboço na página do projeto.





Etapa 5:configuração


As leituras de temperatura devem ser calibradas com o valor original para obter leituras razoáveis. Portanto, para fazer isso você deve seguir os seguintes passos.

Primeiro, vá para o modo de configuração e selecione a opção Tune. No modo de tune, a temperatura interna (0-1023) é exibida na tela. Gire o codificador para selecionar manualmente a potência aplicada à pistola de ar quente. Aqueça a arma a 400 graus. Quando a temperatura e a dispersão ficam baixas, o controlador emite um bipe. Em seguida, ajuste o trim-pot para definir a temperatura interna em cerca de 900 (nas unidades internas). Pressione longamente para o codificador retornar ao menu

Em seguida, vá para o modo de configuração e selecione a opção Calibrar. Escolha o ponto de calibração:200, 300 ou 400 graus, pressione o codificador. A pistola quente atingirá a temperatura desejada e emitirá um bipe. Girando o codificador, insira a temperatura real. Em seguida, selecione outro ponto de referência e repita este processo para todos os pontos de calibração.

Após este pressionamento longo, vá para a tela principal e, em seguida, vá novamente para o modo de Configuração e selecione Salvar.

E agora a estação de retrabalho de ar quente está pronta.





Etapa 6:Vídeo!


Dê uma olhada no funcionamento do controlador no vídeo.

Obrigado sfrwmaker por escrever o código.

Obrigado ao LCSC por seu apoio. LCSC Electronics é um dos fornecedores de componentes eletrônicos que mais cresce na China. LCSC tem o compromisso de oferecer vários itens genuínos e em estoque, desde a sua fundação em 2011. Com o objetivo de fornecer ao mundo todo peças superiores da Ásia. Mais detalhes, visite:https://lcsc.com/

Se você tiver que fazer seu próprio PCB em casa, verifique este tutorial:https://www.instructables.com/id/PCB-Making-1/

Obrigada.

Código

  • Firmware 1.4
Firmware 1.4 C / C ++
Suporte para campainha ativa / passiva. Por favor, altere o parâmetro BUZZER_ACTIVE
Não há mais codificador giratório aumentado. O valor muda em 1.
 / * * Controlador de pistola de ar quente baseado em atmega328 IC * Versão 1.4 * Lançado em 05 de dezembro de 2020 * / # include  #include  #include  #include  #include  #include  #include  const uint16_t temp_minC =100; // Temperatura mínima que o controlador pode verificar com precisãoconst uint16_t temp_maxC =500; // Temperatureconst máximo possível uint16_t temp_ambC =25; // Temperatura ambiente médiaconst uint16_t temp_tip [3] ={200, 300, 400}; // Pontos de referência de temperatura para calibraçãoconst uint16_t min_working_fan =100; // Velocidade mínima possível do ventiladorconst uint8_t AC_SYNC_PIN =2; // Pino de sincronização da saída 220 v. Não mude! Const uint8_t HOT_GUN_PIN =7; // Pinconst de gerenciamento do aquecedor de pistola quente uint8_t FAN_GUN_PIN =9; // Pino de gerenciamento do ventilador da arma quente. Não mude! const uint8_t TEMP_GUN_PIN =A0; // Verificação da temperatura da pistola quente pinconst uint8_t R_MAIN_PIN =3; // Pino principal do codificador rotativo. Não mude! Const uint8_t R_SECD_PIN =4; // Pinconst secundário do codificador rotativo uint8_t R_BUTN_PIN =5; // Pinconst do botão codificador rotativo uint8_t REED_SW_PIN =8; // Pinconst do interruptor Reed uint8_t BUZZER_PIN =6; // Buzzer pinconst bool BUZZER_ACTIVE =true; // A cigarra ativa emite um bipe quando + 5v fornecido a ela // ------------------------------------- ----- Dados de configuração ------------------------------------------- ----- / * O registro de configuração na EEPROM tem o seguinte formato:* uint32_t ID a cada incremento de 1 * dados de configuração de struct cfg, 8 bytes * byte CRC a soma de verificação * / struct cfg {uint32_t calibração; // Dados de calibração compactados por três pontos de temperatura uint16_t temp; // A temperatura predefinida do FERRO nas unidades internas uint8_t fan; // A velocidade predefinida do ventilador 0 - 255 uint8_t off_timeout; // Tempo limite de desligamento automático}; classe CONFIG {public:CONFIG () {can_write =false; buffRecords =0; rAddr =wAddr =0; eLength =0; nextRecID =0; uint8_t rs =sizeof (struct cfg) + 5; // O tamanho total do registro de configuração // Selecione o tamanho apropriado do registro; O tamanho do registro deve ser a potência de 2, ou seja, 8, 16, 32, 64, ... bytes para (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); return save (); // Salva novos dados na 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 summ =0; para (uint8_t i =0; i <4; ++ i) {EEPROM.write (startWrite ++, nxt &0xff); soma <<=2; soma + =nxt; nxt>> =8; } uint8_t * p =(byte *) &Config; para (uint8_t i =0; i  EEPROM.length ()) wAddr =0; nextRecID ++; // Prepare-se para escrever o próximo registro 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 Buff [record_size]; para (uint8_t i =0; i  =0; --i) {ts <<=8; ts | =Buff [byte (i)]; } recID =ts; memcpy (&Config, &Buff [4], sizeof (struct cfg)); return true; } return false;} // ------------------------------------------ classe HOT GUN CONFIG ---------------------------------------------- classe HOTGUN_CFG:public CONFIG {public:HOTGUN_CFG () {} void init (void); uint16_t tempPreset (void); // A temperatura predefinida em unidades internas uint8_t fanPreset (void); // A velocidade predefinida do ventilador 0 - 255 uint16_t tempInternal (uint16_t temp); // Traduzir a temperatura legível por humanos em valor interno uint16_t tempHuman (uint16_t temp); // Traduzir a temperatura das unidades internas para o Celsius void save (uint16_t temp, uint8_t fanSpeed); // Salvar a temperatura predefinida nas unidades internas e a velocidade do ventilador void applyCalibrationData (uint16_t tip [3]); void getCalibrationData (uint16_t tip [3]); void saveCalibrationData (uint16_t tip [3]); void setDefaults (bool Write); // Define os valores dos parâmetros padrão se falhar ao carregar os dados da EEPROM private:uint16_t t_tip [3]; const uint16_t def_tip [3] ={587, 751, 850}; // Valores padrão das leituras do sensor interno nas temperaturas de referência const uint16_t min_temp =50; const uint16_t max_temp =900; const uint16_t def_temp =600; // Temperatura predefinida padrão const uint8_t def_fan =64; // Velocidade predefinida do ventilador padrão 0 - 255 const uint16_t ambient_temp =0; const uint16_t ambient_tempC =25;}; void HOTGUN_CFG ::init (void) {CONFIG ::init (); if (! CONFIG ::load ()) setDefaults (false); // Se falhar ao carregar os dados da EEPROM, inicialize os dados de configuração com os valores padrão uint32_t cd =Config.calibration; t_tip [0] =cd &0x3FF; cd>> =10; // 10 bits por parâmetro de calibração, porque as leituras ADC são de 10 bits t_tip [1] =cd &0x3FF; cd>> =10; t_tip [2] =cd &0x3FF; // Verifique se a calibração da ponta está correta if ((t_tip [0]> =t_tip [1]) || (t_tip [1]> =t_tip [2])) {setDefaults (false); para (uint8_t i =0; i <3; ++ i) t_tip [i] =def_tip [i]; } return;} calibração uint32_t; // Dados de calibração compactados por três pontos de temperatura uint16_t temp; // A temperatura predefinida do FERRO nas unidades internas uint8_t fan; // A velocidade predefinida do ventilador 0 - 255 uint8_t off_timeout; // Desligamento automático timeoutuint16_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) {// Traduzir o temperatura legível por humanos em valor interno t =restrição (t, temp_minC, temp_maxC); uint16_t left =0; uint16_t right =1023; // Valor máximo da temperatura em unidades internas uint16_t temp =map (t, temp_tip [0], temp_tip [2], t_tip [0], t_tip [2]); if (temp>
 (esquerda + direita) / 2) {temp - =(direita-esquerda) / 4; } else {temp + =(direita-esquerda) / 4; } para (uint8_t i =0; i <20; ++ i) {uint16_t tempH =tempHuman (temp); if (tempH ==t) {temp de retorno; } uint16_t new_temp; if (tempH > 1; } t_tip [0] =tip [0]; t_tip [1] =tip [1]; if (tip [2]> max_temp) tip [2] =max_temp; t_tip [2] =tip [2];} void HOTGUN_CFG ::getCalibrationData (uint16_t tip [3]) {tip [0] =t_tip [0]; dica [1] =t_tip [1]; tip [2] =t_tip [2];} void HOTGUN_CFG ::saveCalibrationData (uint16_t tip [3]) {if (tip [2]> max_temp) tip [2] =max_temp; uint32_t cd =tip [2] &0x3FF; cd <<=10; // Pacote de dados de calibração da ponta em uma palavra de 32 bits:10 bits por valor cd | =tip [1] &0x3FF; cd <<=10; cd | =ponta [0]; Config.calibration =cd; t_tip [0] =tip [0]; t_tip [1] =tip [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; if (Gravar) {CONFIG ::save (); }} // ------------------------------------------ classe BUZZER - -------------------------------------------------- --classe BUZZER {public:BUZZER (byte buzzerP, bool ativo =verdadeiro) {buzzer_pin =buzzerP; este-> ativo =ativo; } void init (void); void shortBeep (void); void lowBeep (void); void doubleBeep (void); void failedBeep (void); privado:byte buzzer_pin; bool ativo;}; void BUZZER ::init (void) {pinMode (buzzer_pin, OUTPUT); if (ativo) {digitalWrite (buzzer_pin, LOW); } else {noTone (buzzer_pin); }} void BUZZER ::shortBeep (void) {if (ativo) {digitalWrite (buzzer_pin, HIGH); atraso (80); digitalWrite (buzzer_pin, LOW); } else {tone (buzzer_pin, 3520, 160); }} void BUZZER ::lowBeep (void) {if (ativo) {digitalWrite (buzzer_pin, HIGH); atraso (160); digitalWrite (buzzer_pin, LOW); } else {tom (buzzer_pin, 880, 160); }} void BUZZER ::doubleBeep (void) {if (ativo) {digitalWrite (buzzer_pin, HIGH); atraso (160); digitalWrite (buzzer_pin, LOW); atraso (150); digitalWrite (buzzer_pin, HIGH); atraso (160); digitalWrite (buzzer_pin, LOW); } else {tone (buzzer_pin, 3520, 160); atraso (300); tom (buzzer_pin, 3520, 160); }} void BUZZER ::failedBeep (void) {if (ativo) {digitalWrite (buzzer_pin, HIGH); atraso (170); digitalWrite (buzzer_pin, LOW); atraso (10); digitalWrite (buzzer_pin, HIGH); atraso (80); digitalWrite (buzzer_pin, LOW); atraso (100); digitalWrite (buzzer_pin, HIGH); atraso (80); digitalWrite (buzzer_pin, LOW); } else {tone (buzzer_pin, 3520, 160); atraso (170); tom (buzzer_pin, 880, 250); atraso (260); tom (buzzer_pin, 3520, 160); }} // ------------------------------------------ classe lcd DSPLay para FERRO de solda ----------------------------- classe DSPL:protegido LiquidCrystal_I2C {público:DSPL (vazio):LiquidCrystal_I2C (0x27, 16, 2) {} vazio inicial (vazio); void clear (void) {LiquidCrystal_I2C ::clear (); } void tSet (uint16_t t, bool Celsius =true); // Mostra a temperatura predefinida void tCurr (uint16_t t); // Mostra a temperatura atual void tInternal (uint16_t t); // Mostra a temperatura atual em unidades internas void tReal (uint16_t t); // Mostra a temperatura real em Celsius no modo de calibração void fanSpeed ​​(uint8_t s); // Mostra a velocidade do ventilador void applyPower (uint8_t p, bool show_zero =true); // Mostra a potência aplicada (%) void setupMode (modo uint8_t); void msgON (void); // Mostrar mensagem:"ON" void msgOFF (void); void msgReady (void); void msgCold (void); void msgFail (void); // Mostra a mensagem de 'Falha' void msgTune (void); // Mostra a mensagem 'Tune' private:bool full_second_line; // Se a segunda linha está cheia com a mensagem char temp_units; const uint8_t custom_symbols [3] [8] ={{0b00110, // Grau 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000}, {0b00100, // Sinal do ventilador 0b01100, 0b01100, 0b00110b, 0b10011001, 0b011001, 0b00110 , 0b00000}, {0b00011, // Sinal de energia 0b00110, 0b01100, 0b11111, 0b00110, 0b01100, 0b01000, 0b10000}};}; vazio DSPL ::init (void) {LiquidCrystal_I2C ::begin (); LiquidCrystal_I2C ::clear (); para (uint8_t i =0; i <3; ++ i) LiquidCrystal_I2C ::createChar (i + 1, (uint8_t *) custom_symbols [i]); full_second_line =false; temp_units ='C';} void DSPL ::tSet (uint16_t t, bool Celsius) {char buff [10]; if (Celsius) {temp_units ='C'; } else {temp_units ='F'; } LiquidCrystal_I2C ::setCursor (0, 0); sprintf (buff, "Conjunto:% 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); if (t <1000) {sprintf (buff, "% 3d% c", t, (char) 1); } else {LiquidCrystal_I2C ::print (F ("xxx")); Retorna; } LiquidCrystal_I2C ::print (buff); if (full_second_line) {LiquidCrystal_I2C ::print (F ("")); full_second_line =false; }} void DSPL ::tInternal (uint16_t t) {char buff [6]; LiquidCrystal_I2C ::setCursor (0, 1); if (t <1023) {sprintf (buff, "% 4d", t); } else {LiquidCrystal_I2C ::print (F ("xxxx")); Retorna; } LiquidCrystal_I2C ::print (buff); if (full_second_line) {LiquidCrystal_I2C ::print (F ("")); full_second_line =false; }} void DSPL ::tReal (uint16_t t) {char buff [6]; LiquidCrystal_I2C ::setCursor (11, 1); if (t <1000) {sprintf (buff, ">% 3d% c", t, (char) 1); } else {LiquidCrystal_I2C ::print (F ("xxx")); Retorna; } LiquidCrystal_I2C ::print (buff);} void DSPL ::fanSpeed ​​(uint8_t s) {char buff [6]; s =mapa (s, 0, 255, 0, 99); sprintf (buff, "% c% 2d% c", (char) 2, s, '%'); LiquidCrystal_I2C ::setCursor (11, 1); LiquidCrystal_I2C ::print (buff);} void DSPL ::applyPower (uint8_t p, bool show_zero) {char buff [6]; se (p>
 99) p =99; LiquidCrystal_I2C ::setCursor (5, 1); if (p ==0 &&! show_zero) {LiquidCrystal_I2C ::print (F ("")); } else {sprintf (buff, "% c% 2d% c", (char) 3, p, '%'); LiquidCrystal_I2C ::print (buff); }} void DSPL ::setupMode (modo byte) {LiquidCrystal_I2C ::clear (); LiquidCrystal_I2C ::print (F ("configuração")); LiquidCrystal_I2C ::setCursor (1,1); switch (mode) {case 0:// tip calibrate LiquidCrystal_I2C ::print (F ("calibrate")); pausa; caso 1:// sintoniza LiquidCrystal_I2C ::print (F ("tune")); pausa; caso 2:// salvar LiquidCrystal_I2C ::print (F ("salvar")); pausa; caso 3:// cancelar LiquidCrystal_I2C ::print (F ("cancel")); pausa; caso 4:// definir padrões LiquidCrystal_I2C ::print (F ("reset config")); pausa; padrão:break; }} 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 ("OFF"));} void DSPL ::msgReady (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("Ready"));} void DSPL ::msgCold (void) {LiquidCrystal_I2C ::setCursor (10, 0); LiquidCrystal_I2C ::print (F ("Cold"));} void DSPL ::msgFail (void) {LiquidCrystal_I2C ::setCursor (0, 1); LiquidCrystal_I2C ::print (F ("- ==Falha ==-"));} void DSPL ::msgTune (void) {LiquidCrystal_I2C ::setCursor (0, 0); LiquidCrystal_I2C ::print (F ("Tune"));} // ---------------------------------- -------- classe HISTÓRIA ---------------------------------------- ------------ # define H_LENGTH 16class HISTORY {public:HISTORY (void) {len =0; } void init (void) {len =0; } uint16_t last (void); uint16_t top (void) {fila de retorno [0]; } void put (item uint16_t); // Coloca uma nova entrada no histórico uint16_t average (void); // calcula o valor médio da dispersão do float (void); // calcula a dispersão matemática private:volatile uint16_t queue [H_LENGTH]; volátil byte len; // O número de elementos no índice de bytes voláteis da fila; // A posição do elemento atual, usar buffer de anel}; void HISTORY ::put (uint16_t item) {if (len  =H_LENGTH) índice =0; // Usar buffer de anel}} uint16_t HISTORY ::last (void) {if (len ==0) return 0; uint8_t i =len - 1; se (índice) i =índice - 1; return queue [i];} uint16_t HISTÓRICO ::média (void) {uint32_t sum =0; se (len ==0) retornar 0; if (len ==1) return queue [0]; para (uint8_t i =0; i > 1; // arredondar a soma média / =len; retornar uint16_t (soma);} float HISTÓRICO ::dispersão (void) {if (len <3) retornar 1000; uint32_t sum =0; uint32_t avg =média (); para (uint8_t i =0; i > 1; atualização (valor); return (emp_data + round_v) / emp_k;} void EMP_AVERAGE ::update (valor int32_t) {uint8_t round_v =emp_k>> 1; emp_data + =valor - (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;} // -------------------------------------- ---- algoritmo PID de classe para manter a temperatura ----------------------- / * O algoritmo PID * Un =Kp * (Xs - Xn) + Ki * soma {j =0; j <=n} (Xs - Xj) + Kd (Xn - Xn-1), * Onde Xs - é a temperatura de configuração, Xn - a temperatura na etapa de n-iteração * Neste programa, a fórmula interativa é usada:* Un =Un-1 + Kp * (Xn-1 - Xn) + Ki * (Xs - Xn) + Kd * (Xn-2 + Xn - 2 * Xn-1) * Com a primeira etapa:* U0 =Kp * ( Xs - X0) + Ki * (Xs - X0); Xn-1 =Xn; * * Histórico de coeficientes PID:* 14/10/2017 [768, 32, 328] * 27/11/2019 [2009, 1600, 20] * 27/04/2020 [50, 16, 50] * / classe PID { público:PID (vazio) {Kp =50; Ki =16; Kd =50; } void resetPID (int temp =-1); // redefine os parâmetros do histórico do algoritmo PID // Calcula a potência a ser aplicada long reqPower (int temp_set, int temp_curr); int changePID (uint8_t p, int k); // definir ou obter (se parâmetro <0) parâmetro PID privado:void debugPID (int t_set, int t_curr, long kp, long ki, long kd, long delta_p); int temp_h0, temp_h1; // temperatura medida anteriormente bool pid_iterate; // Se o processo iterativo é usado long i_summ; // Resumo de Ki multiplicado pela potência longa do denominador; // A iterativa de potência multiplicada pelo denominador long Kp, Ki, Kd; // Os coeficientes do algoritmo PID multiplicados pelo denominador const byte denominator_p =11; // A potência do denominador do coeficiente comum de 2 (11 significa dividir por 2048)}; void PID ::resetPID (int temp) {temp_h0 =0; potência =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; padrão: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, BAIXO); 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; } pausa; 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(); } } pausa; 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

Esquemas

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

Processo de manufatura

  1. Tela de cristal líquido (LCD)
  2. Construa uma Thermocam DIY
  3. Estação meteorológica Raspberry Pi 2
  4. Estação meteorológica Raspberry Pi
  5. Retrato possesso - Atualizado
  6. Estação meteorológica V 2.0
  7. Caixa UVC um esterilizador UV DIY
  8. DIY Simple 20 kHz Arduino Oscilloscope no Nokia 5110 LCD
  9. Animação de LCD e jogos
  10. Osciloscópio DIY 10Hz-50kHz em tela LCD 128x64