Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Station de retouche SMD bricolage

Composants et fournitures

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Adafruit Standard LCD - 16x2 Blanc sur Bleu
× 1
module lcd i2c
× 1
Encodeur rotatif avec bouton-poussoir
× 1
Poignée de pistolet à air chaud
× 1
Support de poignée de pistolet à air chaud + buse
× 1
BTA12-600B
× 1
IRFZ44
× 1
MCP602
× 1
MOC3052
× 1
4N25
× 1
Pont redresseur
× 1
Sonnerie
× 1
diode de redressement rapide FR107
× 1
Condensateur 0,01 uF, 400 V
× 1
Condensateur 100 nF
× 6
Résistance à trou traversant, 39 ohm
× 1
Résistance à trou traversant, 33 kohm
× 2
Résistance 330 ohm
× 1
Résistance 220 ohm
× 1
Résistance 1k ohm
× 3
Résistance à trou traversant, 470 ohm
× 1
potentiomètre multi-tours 500k
× 1
Résistance 10k ohm
× 3

Outils et machines nécessaires

Fer à souder (générique)

Applications et services en ligne

Arduino IDE
Autodesk Eagle

À propos de ce projet

Intro :Station de retouche SMD DIY

Dans ce didacticiel, vous pouvez apprendre à fabriquer un contrôleur de pistolet à air chaud à l'aide d'Arduino et d'autres composants courants. Dans ce projet, l'algorithme PID est utilisé pour calculer la puissance requise et est contrôlé par un pilote Triac isolé.

Ce projet utilise une poignée compatible avec 858D. Il dispose d'un thermocouple de type K, d'un radiateur de 700 watts 230 VAC et d'un ventilateur de 24 VDC.

Ce contrôleur est efficace et fiable par rapport au modèle commercial et est facile à construire.

Étape 1 : câblage

Le schéma complet montré sur l'image ci-dessous.


Câblage pour module LCD I2C :

Module I2C<--------------> Arduino Pro Mini

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

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

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

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

Câblage pour module encodeur rotatif :

Encodeur<----------------------->Arduino

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

+<-------------------------------->NC (non connecté, le code utilise le pull-up d'entrée intégré d'arduino)

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

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

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

Câblage de la poignée : (7 fils)

Connecteur 3 broches - (Vert, Noir, Rouge)

Fil rouge<------------------------>Thermocouple +

Fil vert<-------------------->Reed Switch

Fil noir<---------------------->Masse commune.

Connecteur 2 broches - (Bleu, Jaune)

Fil bleu<---------------------------> Ventilateur +0

Fil jaune<------------------------>Ventilateur - (ou GND)

Connecteur 2 grosses broches -(Blanc, Marron)

Fil blanc<------------------------> Réchauffeur

Fil marron<-----------------------> Réchauffeur (pas de polarité)

REMARQUE :

Le câblage de la poignée du pistolet à air chaud peut être différent pour différents types de lances. Référez-vous donc au schéma de câblage sur la photo et suivez le chemin du fil pour trouver les broches respectives.

Étape 2 : Schéma de circuit

Le circuit se compose principalement de 3 parties.

La partie interface :

Il se compose d'un écran LCD 1602 avec module I2C et d'un encodeur rotatif avec bouton poussoir. L'écran affiche la température réglée, la température actuelle, la vitesse du ventilateur, la puissance appliquée et l'état actuel de la poignée. L'encodeur est utilisé pour diverses entrées et pour naviguer à travers les options et les commandes.

La partie capteur :

Il se compose d'un thermocouple de type K pour la détection de la température et d'un interrupteur à lames pour déterminer la position de la poignée. La tension du thermocouple est amplifiée par l'ampli-op à un niveau de tension mesurable par l'arduino. Le gain de l'ampli-op est contrôlé par un potentiomètre de 200K.

La partie contrôleur :

Il y a principalement 2 contrôleurs dans ce circuit. L'un est un simple contrôleur de vitesse de ventilateur PWM avec un MOSFET. L'autre est un contrôleur isolé pour le chauffage. Il se compose d'un TRIAC entraîné par un DIAC opto-couplé et se fait en contrôlant le nombre de cycles d'onde qui est délivré à l'appareil de chauffage. L'optocoupleur 4N25 aide à maintenir la synchronisation avec la forme d'onde AC.

Étape 3 :PCB

Le circuit de ce projet est un peu compliqué, je vous recommande donc d'utiliser une carte imprimée plutôt qu'un PCB à points. Si vous souhaitez créer votre propre PCB, j'ai joint les fichiers eagle à la fin du projet. Mais, si vous voulez les faire faire par une entreprise de fabrication de PCB, vous pouvez le commander auprès de JLCPCB

. Vous pouvez voir le design Easy EDA via ce lien :https://easyeda.com/ManojBR/harws1-1

Étape 4 :Le code et les bibliothèques

Le programme est la partie la plus cruciale du projet et merci beaucoup pour sfrwmaker écrire le programme. Le programme utilise l'algorithme PID pour contrôler la puissance pour maintenir la température de consigne. Il fonctionne en contrôlant le nombre de cycles d'onde délivrés à la poignée par seconde.

Lorsque le contrôleur est allumé, la baguette sera à l'état OFF. En tournant l'encodeur la température et la vitesse du ventilateur peuvent être ajustées. Appui court de l'encodeur basculera entre la vitesse du ventilateur et le réglage de la température de consigne.

Le pistolet à air chaud commence à chauffer dès qu'il est soulevé du support et affiche Prêt et émet un court bip lorsqu'il atteint la température réglée. Il éteint le chauffage dès qu'il est remis dans le support. Mais, le ventilateur continuera à souffler jusqu'à ce qu'il atteigne la température de sécurité. Une fois que la température descend en dessous de 50 C, il émet un bref bip et affiche COLD.

Lorsque le pistolet à air chaud est éteint, le contrôleur entrera en mode de configuration si l'encodeur est appuyé longuement .

Le mode de configuration propose des options de calibrage, de réglage, d'enregistrement et d'annulation et de réinitialisation de la configuration.

Remarque : Si vous utilisez le PCB de easyEDA alors vous devez changer le numéro de broche du commutateur à lames par le numéro de broche. 8 et Broche du buzzer à la broche n°6

vous devez installer la bibliothèque Commoncontrols-master et la bibliothèque time-master pour que le code fonctionne correctement.

Attention : Ne connectez pas le contrôleur à la prise de courant lors du flashage du micrologiciel. L'alimentation non isolée du ventilateur pourrait endommager votre ordinateur portable.

télécharger le code source de l'esquisse à partir de la page du projet.

Étape 5 :Configuration

Les lectures de température doivent être calibrées avec la valeur d'origine pour obtenir des lectures raisonnables. Donc, pour ce faire, vous devez suivre les étapes suivantes.

Tout d'abord, allez dans le mode de configuration et sélectionnez l'option Tune. Dans le mode de réglage, la température interne (0-1023) s'affiche à l'écran. Tournez l'encodeur pour sélectionner manuellement la puissance appliquée au pistolet à air chaud. Chauffer le pistolet à 400 degrés. Lorsque la température et la dispersion deviennent faibles, le contrôleur émet un bip. Réglez ensuite le potentiomètre pour régler la température interne à environ 900 (dans les unités internes). Appui long sur l'encodeur pour revenir au menu

Ensuite, allez dans le mode de configuration, sélectionnez l'option Calibrer. Choisissez le point d'étalonnage :200, 300 ou 400 degrés, appuyez sur l'encodeur. Le pistolet chaud atteindra la température désirée et émettra un bip. En tournant l'encodeur, entrez la température réelle. Sélectionnez ensuite un autre point de référence et répétez ce processus pour tous les points d'étalonnage.

Après cela, appuyez longuement sur et revenez à l'écran principal, puis à nouveau en mode Configuration et sélectionnez Enregistrer.

Et maintenant, la station de reprise à air chaud est terminée.

Étape 6 : vidéo !

Jetez un œil au fonctionnement du contrôleur dans la vidéo.

Merci à sfrwmaker d'avoir écrit le code.

Merci au LCSC pour son soutien. LCSC Electronics est l'un des fournisseurs de composants électroniques à la croissance la plus rapide en Chine. LCSC s'est engagé à offrir une multitude d'articles authentiques et en stock, depuis sa fondation en 2011. Dans le but de fournir au monde entier des pièces de qualité supérieure en provenance d'Asie. Plus de détails s'il vous plaît visitez:https://lcsc.com/

Si vous devez fabriquer votre propre PCB à la maison, consultez ce tutoriel :https://www.instructables.com/id/PCB-Making-1/

Merci.

Code

  • Firmware 1.4
Firmware 1.4C/C++
Prise en charge du buzzer actif/passif. Veuillez modifier le paramètre BUZZER_ACTIVE
Plus d'encodeur rotatif augmenté. La valeur change de 1.
/* * Contrôleur de pistolet à air chaud basé sur atmega328 IC * Version 1.4 * Publié le 05 décembre 2020 */#include #include #include  #include #include #include #include const uint16_t temp_minC =100 ; // Température minimale que le contrôleur peut vérifier avec précisionconst uint16_t temp_maxC =500; // Température maximale possible const uint16_t temp_ambC =25; // Température ambiante moyenneconst uint16_t temp_tip[3] ={200, 300, 400} ; // Points de référence de température pour l'étalonnageconst uint16_t min_working_fan =100; // Vitesse de ventilateur minimale possibleconst uint8_t AC_SYNC_PIN =2; // Broche de synchronisation de la prise 220 v. Ne changez pas!const uint8_t HOT_GUN_PIN =7; // Gestion du réchauffeur du pistolet chaud pinconst uint8_t FAN_GUN_PIN =9; // Broche de gestion du ventilateur du pistolet chaud. Ne changez pas! const uint8_t TEMP_GUN_PIN =A0; // Vérification de la température du pistolet chaud pinconst uint8_t R_MAIN_PIN =3; // Broche principale de l'encodeur rotatif. Ne changez pas!const uint8_t R_SECD_PIN =4; // Codeur rotatif secondaire pinconst uint8_t R_BUTN_PIN =5; // Bouton de l'encodeur rotatif pinconst uint8_t REED_SW_PIN =8; // Interrupteur Reed pinconst uint8_t BUZZER_PIN =6; // Buzzer pinconst bool BUZZER_ACTIVE =true; // Le buzzer actif émet un bip lorsque le +5v lui est fourni//------------------------------------- ----- Données de configuration -------------------------------------------- -----/* L'enregistrement de configuration dans l'EEPROM a le format suivant :* uint32_t ID à chaque incrément de 1 * struct cfg config data, 8 octets * octet CRC la somme de contrôle*/struct cfg { uint32_t calibration ; // Données d'étalonnage emballées par trois points de température uint16_t temp; // La température préréglée du FER dans les unités internes uint8_t fan; // La vitesse de ventilateur prédéfinie 0 - 255 uint8_t off_timeout ; // Délai d'extinction automatique};class CONFIG { public:CONFIG() { can_write =false; buffRecords =0; rAdr =wAdr =0 ; eLongueur =0 ; nextRecID =0 ; uint8_t rs =sizeof(struct cfg) + 5 ; // La taille totale de l'enregistrement de configuration // Sélectionnez la taille d'enregistrement appropriée ; La taille de l'enregistrement doit être une puissance de 2, c'est-à-dire 8, 16, 32, 64, ... octets pour (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(); // Enregistrer les nouvelles données dans l'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 somme =0 ; for (uint8_t i =0; i <4; ++i) { EEPROM.write(startWrite++, nxt &0xff); somme <<=2; somme +=nxt; nxt>>=8 ; } uint8_t* p =(octet *)&Config; for (uint8_t i =0; i  EEPROM.length()) wAddr =0; nextRecID ++; // Préparez-vous à écrire le prochain enregistrement 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]; for (uint8_t i =0; i =0; --i) { ts <<=8; ts |=Buff[octet(i)] ; } recID =ts; memcpy(&Config, &Buff[4], sizeof(struct cfg)); renvoie vrai ; } return false;}//------------------------------------------ classe CONFIG PISTOLET A CHAUD ----------------------------------------------classe HOTGUN_CFG :public CONFIG { public :HOTGUN_CFG() { } void init(void); uint16_t tempPreset(void); // La température prédéfinie dans les unités internes uint8_t fanPreset(void); // La vitesse de ventilateur prédéfinie 0 - 255 uint16_t tempInternal(uint16_t temp); // Traduire la température lisible par l'homme en valeur interne uint16_t tempHuman(uint16_t temp); // Traduire la température des unités internes en Celsius void save (uint16_t temp, uint8_t fanSpeed); // Enregistrer la température prédéfinie dans les unités internes et la vitesse du ventilateur void applyCalibrationData(uint16_t tip[3]); void getCalibrationData(uint16_t tip[3]); void saveCalibrationData(uint16_t tip[3]); void setDefaults(bool Write); // Définir les valeurs de paramètre par défaut en cas d'échec du chargement des données de l'EEPROM private :uint16_t t_tip[3] ; const uint16_t def_tip[3] ={587, 751, 850} ; // Valeurs par défaut des lectures du capteur interne aux températures de référence const uint16_t min_temp =50 ; const uint16_t max_temp =900 ; const uint16_t def_temp =600 ; // Température prédéfinie par défaut const uint8_t def_fan =64; // Vitesse du ventilateur prédéfinie par défaut 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); // En cas d'échec du chargement des données depuis l'EEPROM, initialisez les données de configuration avec les valeurs par défaut uint32_t cd =Config.calibration; t_tip[0] =cd &0x3FF; cd>>=10 ; // 10 bits par paramètre d'étalonnage, car les lectures ADC sont de 10 bits t_tip[1] =cd &0x3FF; cd>>=10 ; t_tip[2] =cd &0x3FF; // Vérifiez que l'étalonnage de la pointe est correct if ((t_tip[0]>=t_tip[1]) || (t_tip[1]>=t_tip[2])) { setDefaults(false); pour (uint8_t i =0; i <3; ++i) t_tip[i] =def_tip[i] ; } return;} uint32_t calibration; // Données d'étalonnage emballées par trois points de température uint16_t temp; // La température préréglée du FER dans les unités internes uint8_t fan; // La vitesse de ventilateur prédéfinie 0 - 255 uint8_t off_timeout ; // Heure d'arrêt automatiqueoutuint16_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) { // Traduire le température lisible par l'homme dans la valeur interne t =contrainte(t, temp_minC, temp_maxC); uint16_t à gauche =0 ; uint16_t droite =1023 ; // Valeur de température maximale en unités internes uint16_t temp =map(t, temp_tip[0], temp_tip[2], t_tip[0], t_tip[2]); if (temp>
 (gauche+droite)/ 2) { temp -=(droite-gauche) / 4; } else { temp +=(droite-gauche) / 4; } pour (uint8_t i =0; i <20; ++i) { uint16_t tempH =tempHuman(temp); if (tempH ==t) { return temp; } uint16_t new_temp; if (tempH > 1 ; } t_tip[0] =tip[0]; t_tip[1] =astuce[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]; pointe[1] =t_pointe[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 =conseil[2] &0x3FF; cd <<=10; // Pack des données d'étalonnage de pointe dans un mot de 32 bits :10 bits par valeur cd |=tip[1] &0x3FF; cd <<=10; cd |=conseil[0]; Config.calibration =cd; t_tip[0] =astuce[0] ; t_tip[1] =astuce[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 (Ecrire) { CONFIG::save(); }}//------------------------------------------ classe BUZZER -- -------------------------------------------------- --class BUZZER { public:BUZZER(byte buzzerP, bool active =true) { buzzer_pin =buzzerP; this->actif =actif ; } void init(void); void shortBeep(void); void lowBeep(void); void doubleBeep(void); void failedBeep(void); privé :octet buzzer_pin; bool actif;};void BUZZER::init(void) { pinMode(buzzer_pin, OUTPUT); if (actif) { digitalWrite(buzzer_pin, LOW); } else { noTone(buzzer_pin); }}void BUZZER::shortBeep(void) { if (actif) { digitalWrite(buzzer_pin, HIGH); retard (80); digitalWrite(buzzer_pin, LOW); } else { tone(buzzer_pin, 3520, 160); }}void BUZZER::lowBeep(void) { if (actif) { digitalWrite(buzzer_pin, HIGH); retard (160); digitalWrite(buzzer_pin, LOW); } else { tone(buzzer_pin, 880, 160); }}void BUZZER::doubleBeep(void) { if (actif) { digitalWrite(buzzer_pin, HIGH); retard (160); digitalWrite(buzzer_pin, LOW); retard (150); digitalWrite(buzzer_pin, HAUT); retard (160); digitalWrite(buzzer_pin, LOW); } else { tone(buzzer_pin, 3520, 160); retard (300); tonalité (buzzer_pin, 3520, 160); }}void BUZZER::failedBeep(void) { if (actif) { digitalWrite(buzzer_pin, HIGH); retard(170); digitalWrite(buzzer_pin, LOW); retard(10) ; digitalWrite(buzzer_pin, HAUT); retard (80); digitalWrite(buzzer_pin, LOW); retard (100); digitalWrite(buzzer_pin, HAUT); retard (80); digitalWrite(buzzer_pin, LOW); } else { tone(buzzer_pin, 3520, 160); retard(170); tonalité(buzzer_pin, 880, 250); retard (260); tonalité (buzzer_pin, 3520, 160); }}//------------------------------------------- classe lcd DSPLay pour FER à souder -----------------------------classe DSPL :protected LiquidCrystal_I2C { public :DSPL(void) :LiquidCrystal_I2C(0x27, 16, 2) { } void init(void); void clear(void) { LiquidCrystal_I2C::clear(); } void tSet(uint16_t t, bool Celsius =true); // Affiche la température prédéfinie void tCurr(uint16_t t); // Affiche la température actuelle void tInternal(uint16_t t); // Affiche la température actuelle en unités internes void tReal(uint16_t t); // Affiche la température réelle en Celsius en mode de calibrage void fanSpeed(uint8_t s); // Affiche l'annulation de la vitesse du ventilateur appliquéePower(uint8_t p, bool show_zero =true); // Afficher la puissance appliquée (%) void setupMode(uint8_t mode); void msgON(void); // Afficher le message :"ON" void msgOFF(void); void msgReady(void); void msgCold(void); void msgFail(void); // Afficher le message 'Échec' void msgTune(void); // Afficher le message 'Tune' privé :bool full_second_line; // Si la deuxième ligne est pleine avec le message char temp_units; const uint8_t custom_symbols[3][8] ={ { 0b00110, // Degré 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }, { 0b00100, // Signe d'éventail 0b01100, 0b01100, 0b00110, 0b010, 0b10000 , 0b00000 }, { 0b00011, // Signe de puissance 0b00110, 0b01100, 0b11111, 0b00110, 0b01100, 0b01000, 0b10000 } };};void DSPL::init(void) { LiquidCrystal_I2C::begin(); LiquidCrystal_I2C::clear(); pour (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, "Set:%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")); retourner; } 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")); retourner; } 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")); retourner; } LiquidCrystal_I2C::print(buff);}void DSPL::fanSpeed(uint8_t s) { char buff[6]; s =carte(s, 0, 255, 0, 99); sprintf(buff, " %c%2d%c", (char)2, s, '%'); LiquidCrystal_I2C::setCursor(11, 1); LiquidCrystal_I2C::print(buff);}void DSPL::appliedPower(uint8_t p, bool show_zero) { char buff[6]; si (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(mode octet) { LiquidCrystal_I2C::clear(); LiquidCrystal_I2C::print(F("configuration")); LiquidCrystal_I2C::setCursor(1,1); switch (mode) { case 0:// tip calibre LiquidCrystal_I2C::print(F("calibrate")); Pause; case 1 :// régler LiquidCrystal_I2C::print(F("tune")); Pause; case 2 :// sauvegarde LiquidCrystal_I2C::print(F("save")); Pause; case 3 :// annuler LiquidCrystal_I2C::print(F("annuler")); Pause; case 4:// définir les valeurs par défaut LiquidCrystal_I2C::print(F("reset config")); Pause; par défaut :pause ; }}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("Froid"));}void DSPL::msgFail(void) { LiquidCrystal_I2C::setCursor(0, 1); LiquidCrystal_I2C::print(F(" -==Échec ==- "));}void DSPL::msgTune(void) { LiquidCrystal_I2C::setCursor(0, 0); LiquidCrystal_I2C::print(F("Tune"));}//---------------------------------- -------- HISTOIRE de la classe ---------------------------------------- ------------#define H_LENGTH 16class HISTORY { public:HISTORY(void) { len =0; } void init(void) { len =0; } uint16_t last(void); uint16_t top(void) { return queue[0]; } void put (élément uint16_t); // Mettre une nouvelle entrée dans l'historique uint16_t average(void); // calcule la valeur moyenne float dispersion(void); // calcul de la dispersion mathématique private:volatile uint16_t queue[H_LENGTH]; longueur d'octet volatile; // Le nombre d'éléments dans l'index d'octet volatile de la file d'attente ; // La position actuelle de l'élément, utilisez le tampon annulaire};void HISTORY::put(uint16_t item) { if (len =H_LENGTH) index =0 ; // Utiliser le tampon en anneau }}uint16_t HISTORY::last(void) { if (len ==0) return 0; uint8_t i =len - 1 ; si (indice) i =indice - 1 ; return queue[i];}uint16_t HISTORY::average(void) { uint32_t sum =0; if (len ==0) renvoie 0 ; if (len ==1) return queue[0]; for (uint8_t i =0; i > 1; // arrondir la somme moyenne /=len; return uint16_t(sum);}float HISTORY::dispersion(void) { if (len <3) return 1000; uint32_t somme =0 ; uint32_t moy =moyenne(); for (uint8_t i =0; i > 1; mise à jour (valeur); return (emp_data + round_v) / emp_k;}void EMP_AVERAGE::update(int32_t value) { uint8_t round_v =emp_k>> 1; emp_data +=value - (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;}//-------------------------------------- ---- classe PID algorithme pour maintenir la température -----------------------/* L'algorithme PID * Un =Kp*(Xs - Xn) + Ki*somme{j=0; j<=n}(Xs - Xj) + Kd(Xn - Xn-1), * Où Xs - est la température de configuration, Xn - la température à l'étape de n-itération * Dans ce programme, la formule interactive est utilisée :* Un =Un-1 + Kp*(Xn-1 - Xn) + Ki*(Xs - Xn) + Kd*(Xn-2 + Xn - 2*Xn-1) * Au premier pas :* U0 =Kp*( Xs - X0) + Ki*(Xs - X0) ; Xn-1 =Xn ; * * Historique des coefficients PID :* 14/10/2017 [768, 32, 328] * 27/11/2019 [ 2009, 1600, 20] * 27/04/2020 [ 50, 16, 50] */classe PID { public:PID(void) { Kp =50; Ki =16; Kd =50; } void resetPID(int temp =-1); // reset PID algorithm history parameters // Calculate the power to be applied long reqPower(int temp_set, int temp_curr); int changePID(uint8_t p, int k); // set or get (if parameter <0) PID parameter private:void debugPID(int t_set, int t_curr, long kp, long ki, long kd, long delta_p); int temp_h0, temp_h1; // previously measured temperature bool pid_iterate; // Whether the iterative process is used long i_summ; // Ki summary multiplied by denominator long power; // The power iterative multiplied by denominator 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); 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; } break; 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(); } } break; 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

Schémas

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

Processus de fabrication

  1. Affichage à cristaux liquides (LCD)
  2. Créer une thermocam DIY
  3. Station météo Raspberry Pi 2
  4. Station météo Raspberry Pi
  5. Portrait possédé – Mise à jour
  6. Weather Station V 2.0
  7. Boîte UVC d'un stérilisateur UV DIY
  8. Oscilloscope Arduino 20 kHz simple bricolage sur écran LCD Nokia 5110
  9. Animation LCD et jeux