Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

DIY SMD Rework Station

Komponenten und Verbrauchsmaterialien

SparkFun Arduino Pro Mini 328 - 5V/16MHz
× 1
Adafruit Standard LCD - 16x2 Weiß auf Blau
× 1
lcd i2c-Modul
× 1
Drehgeber mit Druckknopf
× 1
Heißluftpistolengriff
× 1
Heißluftpistolen-Griffhalter + Düse
× 1
BTA12-600B
× 1
IRFZ44
× 1
MCP602
× 1
MOC3052
× 1
4N25
× 1
Brückengleichrichter
× 1
Summer
× 1
FR107 schnelle Gleichrichterdiode
× 1
0,01 uF Kondensator, 400V
× 1
Kondensator 100 nF
× 6
Durchgangslochwiderstand, 39 Ohm
× 1
Durchgangslochwiderstand, 33 kOhm
× 2
Widerstand 330 Ohm
× 1
Widerstand 220 Ohm
× 1
Widerstand 1k Ohm
× 3
Durchgangslochwiderstand, 470 Ohm
× 1
500k Multiturn-Potentiometer
× 1
Widerstand 10k Ohm
× 3

Notwendige Werkzeuge und Maschinen

Lötkolben (generisch)

Apps und Onlinedienste

Arduino-IDE
Autodesk Eagle

Über dieses Projekt

Intro:DIY SMD Rework Station

In diesem Tutorial erfahren Sie, wie Sie mit Arduino und anderen gängigen Komponenten eine Heißluftpistolensteuerung herstellen. In diesem Projekt wird der PID-Algorithmus verwendet, um die erforderliche Leistung zu berechnen und wird von einem isolierten Triac-Treiber gesteuert.

Dieses Projekt verwendet einen mit 858D kompatiblen Griff. Es verfügt über ein Thermoelement vom Typ K, eine 700-Watt-230-VAC-Heizung und einen 24-VDC-Lüfter.

Dieser Controller ist im Vergleich zu kommerziellen effizient und zuverlässig und einfach zu bauen.

Schritt 1:Verkabelung

Das vollständige Schema ist auf dem Bild unten gezeigt.


Verkabelung für I2C-LCD-Modul:

I2C-Modul<--------------> Arduino Pro Mini

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

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

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

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

Verkabelung für Drehgebermodul:

Encoder<--------------------------------->Arduino

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

+<-------------------------------->NC (Nicht verbunden, Code verwendet den eingebauten Eingangs-Pull-up von Arduino)

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

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

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

Verkabelung des Griffs: (7-Draht)

3-poliger Stecker - (Grün, Schwarz, Rot)

Rotes Kabel<---------------------------------->Thermoelement +

Grünes Kabel<------------------>Reed-Schalter

Schwarzes Kabel<--------------------->Gemeinsame Masse.

2-poliger Stecker - (Blau, Gelb)

Blaues Kabel<--------------------------> Lüfter +0

Gelbes Kabel<--------------------------------->Lüfter - (oder GND)

2 Big-Pin-Anschluss -(Weiß, Braun)

Weißer Draht<----------------------------------->Heizung

Brauner Draht<----------------------> Heizung (keine Polarität)

HINWEIS:

Die Verdrahtung des Heißluftgebläsegriffs kann für verschiedene Düsentypen unterschiedlich sein. Sehen Sie sich also den Schaltplan auf dem Foto an und folgen Sie dem Kabelverlauf, um die entsprechenden Pins zu finden.

Schritt 2:Schaltplan

Die Schaltung besteht hauptsächlich aus 3 Teilen.

Der Schnittstellenteil:

Es besteht aus einem 1602 LCD-Display mit I2C-Modul und einem Drehgeber mit Drucktaster. Das Display zeigt die eingestellte Temperatur, die aktuelle Temperatur, die Lüftergeschwindigkeit und die angewandte Leistung sowie den aktuellen Status des Griffs an. Der Encoder wird für verschiedene Eingaben und zum Navigieren durch die Optionen und Bedienelemente verwendet.

Der Sensorteil:

Es besteht aus einem Thermoelement Typ K zur Temperaturerfassung und einem Reed-Schalter zur Bestimmung der Griffposition. Die Spannung des Thermoelements wird vom Operationsverstärker auf einen vom Arduino messbaren Spannungspegel verstärkt. Die Verstärkung des Operationsverstärkers wird durch das 200K-Trimmpotentiometer gesteuert.

Der Controller-Teil:

Es gibt hauptsächlich 2 Controller in dieser Schaltung. Das eine ist ein einfacher PWM-Lüftergeschwindigkeitsregler mit einem MOSFET. Der andere ist ein isolierter Regler für die Heizung. Es besteht aus einem TRIAC, der von einem opto-gekoppelten DIAC angetrieben wird, und wird durch die Steuerung der Anzahl der Wellenzyklen durchgeführt, die an das Heizgerät geliefert werden. Der Optokoppler 4N25 hilft, die Synchronisierung mit der AC-Wellenform aufrechtzuerhalten.

Schritt 3:Leiterplatte

Die Schaltung dieses Projekts ist etwas kompliziert, daher empfehle ich Ihnen, eine Leiterplatte als eine Punktplatine zu verwenden. Wenn Sie Ihre eigene Platine erstellen möchten, habe ich die Eagle-Dateien am Ende des Projekts angehängt. Wenn Sie sie jedoch von einem PCB-Herstellungsunternehmen ausführen lassen möchten, können Sie es bei JLCPCB bestellen

. Sie können das Easy EDA-Design über diesen Link anzeigen:https://easyeda.com/ManojBR/harws1-1

Schritt 4:Der Code und die Bibliotheken

Das Programm ist der wichtigste Teil des Projekts und vielen Dank für sfrwmaker das Programm schreiben. Das Programm verwendet den PID-Algorithmus um die Leistung zu regeln, um die eingestellte Temperatur zu halten. Es funktioniert, indem es die Anzahl der Wellenzyklen steuert, die pro Sekunde an den Griff geliefert werden.

Wenn der Controller eingeschaltet ist, befindet sich der Stab im AUS-Zustand. Durch Drehen des Encoders Temperatur und Lüftergeschwindigkeit können eingestellt werden. Kurz drücken des Encoders wechselt zwischen der Lüftergeschwindigkeit und der eingestellten Temperatureinstellung.

Das Heißluftgebläse beginnt zu heizen, sobald es aus der Halterung gehoben wird und zeigt Bereit an und gibt einen kurzen Piepton ab, wenn es die eingestellte Temperatur erreicht hat. Er schaltet die Heizung ab, sobald er wieder in den Halter eingesetzt wird. Der Lüfter bläst jedoch weiter, bis er die sichere Temperatur erreicht hat. Nachdem die Temperatur unter 50 °C gefallen ist, ertönt ein kurzer Piepton und es wird COLD angezeigt.

Wenn die Heißluftpistole ausgeschaltet ist, wechselt die Steuerung in den Setup-Modus wenn der Encoder lang gedrückt wird .

Der Setup-Modus verfügt über die Optionen Kalibrieren, Einstellen, Speichern und Abbrechen und Konfiguration zurücksetzen.

Hinweis: Wenn Sie PCB von easyEDA verwenden dann sollten Sie die Pin-Nummer des Reed-Schalters auf Pin-Nr. 8 und Buzzer-Pin an Pin Nr.6

Sie müssen die Commoncontrols-Master-Bibliothek und die Time-Master-Bibliothek installieren, damit der Code richtig funktioniert.

Achtung: Schließen Sie den Controller beim Flashen der Firmware nicht an die Steckdose an. Eine nicht isolierte Stromversorgung des Lüfters könnte Ihren Laptop beschädigen.

Laden Sie den Sketch-Quellcode von der Projektseite herunter.

Schritt 5:Einrichtung

Die Temperaturmesswerte sollten mit dem Originalwert kalibriert werden, um vernünftige Messwerte zu erhalten. Um dies zu tun, sollten Sie die folgenden Schritte ausführen.

Gehen Sie zuerst in den Setup-Modus und wählen Sie die Tune-Option. Im Tune-Modus wird die interne Temperatur (0-1023) auf dem Bildschirm angezeigt. Drehen Sie den Encoder, um die dem Heißluftgebläse zugeführte Leistung manuell auszuwählen. Erhitzen Sie die Pistole auf 400 Grad. Wenn die Temperatur und die Dispersion niedrig werden, piept der Controller. Stellen Sie dann den Trim-Poti ein, um die Innentemperatur auf etwa 900 (in den Inneneinheiten) einzustellen. Langes Drücken des Encoders, um zum Menü zurückzukehren

Gehen Sie dann in den Setup-Modus und wählen Sie die Option Kalibrieren. Wählen Sie den Kalibrierungspunkt:200, 300 oder 400 Grad, drücken Sie den Encoder. Die Heißluftpistole erreicht die gewünschte Temperatur und piept. Geben Sie durch Drehen des Encoders die tatsächliche Temperatur ein. Wählen Sie dann einen anderen Referenzpunkt und wiederholen Sie diesen Vorgang für alle Kalibrierpunkte.

Nach diesem langen Drücken und zum Hauptbildschirm kommen und dann wieder in den Setup-Modus gehen und Speichern auswählen.

Und jetzt ist die Heißluft-Nacharbeitsstation fertig.

Schritt 6:Video!

Sehen Sie sich die Funktionsweise des Controllers im Video an.

Vielen Dank an sfrwmaker für das Schreiben des Codes.

Danke an LCSC für ihre Unterstützung. LCSC Electronics ist einer der am schnellsten wachsenden Anbieter von elektronischen Komponenten in China. LCSC hat sich seit seiner Gründung im Jahr 2011 dazu verpflichtet, eine Vielzahl von Original- und Lagerartikeln anzubieten. Mit dem Ziel, die ganze Welt mit höherwertigen Teilen aus Asien zu versorgen. Weitere Informationen finden Sie unter:https://lcsc.com/

Wenn Sie zu Hause Ihre eigene Leiterplatte herstellen müssen, lesen Sie dieses Tutorial:https://www.instructables.com/id/PCB-Making-1/

Danke.

Code

  • Firmware 1.4
Firmware 1.4C/C++
Aktive/passive Summerunterstützung. Bitte ändern Sie den Parameter BUZZER_ACTIVE
Kein erhöhter Drehgeber mehr. Wert ändert sich um 1.
/* * Heißluftpistolensteuerung basierend auf atmega328 IC * Version 1.4 * Veröffentlicht am 05.12.2020 */#include #include #include  #include #include #include #include const uint16_t temp_minC =100; // Minimale Temperatur, die der Controller genau überprüfen kannconst uint16_t temp_maxC =500; // Maximal mögliche Temperaturconst uint16_t temp_ambC =25; // Durchschnittliche Umgebungstemperaturconst uint16_t temp_tip[3] ={200, 300, 400}; // Temperaturreferenzpunkte für Calibrationconst uint16_t min_working_fan =100; // Minimal mögliche Lüfterdrehzahlconst uint8_t AC_SYNC_PIN =2; // Ausgang 220 V Synchronisationsstift. Nicht ändern!const uint8_t HOT_GUN_PIN =7; // Heißluftheizungsmanagement Pinconst uint8_t FAN_GUN_PIN =9; // Pin für die Verwaltung des Heißluftgebläses. Ändere dich nicht! const uint8_t TEMP_GUN_PIN =A0; // Temperaturkontrolle der Heißluftpistole Pinconst uint8_t R_MAIN_PIN =3; // Hauptstift des Drehgebers. Nicht ändern!const uint8_t R_SECD_PIN =4; // Sekundärer Drehgeber Pinconst uint8_t R_BUTN_PIN =5; // Drehgebertaste pinconst uint8_t REED_SW_PIN =8; // Reedschalter pinconst uint8_t BUZZER_PIN =6; // Summer pinconst bool BUZZER_ACTIVE =true; // Aktiver Summer piept, wenn +5 V zugeführt werden // --------------------------------- ----- Konfigurationsdaten ------------------------------------------ -----/* Konfigurationsdatensatz im EEPROM hat das folgende Format:* uint32_t ID jedes Mal inkrementiert um 1 * struct cfg Konfigurationsdaten, 8 Byte * Byte CRC die Prüfsumme*/struct cfg { uint32_t Calibration; // Gepackte Kalibrierdaten nach drei Temperaturpunkten uint16_t temp; // Die voreingestellte Temperatur des IRON in internen Einheiten uint8_t fan; // Die voreingestellte Lüftergeschwindigkeit 0 - 255 uint8_t off_timeout; // Automatisches Abschalten Timeout};class CONFIG { public:CONFIG() { can_write =false; buffRecords =0; rAddr =wAddr =0; eLänge =0; nextRecID =0; uint8_t rs =sizeof(struct cfg) + 5; // Die Gesamtgröße des Konfigurationsdatensatzes // Wählen Sie die entsprechende Datensatzgröße aus; Die Datensatzgröße sollte eine Potenz von 2 sein, d. h. 8, 16, 32, 64, ... Bytes für (record_size =8; record_size  recID) { minRecID =recID; minRecAddr =Adresse; } if (maxRecID  eLength) wAddr =0; aufrechtzuerhalten. Sonst { 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); zurück speichern (); // Neue Daten im EEPROM speichern}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 Summe =0; for (uint8_t i =0; i <4; ++i) { EEPROM.write(startWrite++, nxt &0xff); Summe <<=2; Summe +=nxt; nxt>>=8; } uint8_t* p =(Byte *)&Config; for (uint8_t i =0; i  EEPROM.length()) wAddr =0; nextRecID ++; // Bereite dich darauf vor, den nächsten Datensatz zu schreiben 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[byte(i)]; } recID =ts; memcpy(&Config, &Buff[4], sizeof(struct cfg)); true zurückgeben; } false zurückgeben;} //------------------------------------------ Klasse HOT GUN KONFIGURATION ---------------------------------------------- Klasse HOTGUN_CFG:public CONFIG { public:HOTGUN_CFG() {} void init(void); uint16_t tempPreset(void); // Die voreingestellte Temperatur in internen Einheiten uint8_t fanPreset(void); // Die voreingestellte Lüftergeschwindigkeit 0 - 255 uint16_t tempInternal (uint16_t temp); // Übersetze die vom Menschen lesbare Temperatur in einen internen Wert uint16_t tempHuman(uint16_t temp); // Temperatur von internen Einheiten in Celsius umwandeln void save(uint16_t temp, uint8_t fanSpeed); // Speichern Sie die voreingestellte Temperatur in den internen Einheiten und die Lüftergeschwindigkeit void applyCalibrationData(uint16_t tip[3]); void getCalibrationData(uint16_t tip[3]); void saveCalibrationData(uint16_t tip[3]); void setDefaults(bool Schreiben); // Setzen Sie die Standardparameterwerte, wenn das Laden der Daten aus dem privaten EEPROM fehlgeschlagen ist:uint16_t t_tip[3]; const uint16_t def_tip[3] ={587, 751, 850}; // Standardwerte der internen Sensorwerte bei Referenztemperaturen const uint16_t min_temp =50; const uint16_t max_temp =900; const uint16_t def_temp =600; // Voreingestellte Standardtemperatur const uint8_t def_fan =64; // Standardmäßig voreingestellte Lüftergeschwindigkeit 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); // Wenn das Laden der Daten aus dem EEPROM fehlgeschlagen ist, die Konfigurationsdaten mit den Standardwerten initialisieren uint32_t cd =Config.calibration; t_tip[0] =cd &0x3FF; cd>>=10; // 10 Bits pro Kalibrierungsparameter, da die ADC-Messwerte 10 Bits betragen t_tip[1] =cd &0x3FF; cd>>=10; t_tip[2] =cd &0x3FF; // Überprüfen Sie, ob die Spitzenkalibrierung korrekt ist if ((t_tip[0]>=t_tip[1]) || (t_tip[1]>=t_tip[2])) { setDefaults(false); für (uint8_t i =0; i <3; ++i) t_tip[i] =def_tip[i]; } zurück;} uint32_t Kalibrierung; // Gepackte Kalibrierdaten nach drei Temperaturpunkten uint16_t temp; // Die voreingestellte Temperatur des IRON in internen Einheiten uint8_t fan; // Die voreingestellte Lüftergeschwindigkeit 0 - 255 uint8_t off_timeout; // Automatische Abschaltung 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) { // Übersetze die menschlich lesbare Temperatur in internen Wert t =Constraint(t, temp_minC, temp_maxC); uint16_t links =0; uint16_t rechts =1023; // Maximaler Temperaturwert in internen Einheiten uint16_t temp =map(t, temp_tip[0], temp_tip[2], t_tip[0], t_tip[2]); if (temp>
 (links+rechts)/ 2) {temp -=(rechts-links) / 4; aufrechtzuerhalten. Sonst {temp +=(rechts-links) / 4; } for (uint8_t i =0; i <20; ++i) { uint16_t tempH =tempHuman(temp); if (tempH ==t) { Rücklauftemperatur; } 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]; tip[1] =t_tipp[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; // Spitze-Kalibrierungsdaten in ein 32-Bit-Wort packen:10 Bits pro Wert cd |=tip[1] &0x3FF; cd <<=10; cd |=tip[0]; Konfig.Kalibrierung =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; Konfig.Kalibrierung =c; Konfig.temp =def_temp; Konfig.fan =def_fan; if (Schreiben) { CONFIG::save(); }}//------------------------------------------------------ Klasse SUMMER -- -------------------------------------------------- --class BUZZER { public:BUZZER(byte BuzzerP, bool active =true) { Buzzer_pin =BuzzerP; this->active =aktiv; } void init(void); Leere shortBeep(void); void lowBeep(void); void doubleBeep(void); void failedBeep(void); privat:Byte Summer_Pin; bool aktiv;};void BUZZER::init(void) { pinMode(buzzer_pin, OUTPUT); wenn (aktiv) { digitalWrite (summer_pin, LOW); aufrechtzuerhalten. Sonst { noTone (summer_pin); }}void BUZZER::shortBeep (void) { if (active) { digitalWrite (buzzer_pin, HIGH); Verzögerung (80); digitalWrite (summer_pin, LOW); aufrechtzuerhalten. Sonst { Ton (summer_pin, 3520, 160); }}void BUZZER::lowBeep (void) { if (active) { digitalWrite (buzzer_pin, HIGH); Verzögerung(160); digitalWrite (summer_pin, LOW); aufrechtzuerhalten. Sonst { Ton (summer_pin, 880, 160); }}void BUZZER::doubleBeep (void) { if (active) { digitalWrite (buzzer_pin, HIGH); Verzögerung(160); digitalWrite (summer_pin, LOW); Verzögerung (150); digitalWrite (summer_pin, HIGH); Verzögerung(160); digitalWrite (summer_pin, LOW); aufrechtzuerhalten. Sonst { Ton (summer_pin, 3520, 160); Verzögerung (300); Ton (Summer_Pin, 3520, 160); }}void BUZZER::failedBeep (void) { if (active) { digitalWrite (buzzer_pin, HIGH); Verzögerung (170); digitalWrite (summer_pin, LOW); Verzögerung(10); digitalWrite (summer_pin, HIGH); Verzögerung (80); digitalWrite (summer_pin, LOW); Verzögerung (100); digitalWrite (summer_pin, HIGH); Verzögerung (80); digitalWrite (summer_pin, LOW); aufrechtzuerhalten. Sonst { Ton (summer_pin, 3520, 160); Verzögerung (170); Ton (Summer_Pin, 880, 250); Verzögerung (260); Ton (Summer_Pin, 3520, 160); }}//------------------------------------------------------ Klasse lcd DSPLay für Lötkolben ----------------------------------------- Klasse DSPL :protected LiquidCrystal_I2C { public:DSPL(void) :LiquidCrystal_I2C(0x27, 16, 2) {} Leere init (void); Void clear(void) { LiquidCrystal_I2C::clear(); } void tSet(uint16_t t, bool Celsius =true); // Zeigt die voreingestellte Temperatur an void tCurr(uint16_t t); // Zeigt die aktuelle Temperatur an void tInternal(uint16_t t); // Zeigt die aktuelle Temperatur in internen Einheiten an void tReal(uint16_t t); // Zeigt die tatsächliche Temperatur in Celsius im Kalibriermodus an void fanSpeed ​​(uint8_t s); // Zeigt die Lüftergeschwindigkeit an void applyPower(uint8_t p, bool show_zero =true); // Zeigt die angelegte Leistung (%) an void setupMode (uint8_t mode); Leere msgON(void); // Nachricht anzeigen:"ON" void msgOFF(void); Leere msgReady(void); Leere msgCold(void); ungültige msgFail (ungültig); // 'Fehler'-Meldung anzeigen void msgTune(void); // 'Tune'-Nachricht anzeigen privat:bool full_second_line; // Ob die zweite Zeile mit der Meldung voll ist char temp_units; const uint8_t custom_symbols[3][8] ={ { 0b00110, // Grad 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }, { 0b00100, // Fächerzeichen 0b01100, 0b01100, 0b00110, 0b01011, 0b00011001, 00 , 0b00000 }, { 0b00011, // Potenzzeichen 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 =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")); Rückkehr; } 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")); Rückkehr; } 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")); Rückkehr; } LiquidCrystal_I2C::print(buff);}void DSPL::fanSpeed(uint8_t s) { char buff[6]; s =Karte(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]; wenn (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 (Byte-Modus) { LiquidCrystal_I2C::clear(); LiquidCrystal_I2C::print(F("Setup")); LiquidCrystal_I2C::setCursor(1,1); Schalter (Modus) { Fall 0:// Spitze kalibrieren LiquidCrystal_I2C::print (F ("kalibrieren")); brechen; Fall 1:// LiquidCrystal_I2C::print(F("tune") optimieren); brechen; Fall 2:// LiquidCrystal_I2C speichern::print(F("save")); brechen; Fall 3:// LiquidCrystal_I2C::print(F("cancel") abbrechen); brechen; Fall 4:// Standardwerte setzen LiquidCrystal_I2C::print(F("reset config")); brechen; Vorgabe: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(" Cold"));}void DSPL::msgFail(void) { LiquidCrystal_I2C::setCursor(0, 1); LiquidCrystal_I2C::print(F(" -==Fehlgeschlagen ==- "));}void DSPL::msgTune(void) { LiquidCrystal_I2C::setCursor(0, 0); LiquidCrystal_I2C::print(F("Tune"));}//--------------------------------- -------- GESCHICHTE der Klasse ---------------------------------------- ------------#define H_LENGTH 16class HISTORY { public:HISTORY(void) { len =0; aufrechtzuerhalten. Void init (void) { len =0; } uint16_t last(void); uint16_t top(void) { return queue[0]; } void put(uint16_t item); // Neuen Eintrag in die Historie einfügen uint16_t Average(void); // den Durchschnittswert berechnen Float Dispersion (void); // Berechnung der mathematischen Streuung private:volatile uint16_t queue[H_LENGTH]; flüchtiges Byte len; // Die Anzahl der Elemente im volatilen Byte-Index der Warteschlange; // Die aktuelle Elementposition, Ringpuffer verwenden};void HISTORY::put(uint16_t item) { if (len =H_LENGTH) index =0; // Ringpuffer verwenden}}uint16_t HISTORY::last(void) { if (len ==0) return 0; uint8_t i =len - 1; if (Index) i =Index – 1; Return Queue[i];}uint16_t HISTORY::average(void) { uint32_t Summe =0; if (len ==0) Rückgabe 0; if (len ==1) return queue[0]; for (uint8_t i =0; i > 1; // runde die durchschnittliche Summe /=len; return uint16_t(sum);}float HISTORY::dispersion(void) { if (len <3) return 1000; uint32_t Summe =0; uint32_t avg =Durchschnitt(); for (uint8_t i =0; i > 1; update(Wert); return (emp_data + round_v) / emp_k;}void EMP_AVERAGE::update(int32_t value) { uint8_t round_v =emp_k>> 1; emp_data +=Wert - (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;}//---------------------------------------- ---- Klasse PID-Algorithmus zum Halten der Temperatur -----------------------------------/* Der PID-Algorithmus * Un =Kp*(Xs - Xn) + Ki*summ{j=0; j<=n}(Xs - Xj) + Kd(Xn - Xn-1), * Wobei Xs - die Einstelltemperatur ist, Xn - die Temperatur im n-Iterationsschritt * In diesem Programm wird die interaktive Formel verwendet:* Un =Un-1 + Kp*(Xn-1 - Xn) + Ki*(Xs - Xn) + Kd*(Xn-2 + Xn - 2*Xn-1) * Mit dem ersten Schritt:* U0 =Kp*( Xs – X0) + Ki*(Xs – X0); Xn-1 =Xn; * * Historie der PID-Koeffizienten:* 14.10.2017 [768, 32, 328] * 27.11.2019 [ 2009, 1600, 20] * 27.04.2020 [ 50, 16, 50] */Klasse 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

Schaltpläne

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

Herstellungsprozess

  1. Liquid Crystal Display (LCD)
  2. Bauen Sie eine DIY-Thermocam
  3. Raspberry Pi 2 Wetterstation
  4. Raspberry Pi Wetterstation
  5. Besessenes Porträt – Aktualisiertes
  6. Wetterstation V 2.0
  7. UVC-Box einen DIY-UV-Sterilisator
  8. DIY Einfaches 20-kHz-Arduino-Oszilloskop auf Nokia 5110 LCD
  9. LCD-Animation und -Spiele
  10. DIY 10Hz-50kHz Oszilloskop auf 128x64 LCD-Display