Sari la conținut

Tabel Lideri

Conținut Popular

Afișez conținut cu cea mai mare reputație pe 01.08.2020 în toate secțiunile

  1. Mi-am dorit de multă vreme să construiesc o stație de lipit care să folosească curentul alternativ ca și sursă de curent pentru alimentarea rezistenței letconului. Inițial am construit proiectul acesta: https://www.allaboutcircuits.com/projects/do-it-yourself-soldering-station-with-an-atmega8/?utm_source=eetech&utm_medium=eetech-social&utm_campaign=reposts-projects/ căruia i-am adăugat o protecție la supratemepratură. Apoi am realizat proiectul acesta: https://www.instructables.com/id/DIY-Arduino-Soldering-Station/ Cu ajutor la scrierea programului, am realizat proiectul din această schemă: Explicațiile pentru schemă sunt: SV3 - avem conectați doar pinii A2 și A3 (veți vedea în program pentru că sunt folosiți la testare), SV1 - aici avem conectat un modul cu MAX6675 și SV2 - aici am conectat un LCD 1602, pe care se va afișa conform cu programul: temperatura setată din potențiometrul R7, temperatura aproximată a vârfului și [temperatura] citită de către MAX6675. OK1 generează câte un impuls pentru fiecare trecere prin 0 a tensiunii alternative, K1 este un releu care oprește alimentarea rezistenței în momentul în care este depășită temperatura de 432 C sau atunci când este decuplat unul sau ambele fire de la termocuplu, partea de alimentare este formată din LM317 și L7805, iar elementul de forță este alcătuit din triacul BT138, care este controlat de pinul 7 al lui Arduino Nano V3. Pentru controlul temperaturii, am folosit un controller de tip PID, prin utilizarea în mediul Arduino IDE a librăriei <PID_v1.h>. La prima vedere, controlerul pare să funcționeze. Programul implementat este: #include <PID_v1.h> #include <LiquidCrystal.h> #include <SPI.h> #include <Wire.h> #include <max6675.h> #define thermoDO 12 #define thermoCS 10 #define thermoCLK 13 #define potentiometer A0 #define zerocrossing 2 #define triac 7 #define relay A1 #define test A2 #define test1 A3 int lowError = 0; //guessing for now. The bigger these values the smaller the deadband either side of 0 error that constitues a 50% duty cycle int highError = 220; float temperature, realTemperature; int pottemperature; int counter; int tempError = false; // global error flag int shownError = false; //flag to say error shown int duty = 0; // variable for duty cycle //PID constants //double Kp = 5; //double Ki = 0.25; //double Kd = 0; //Define the aggressive and conservative Tuning Parameters double aggKp = 4, aggKi = 0.2, aggKd = 1; double consKp = 1, consKi = 0.05, consKd = 0.25; //PID variables unsigned long currentTime, previousTime; double elapsedTime; double error; double lastError; double input, output, setPoint; double cumError, rateError; PID myPID(&input, &output, &setPoint, consKp, consKi, consKd, DIRECT); byte thermometer[8] = //icon for termometer { B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110 }; byte arrow[8] = //icon for arrow { B11000, B01100, B00110, B00011, B00011, B00110, B01100, B11000 }; MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); /* The circuit: LCD RS pin to digital pin 12 LCD Enable pin to digital pin 11 LCD D4 pin to digital pin 5 LCD D5 pin to digital pin 4 LCD D6 pin to digital pin 3 LCD D7 pin to digital pin 2 LCD R/W pin to ground LCD VSS pin to ground LCD VCC pin to 5V 10K resistor: ends to +5V and ground wiper to LCD VO pin (pin 3) */ LiquidCrystal lcd(3, 4, 5, 6, 8, 9); // added stuff to log temperatures on serial monitor // change loop time management from simple delay #define PRINTRATE 100 #define DISPLAYRATE 250 char textbuf[100]; //buffer for data to send unsigned long serialTime = millis(); //sending interval for data unsigned long displayTime = serialTime; //display interval for LCD int pt; //local store for pot and iron temperatures; int tmp; double err, cErr, rErr, op; int dty; void setup() { myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, 220); Serial.begin(115200); // or faster if your Arduino/PC can handle it... pinMode(test, OUTPUT); pinMode(test1, OUTPUT); lcd.createChar(0, thermometer); lcd.createChar(1, arrow); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("STATIE DE LIPIT"); output = 0; setPoint = 0; delay(1200); lcd.clear(); pinMode(relay, OUTPUT); pinMode(potentiometer, INPUT); pinMode(zerocrossing, INPUT_PULLUP); pinMode(triac, OUTPUT); digitalWrite(triac, LOW); digitalWrite(relay, HIGH); realTemperature = thermocouple.readCelsius(); temperature = 0.779828 * realTemperature - 10.3427; input = temperature; //updateDisplay(); attachInterrupt(digitalPinToInterrupt(2), zero, RISING); } void loop() { if (millis() > serialTime + PRINTRATE) { //send serial data every PRINTRATE mS noInterrupts(); // make sure our local copies are not corrupted while copying them over from ISR tmp = temperature; pt = pottemperature; err = error; cErr = cumError; rErr = rateError; op = output; dty = duty; interrupts(); sprintf(textbuf, "Time: %lu, Set: %4u, Temp: %4u", millis() / 100, pt, tmp); //format the print string Serial.print(textbuf); sprintf(textbuf, ", error: %.9g, cumErr: %.9g, rateErr: %.9g, output: %.9g, duty: %3u", err, cErr, rErr, op, dty); Serial.println(textbuf); //send to serial monitor, about 3mS @ 115200 serialTime += PRINTRATE; } if (millis() > displayTime + DISPLAYRATE) { //update display every DISPLAYRATE mS if (!tempError) { // if no error updateDisplay(); } else // do something on error { // eg show the word error on the display if (!shownError) { // we've not shown error yet, so show it displayErrors(); shownError = true; //set flag so don't show it again } } displayTime += DISPLAYRATE; } } void zero() { counter++; //*** change this line below if (counter > duty) { //reach duty cycle limit, unless duty was 25 in which case leave on until next duty calculated later digitalWrite(triac, LOW); } if (counter >= 25) { counter = 0; digitalWrite(test, HIGH); //this will generate a pulse on test pin (5) every 250mS to prove counter incrementing... pottemperature = analogRead(potentiometer); pottemperature = map(pottemperature, 0, 1023, 150, 400); setPoint = pottemperature; digitalWrite(test, LOW); // put test pin low realTemperature = thermocouple.readCelsius(); temperature = int(0.779828 * realTemperature - 10.3427); // make temperature an integer input = temperature; if (tempError || isnan(realTemperature) || temperature >= 432) { // on error kill power & set global error flag digitalWrite(relay, LOW); // turn off power to iron //*** add this line below just in case digitalWrite(triac, LOW); tempError = true; //set error flag. can only be unset outside ISR. Once set no further action taken till unset in main loop. } else { //reading valid //*** if (temperature < pottemperature) { //*** remove this line and allow errors to be both + and - digitalWrite(test1, HIGH); // *** changed, generate a pulse on test1 (D6) when reading valid //error = pottemperature - temperature; // *** +ve error when low = increase duty cycle, -ve error when high = decrease it double gap = abs(setPoint - input); //distance away from setpoint if (gap < 10) { //we're close to setpoint, use conservative tuning parameters myPID.SetTunings(consKp, consKi, consKd); } else { //we're far from setpoint, use aggressive tuning parameters myPID.SetTunings(aggKp, aggKi, aggKd); } myPID.Compute(); // error = map(error, lowError, highError, 0, 24); // cumError += error * 250.0; // // rateError = (error - lastError) / 250.0; // // output = Kp * error + Ki * cumError + Kd * rateError; //output error needs to be mapped to a number between 0 and 24 duty = map(output, lowError, highError, 0, 25); // *** lowError is const for fully off, highError is const for fully on. zero error maps to 50% duty = constrain(duty, 0, 25); // ***keep duty between 0 and 25 (25 = 100%) //*** re-arrange & add 3 lines if (duty > 0) { digitalWrite(triac, HIGH); } else { digitalWrite(triac, LOW); } lastError = error; digitalWrite(test1, LOW); //*** remove 3 lines // } // else { // duty = 0; // }//if (temperature }//if (tempError } //if(counter >= 25 }// zero() void updateDisplay() { pottemperature = analogRead(potentiometer); pottemperature = map(pottemperature, 0, 1023, 150, 400); lcd.clear(); lcd.setCursor(0, 0); lcd.write((byte)0); lcd.setCursor(2, 0); lcd.print((int)pottemperature); lcd.setCursor(6, 0); lcd.print((char)223); //degree sign lcd.setCursor(7, 0); lcd.print("C"); lcd.setCursor(0, 1); lcd.write((byte)1); if (temperature <= 45) { lcd.setCursor(2, 1); lcd.print("Lo"); } else { lcd.setCursor(2, 1); lcd.print((int)temperature); } lcd.setCursor(6, 1); lcd.print("["); lcd.setCursor(7, 1); lcd.print((int)realTemperature); lcd.setCursor(10, 1); lcd.print("]"); lcd.setCursor(12, 1); lcd.print((char)223); lcd.setCursor(13, 1); lcd.print("C"); } void displayErrors() { digitalWrite(relay, LOW); // the relay will disconnect the power to the soldering iron heating element lcd.clear(); lcd.setCursor(0, 0); lcd.write((byte)0); lcd.setCursor(1, 0); lcd.write((byte)0); lcd.setCursor(5, 0); lcd.print("ERROR!"); lcd.setCursor(14, 0); lcd.write((byte)0); lcd.setCursor(15, 0); lcd.write((byte)0); } Am 2 întrebări în ceea ce privește programul (codul) implementat: 1. Observ pe osciloscop că tranziția de la 0 logic la 1 logic (0V - 5V) de pe pinul 7 (albastru pe imagine) al lui Arduino, se face cu o întârziere de aproximativ 1 mS față de impulsul care il primește pe pinul 2 (galben pe imagine). În ce măsură afectează această întârziere funcționarea circuitului ? În timp ce tranziția de la 1 la 0 se face la momentul potrivit: Pe rezistența letconului: 2. Ce parere aveti despre cod ? Eu am adăugat numai partea cu implementarea PID-ului. Acesta este rezultatul (albastru = setpoint și roșu = temperatura letconului): Vă mulțumesc pentru eventualele sfaturi/observații/comentarii. 😀 Urmează și partea cu realizarea practică a stației, dar mai întâi aș dori să rezolv problemele prezentate. Dacă există informații neclare sau incomplete, vă rog să îmi spuneți și voi încerca să clarific.
    1 punct
Acest tabel lideri este setat pe București/GMT+03:00
×
×
  • Creează nouă...

Informații Importante

Folosim cookie-uri și tehnologii asemănătoare pentru a-ți îmbunătăți experiența pe acest website, pentru a-ți oferi conținut și reclame personalizate și pentru a analiza traficul și audiența website-ului. Înainte de a continua navigarea pe www.tehnium-azi.ro te rugăm să fii de acord cu: Termeni de Utilizare.