Serwisy partnerskie:
Close icon
Serwisy partnerskie

Mini sterownik rozpływu z wyświetlaczem LCD

Article Image
Elmax
Piece rozpływowe są ważnym urządzeniem w technologii wytwarzania płytek PCB z zastosowaniem elementów do montażu powierzchniowego. Dla zapewnienia odpowiednich warunków cieplnych w procesie lutowania elementów SMD stosuje się sterowniki pieców rozpływowych. W tym artykule przedstawimy pierwszą wersję mini sterownika pieca rozpływowego Rocket Stream v1, który jest prawdopodobnie najlepiej przetestowanym sterownikiem pieca rozpływowego DIY w Internecie, ponieważ jest on używany przez firmę Rocket Stream do produkcji ich płytek.

Rocket Stream's Reflow Oven Controller v1 jest zasilany przez ATtiny1634R i wykorzystuje najnowszy interfejs czujnika termopary IC MAX31856 firmy Maxim. Jest to jeden z najtańszych projektów w Internecie, ponieważ Rocket Stream był w stanie obniżyć całkowity koszt projektu, nie używając płytki rozwojowej takiej jak Arduino i używając jak najwięcej elementów SMD w miejsce elementów przewlekanych, aby zredukować czas i nakład pracy, pozostawiając tylko blok zacisków i złącze LCD jako jedyne elementy przewlekane.

ATtiny1634R jest jednym z nowych ATtiny. Jest to 8-bitowy mikrokontroler AVR® o wysokiej wydajności i niskim poborze mocy, z zaawansowaną architekturą RISC, 16 kilobajtami wbudowanej, samo-programowalnej pamięci Flash oraz 256 bajtami wbudowanej, programowalnej pamięci EEPROM z obsługą do 100 000 cykli zapisu i kasowania. Układ jest programowalny przez port SPI i może być programowany za pomocą Arduino IDE.

Inne zaangażowane komponenty obejmują zewnętrzny przekaźnik półprzewodnikowy (SSR), który powinien być dostosowany do poboru prądu przez piec (grzałkę) oraz termoparę typu K, która zapewnia informację zwrotną o temperaturze do sterownika i wyświetlacza LCD, na którym wyświetlane są informacje/status systemu.

Główne komponenty wymagane do budowy sterownika to:

  • ATtiny1634R
  • Interfejs termopary MAX31856
  • Termopara typu K (Rocket stream zaleca te z włóknem szklanym lub stalowym płaszczem)
  • 8×2 LCD czarne znaki z żółtym podświetleniem
  • 2 przyciski
  • 1 czerwona dioda LED
  • 2 bloki zacisków
  • 1 tranzystor
  • 1 brzęczyk

Kompletna lista elementów jest zdecydowanie dłuższa i podamy ją w poniższej tabeli:

Wykaz elementów
Ilość
Symbol
Nazwa/opis/gdzie kupić
2
C1, C2
10nF 805
5
C3, C6, C7, C8, C9
100nF 805
2
C4, C5
1uF 16V X7R
3
C10, C11, C12
10uF 10V X5R
1
D1
Red
2
Q1, Q2
2N3904
2
R2, R3
100R
4
R4, R5, R9, R10
10k
1
R6
2K2
1
R7
27K
1
R8
53K6
2
SW1, SW2
IT-1109S
1
SW3
TS-018

Schematy

 Schemat Tiny Reflow Controller v1

Schemat i wynikowa płytka PCB zostały opracowane w programie KICAD, a pliki są załączone w pliku zip w sekcji download. Możesz edytować projekt, aby dokonać dowolnych modyfikacji lub po prostu użyć plików Gerber, które zostały już wygenerowane, aby wyprodukować własną płytkę PCB. Obraz mini sterownika pieca rozpływowego jest pokazany poniżej.

 Płytka dolna mini sterownika pieca rozpływowego v1 (bez LCD)

Kod

Do opracowania kodu dzisiejszego projektu użyjemy Arduino IDE, w związku z tym będziesz musiał zainstalować pliki wspierające płytkę Arduino IDE dla mikrokontrolera ATTINY1634R, aby można go było zaprogramować za pomocą Arduino IDE.

Szkic dla tego projektu jest oparty na przykładowym kodzie dostarczonym przez Rocket Stream. Steruje on procesem rozpływu za pomocą algorytmu sterowania PID, który jest oparty na wspaniałej bibliotece Arduino PID napisanej przez Bretta Beauregarda. Szkic po prostu ocenia aktualny poziom ciepła, porównuje go z wartością, jaka powinna być na danym etapie rozpływu i reguluje się przy użyciu algorytmów PID, aby zapewnić, że jest on zgodny z oczekiwaniami.

Poza biblioteką PID, inne biblioteki użyte w projekcie to: Liquid Crystal Library, która została użyta do interfejsu z LCD, biblioteka Adafruit Max31856, która została użyta do interfejsu z termoparą, oraz biblioteka Arduino EEPROM, która została użyta do zarządzania przechowywaniem i ekstrakcją danych na EEPROM. Podczas gdy biblioteka EEPROM jest dostarczana z Arduino IDE, pozostałe biblioteki można zainstalować za pomocą menedżera bibliotek Arduino. Przykładowy kod, z którym będziemy pracować, uwzględnia zarówno ołowiowe jak i bezołowiowe konfiguracje pieca rozpływowego, pozwalając użytkownikowi na zmianę z jednej na drugą za pomocą przycisku.

Szkic rozpoczynamy od dołączenia wszystkich bibliotek, z których będziemy korzystać, po czym tworzymy definicję typu, który przechowuje kilka parametrów wskazujących na stan procesu rozpływu.

// ***** INCLUDES *****
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <Adafruit_MAX31856.h>
#include <PID_v1.h>

// ***** TYPE DEFINITIONS *****
typedef enum REFLOW_STATE
{
  REFLOW_STATE_IDLE,
  REFLOW_STATE_PREHEAT,
  REFLOW_STATE_SOAK,
  REFLOW_STATE_REFLOW,
  REFLOW_STATE_COOL,
  REFLOW_STATE_COMPLETE,
  REFLOW_STATE_TOO_HOT,
  REFLOW_STATE_ERROR
} reflowState_t;

Tworzymy także inne deklaracje typów, aby przechowywać status reflow, status przełącznika, stan odbicia i Reflow_Profile w oparciu o status przełącznika.

typedef enum REFLOW_STATUS
{
  REFLOW_STATUS_OFF,
  REFLOW_STATUS_ON
} reflowStatus_t;

typedef  enum SWITCH
{
  SWITCH_NONE,
  SWITCH_1,
  SWITCH_2
}  switch_t;

typedef enum DEBOUNCE_STATE
{
  DEBOUNCE_STATE_IDLE,
  DEBOUNCE_STATE_CHECK,
  DEBOUNCE_STATE_RELEASE
} debounceState_t;

typedef enum REFLOW_PROFILE
{
  REFLOW_PROFILE_LEADFREE,
  REFLOW_PROFILE_LEADED
} reflowProfile_t;

Następnie tworzymy zmienne przechowujące stałe wartości, które będą używane niezależnie od wybranego profilu (General Profile constant), a po nich tworzymy zmienne przechowujące wartości specyficzne dla profilu bezołowiowego i tworzymy również te specyficzne dla profilu ołowiowego. W ten sposób zapewniamy, że niezależnie od wybranego przez użytkownika profilu, niezbędne informacje będą dostępne.

// ***** CONSTANTS *****
// ***** GENERAL PROFILE CONSTANTS *****
#define PROFILE_TYPE_ADDRESS 0
#define TEMPERATURE_ROOM 50
#define TEMPERATURE_SOAK_MIN 150
#define TEMPERATURE_COOL_MIN 100
#define SENSOR_SAMPLING_TIME 1000
#define SOAK_TEMPERATURE_STEP 5

// ***** LEAD FREE PROFILE CONSTANTS *****
#define TEMPERATURE_SOAK_MAX_LF 200
#define TEMPERATURE_REFLOW_MAX_LF 250
#define SOAK_MICRO_PERIOD_LF 9000

// ***** LEADED PROFILE CONSTANTS *****
#define TEMPERATURE_SOAK_MAX_PB 180
#define TEMPERATURE_REFLOW_MAX_PB 224
#define SOAK_MICRO_PERIOD_PB 10000

Następnie tworzymy zmienne, które będą używane przez algorytm PID, potem komunikaty LCD i kilka innych zmiennych. Nazwy są bardzo opisowe więc powinno być łatwo je śledzić.

// ***** PID PARAMETERS *****
// ***** PRE-HEAT STAGE *****
#define PID_KP_PREHEAT 100
#define PID_KI_PREHEAT 0.025
#define PID_KD_PREHEAT 20
// ***** SOAKING STAGE *****
#define PID_KP_SOAK 300
#define PID_KI_SOAK 0.05
#define PID_KD_SOAK 250
// ***** REFLOW STAGE *****
#define PID_KP_REFLOW 300
#define PID_KI_REFLOW 0.05
#define PID_KD_REFLOW 350
#define PID_SAMPLE_TIME 1000

// ***** LCD MESSAGES *****
const char* lcdMessagesReflowStatus[] = {
  "Ready",
  "Pre",
  "Soak",
  "Reflow",
  "Cool",
  "Done!",
  "Hot!",
  "Error"
};

// ***** DEGREE SYMBOL FOR LCD *****
unsigned char degree[8]  = {
  140, 146, 146, 140, 128, 128, 128, 128
};

// ***** PIN ASSIGNMENT *****
int ssrPin = 3;
int thermocoupleCSPin = 2;
int lcdRsPin = 10;
int lcdEPin = 9;
int lcdD4Pin = 8;
int lcdD5Pin = 7;
int lcdD6Pin = 6;
int lcdD7Pin = 5;
int buzzerPin = 14;
int switchPin = A1;

// ***** PID CONTROL VARIABLES *****
double setpoint;
double input;
double output;
double kp = PID_KP_PREHEAT;
double ki = PID_KI_PREHEAT;
double kd = PID_KD_PREHEAT;
int windowSize;
unsigned long windowStartTime;
unsigned long nextCheck;
unsigned long nextRead;
unsigned long updateLcd;
unsigned long timerSoak;
unsigned long buzzerPeriod;
unsigned char soakTemperatureMax;
unsigned char reflowTemperatureMax;
unsigned long soakMicroPeriod;
// Reflow oven controller state machine state variable
reflowState_t reflowState;
// Reflow oven controller status
reflowStatus_t reflowStatus;
// Reflow profile type
reflowProfile_t reflowProfile;
// Switch debounce state machine state variable
debounceState_t debounceState;
// Switch debounce timer
long lastDebounceTime;
// Switch press status
switch_t switchStatus;
switch_t switchValue;
switch_t switchMask;
// Seconds timer
int timerSeconds;
// Thermocouple fault status
unsigned char fault;

Po utworzeniu wszystkich zmiennych, tworzymy instancję bibliotek PID, LiquidCrystal oraz MAX31856, po czym przechodzimy do funkcji void setup().

// PID control interface
PID reflowOvenPID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
// LCD interface
LiquidCrystal lcd(lcdRsPin, lcdEPin, lcdD4Pin, lcdD5Pin, lcdD6Pin, lcdD7Pin);
// MAX31856 thermocouple interface
Adafruit_MAX31856 thermocouple = Adafruit_MAX31856(thermocoupleCSPin);

Funkcję void setup() rozpoczynamy od sprawdzenia aktualnie wybranego profilu rozpływu w pamięci EEPROM, co pomaga określić, która z grup zmiennych powinna być wybrana. Jeśli żaden profil rozpływu nie był wcześniej zapisany, system wybiera domyślnie profil Leadfree.

void setup()
{
  // Check current selected reflow profile
  unsigned char value = EEPROM.read(PROFILE_TYPE_ADDRESS);
  if ((value == 0) || (value == 1))
  {
    // Valid reflow profile value
    reflowProfile = value;
  }
  else
  {
    // Default to lead-free profile
    EEPROM.write(PROFILE_TYPE_ADDRESS, 0);
    reflowProfile = REFLOW_PROFILE_LEADFREE;
  }

Następnie inicjalizujemy pin SSR, aby upewnić się, że piec rozpływowy jest otwarty, po czym inicjalizujemy brzęczyk, ustawiając go tak, aby włączał się natychmiast po włączeniu zasilania systemu.

// SSR pin initialization to ensure reflow oven is off
  digitalWrite(ssrPin, LOW);
  pinMode(ssrPin, OUTPUT);

  // Buzzer pin initialization to ensure annoying buzzer is off
  digitalWrite(buzzerPin, LOW);
  pinMode(buzzerPin, OUTPUT);

  // LED pins initialization and turn on upon start-up (active high)
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);

Inicjalizujemy również termoparę, podając jej typ, a także inicjalizujemy LCD i wyświetlamy coś w rodzaju splash screen'a z datą i wersją kontrolera.

// Initialize thermocouple interface
  thermocouple.begin();
  thermocouple.setThermocoupleType(MAX31856_TCTYPE_K);

  // Start-up splash
  digitalWrite(buzzerPin, HIGH);
  lcd.begin(8, 2);
  lcd.createChar(0, degree);
  lcd.clear();
  lcd.print(" Tiny  ");
  lcd.setCursor(0, 1);
  lcd.print(" Reflow ");
  digitalWrite(buzzerPin, LOW);
  delay(2000);
  lcd.clear();
  lcd.print(" v1.00  ");
  lcd.setCursor(0, 1);
  lcd.print("26-07-17");
  delay(2000);
  lcd.clear();

Następnie inicjalizujemy komunikację szeregową, wyłączamy diodę stanu LED  oraz inicjalizujemy zmienne, których będziemy używać do monitorowania czasu podczas działania szkicu.

// Serial communication at 115200 bps
  Serial.begin(115200);

  // Turn off LED (active high)
  digitalWrite(LED_BUILTIN, LOW);
  // Set window size
  windowSize = 2000;
  // Initialize time keeping variable
  nextCheck = millis();
  // Initialize thermocouple reading variable
  nextRead = millis();
  // Initialize LCD update timer
  updateLcd = millis();
}

Po wykonaniu tych czynności przechodzimy do funkcji void loop(), w której odbywają się wszystkie najważniejsze akcje.

Kod funkcji void loop() jest dość obszerny, ale idea jest prosta. Używamy zmiennych utworzonych wcześniej do śledzenia czasu do zarządzania procesem rozpływu, monitorując ilość ciepła za pomocą termostatu i używając tej informacji jako wejścia do algorytmu PID, który następnie określa sposób działania grzałki. Dla każdego etapu procesu rozpływu, PID działa w taki sposób, że wyznaczona ilość ciepła dla tego etapu jest osiągnięta. Podczas gdy to wszystko się dzieje, informacje o czasie i temperaturze są również wyświetlane na ekranie, aby zapewnić wizualną informację zwrotną dla użytkownika, a przełączniki, które są używane do ustawiania statusu rozpływu i profilu rozpływu są również obserwowane, aby system mógł natychmiast działać na każdą zmianę ich stanu.

void loop()
{
  // Current time
  unsigned long now;

  // Time to read thermocouple?
  if (millis() > nextRead)
  {
    // Read thermocouple next sampling period
    nextRead += SENSOR_SAMPLING_TIME;
    // Read current temperature
    input = thermocouple.readThermocoupleTemperature();
    // Check for thermocouple fault
    fault = thermocouple.readFault();

    // If any thermocouple fault is detected
    if ((fault & MAX31856_FAULT_CJRANGE) ||
        (fault & MAX31856_FAULT_TCRANGE) ||
        (fault & MAX31856_FAULT_CJHIGH) ||
        (fault & MAX31856_FAULT_CJLOW) ||
        (fault & MAX31856_FAULT_TCHIGH) ||
        (fault & MAX31856_FAULT_TCLOW) ||
        (fault & MAX31856_FAULT_OVUV) ||
        (fault & MAX31856_FAULT_OPEN))
    {
      // Illegal operation
      reflowState = REFLOW_STATE_ERROR;
      reflowStatus = REFLOW_STATUS_OFF;
    }
  }

  if (millis() > nextCheck)
  {
    // Check input in the next seconds
    nextCheck += 1000;
    // If reflow process is on going
    if (reflowStatus == REFLOW_STATUS_ON)
    {
      // Toggle red LED as system heart beat
      digitalWrite(LED_BUILTIN, !(digitalRead(LED_BUILTIN)));
      // Increase seconds timer for reflow curve analysis
      timerSeconds++;
      // Send temperature and time stamp to serial
      Serial.print(timerSeconds);
      Serial.print(",");
      Serial.print(setpoint);
      Serial.print(",");
      Serial.print(input);
      Serial.print(",");
      Serial.println(output);
    }
    else
    {
      // Turn off red LED
      digitalWrite(LED_BUILTIN, LOW);
    }
  }

  if (millis() > updateLcd)
  {
    // Update LCD in the next 250 ms
    updateLcd += 250;
    // Clear LCD
    lcd.clear();
    // Print current system state
    lcd.print(lcdMessagesReflowStatus[reflowState]);
    lcd.setCursor(6, 0);
    if (reflowProfile == REFLOW_PROFILE_LEADFREE)
    {
      lcd.print("LF");
    }
    else
    {
      lcd.print("PB");
    }
    // Move the cursor to the 2 line
    lcd.setCursor(0, 1);

    // If currently in error state
    if (reflowState == REFLOW_STATE_ERROR)
    {
      // Thermocouple error (open, shorted)
      lcd.print("TC Error");
    }
    else
    {
      // Display current temperature
      lcd.print(input);

#if ARDUINO >= 100
      // Display degree Celsius symbol
      lcd.write((uint8_t)0);
#else
      // Display degree Celsius symbol
      lcd.print(0, BYTE);
#endif
      lcd.print("C ");
    }
  }

  // Reflow oven controller state machine
  switch (reflowState)
  {
    case REFLOW_STATE_IDLE:
      // If oven temperature is still above room temperature
      if (input >= TEMPERATURE_ROOM)
      {
        reflowState = REFLOW_STATE_TOO_HOT;
      }
      else
      {
        // If switch is pressed to start reflow process
        if (switchStatus == SWITCH_1)
        {
          // Send header for CSV file
          Serial.println("Time,Setpoint,Input,Output");
          // Intialize seconds timer for serial debug information
          timerSeconds = 0;
          // Initialize PID control window starting time
          windowStartTime = millis();
          // Ramp up to minimum soaking temperature
          setpoint = TEMPERATURE_SOAK_MIN;
          // Load profile specific constant
          if (reflowProfile == REFLOW_PROFILE_LEADFREE)
          {
            soakTemperatureMax = TEMPERATURE_SOAK_MAX_LF;
            reflowTemperatureMax = TEMPERATURE_REFLOW_MAX_LF;
            soakMicroPeriod = SOAK_MICRO_PERIOD_LF;
          }
          else
          {
            soakTemperatureMax = TEMPERATURE_SOAK_MAX_PB;
            reflowTemperatureMax = TEMPERATURE_REFLOW_MAX_PB;
            soakMicroPeriod = SOAK_MICRO_PERIOD_PB;
          }
          // Tell the PID to range between 0 and the full window size
          reflowOvenPID.SetOutputLimits(0, windowSize);
          reflowOvenPID.SetSampleTime(PID_SAMPLE_TIME);
          // Turn the PID on
          reflowOvenPID.SetMode(AUTOMATIC);
          // Proceed to preheat stage
          reflowState = REFLOW_STATE_PREHEAT;
        }
      }
      break;

    case REFLOW_STATE_PREHEAT:
      reflowStatus = REFLOW_STATUS_ON;
      // If minimum soak temperature is achieve
      if (input >= TEMPERATURE_SOAK_MIN)
      {
        // Chop soaking period into smaller sub-period
        timerSoak = millis() + soakMicroPeriod;
        // Set less agressive PID parameters for soaking ramp
        reflowOvenPID.SetTunings(PID_KP_SOAK, PID_KI_SOAK, PID_KD_SOAK);
        // Ramp up to first section of soaking temperature
        setpoint = TEMPERATURE_SOAK_MIN + SOAK_TEMPERATURE_STEP;
        // Proceed to soaking state
        reflowState = REFLOW_STATE_SOAK;
      }
      break;

    case REFLOW_STATE_SOAK:
      // If micro soak temperature is achieved
      if (millis() > timerSoak)
      {
        timerSoak = millis() + soakMicroPeriod;
        // Increment micro setpoint
        setpoint += SOAK_TEMPERATURE_STEP;
        if (setpoint > soakTemperatureMax)
        {
          // Set agressive PID parameters for reflow ramp
          reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
          // Ramp up to first section of soaking temperature
          setpoint = reflowTemperatureMax;
          // Proceed to reflowing state
          reflowState = REFLOW_STATE_REFLOW;
        }
      }
      break;

    case REFLOW_STATE_REFLOW:
      // We need to avoid hovering at peak temperature for too long
      // Crude method that works like a charm and safe for the components
      if (input >= (reflowTemperatureMax - 5))
      {
        // Set PID parameters for cooling ramp
        reflowOvenPID.SetTunings(PID_KP_REFLOW, PID_KI_REFLOW, PID_KD_REFLOW);
        // Ramp down to minimum cooling temperature
        setpoint = TEMPERATURE_COOL_MIN;
        // Proceed to cooling state
        reflowState = REFLOW_STATE_COOL;
      }
      break;

    case REFLOW_STATE_COOL:
      // If minimum cool temperature is achieve
      if (input <= TEMPERATURE_COOL_MIN)
      {
        // Retrieve current time for buzzer usage
        buzzerPeriod = millis() + 1000;
        // Turn on buzzer to indicate completion
        digitalWrite(buzzerPin, HIGH);
        // Turn off reflow process
        reflowStatus = REFLOW_STATUS_OFF;
        // Proceed to reflow Completion state
        reflowState = REFLOW_STATE_COMPLETE;
      }
      break;

    case REFLOW_STATE_COMPLETE:
      if (millis() > buzzerPeriod)
      {
        // Turn off buzzer
        digitalWrite(buzzerPin, LOW);
        // Reflow process ended
        reflowState = REFLOW_STATE_IDLE;
      }
      break;

    case REFLOW_STATE_TOO_HOT:
      // If oven temperature drops below room temperature
      if (input < TEMPERATURE_ROOM)
      {
        // Ready to reflow
        reflowState = REFLOW_STATE_IDLE;
      }
      break;

    case REFLOW_STATE_ERROR:
      // Check for thermocouple fault
      fault = thermocouple.readFault();

      // If thermocouple problem is still present
      if ((fault & MAX31856_FAULT_CJRANGE) ||
          (fault & MAX31856_FAULT_TCRANGE) ||
          (fault & MAX31856_FAULT_CJHIGH) ||
          (fault & MAX31856_FAULT_CJLOW) ||
          (fault & MAX31856_FAULT_TCHIGH) ||
          (fault & MAX31856_FAULT_TCLOW) ||
          (fault & MAX31856_FAULT_OVUV) ||
          (fault & MAX31856_FAULT_OPEN))
      {
        // Wait until thermocouple wire is connected
        reflowState = REFLOW_STATE_ERROR;
      }
      else
      {
        // Clear to perform reflow process
        reflowState = REFLOW_STATE_IDLE;
      }
      break;
  }

  // If switch 1 is pressed
  if (switchStatus == SWITCH_1)
  {
    // If currently reflow process is on going
    if (reflowStatus == REFLOW_STATUS_ON)
    {
      // Button press is for cancelling
      // Turn off reflow process
      reflowStatus = REFLOW_STATUS_OFF;
      // Reinitialize state machine
      reflowState = REFLOW_STATE_IDLE;
    }
  }
  // Switch 2 is pressed
  else if (switchStatus == SWITCH_2)
  {
    // Only can switch reflow profile during idle
    if (reflowState == REFLOW_STATE_IDLE)
    {
      // Currently using lead-free reflow profile
      if (reflowProfile == REFLOW_PROFILE_LEADFREE)
      {
        // Switch to leaded reflow profile
        reflowProfile = REFLOW_PROFILE_LEADED;
        EEPROM.write(PROFILE_TYPE_ADDRESS, 1);
      }
      // Currently using leaded reflow profile
      else
      {
        // Switch to lead-free profile
        reflowProfile = REFLOW_PROFILE_LEADFREE;
        EEPROM.write(PROFILE_TYPE_ADDRESS, 0);
      }
    }
  }
  // Switch status has been read
  switchStatus = SWITCH_NONE;

  // Simple switch debounce state machine (analog switch)
  switch (debounceState)
  {
    case DEBOUNCE_STATE_IDLE:
      // No valid switch press
      switchStatus = SWITCH_NONE;

      switchValue = readSwitch();

      // If either switch is pressed
      if (switchValue != SWITCH_NONE)
      {
        // Keep track of the pressed switch
        switchMask = switchValue;
        // Intialize debounce counter
        lastDebounceTime = millis();
        // Proceed to check validity of button press
        debounceState = DEBOUNCE_STATE_CHECK;
      }
      break;

    case DEBOUNCE_STATE_CHECK:
      switchValue = readSwitch();
      if (switchValue == switchMask)
      {
        // If minimum debounce period is completed
        if ((millis() - lastDebounceTime) > DEBOUNCE_PERIOD_MIN)
        {
          // Valid switch press
          switchStatus = switchMask;
          // Proceed to wait for button release
          debounceState = DEBOUNCE_STATE_RELEASE;
        }
      }
      // False trigger
      else
      {
        // Reinitialize button debounce state machine
        debounceState = DEBOUNCE_STATE_IDLE;
      }
      break;

    case DEBOUNCE_STATE_RELEASE:
      switchValue = readSwitch();
      if (switchValue == SWITCH_NONE)
      {
        // Reinitialize button debounce state machine
        debounceState = DEBOUNCE_STATE_IDLE;
      }
      break;
  }

  // PID computation and SSR control
  if (reflowStatus == REFLOW_STATUS_ON)
  {
    now = millis();

    reflowOvenPID.Compute();

    if ((now - windowStartTime) > windowSize)
    {
      // Time to shift the Relay Window
      windowStartTime += windowSize;
    }
    if (output > (now - windowStartTime)) digitalWrite(ssrPin, HIGH);
    else digitalWrite(ssrPin, LOW);
  }
  // Reflow oven process is off, ensure oven is off
  else
  {
    digitalWrite(ssrPin, LOW);
  }
}

Kompletny kod jest załączony wraz z innymi plikami w dziale download.

Programowanie ATtiny1634R

Płytka posiada standardowe złącze FTDI (lub kompatybilne) USB-serial 6-pinowe, które może być użyte do wgrania firmware do wbudowanego mcu. Można to zrobić poprzez Arduino IDE. Wbudowany mikrokontroler ATtiny1634R używa ATtinyCore napisanego przez Spence Konde. Wszystko co musisz zrobić, to zainstalować ATtinyCore poprzez Arduino IDE Boards Manager. Wcześniej będziesz musiał wypalić bootloader ATtinyCore do mcu. Możesz użyć AVRISP mkII (lub dowolnego programatora AVR obsługiwanego przez IDE) do zaprogramowania bootloadera na ATtiny1634R. Aby zaprogramować bootloader, podłączasz standardowy 6-pinowy AVR ISP (2×3 piny 2.54 mm) do programatora AVRISP mkII. Następnie po wybraniu odpowiedniej opcji płytki wciskamy "burn bootloader". Po wgraniu bootloadera, można użyć USB FTDI do wgrania kodu normalnie z Arduino IDE.

Po zainstalowaniu pakietu ATtinyCore, powinieneś wybrać ATtiny1634 (Optiboot) z wewnętrznym zegarem 8 MHz:

Demo

Wersja PCB kontrolera rozpływowego jest dostarczana z interfejsem FTDI, przez który można go programować, więc jeśli budujesz na płytce prototypowej upewnij się, że to też jest przewidziane.  Używając kabla FTDI do USB, podłącz konfigurację do komputera. Wybierz typ płytki i załaduj do niej kod. Po wykonaniu tych czynności, możesz teraz podłączyć swój mini sterownik pieca rozpływowego do pieca i włączyć go. Powinieneś zobaczyć splash z ekranem podobnym do tego z poniższego obrazka.

Instalacja na małym piecu

Zainstalowaliśmy sterownik Tiny Reflow v1 na naszym małym, zmodyfikowanym piecu. Był to mały piec o mocy 600 W z analogowymi pokrętłami i termostatem. Dodaliśmy do niego izolację i dwa dodatkowe elementy grzejne o mocy 300 W każdy. Tak więc całkowita moc wynosi teraz 1200W. To sprawia, że piec jest bardziej wydajny i jest teraz w stanie osiągnąć pożądaną temperaturę łatwiej niż z elementami grzewczymi 600W. Różnicę w wydajności 600W i 1200W można zobaczyć na poniższych wykresach.

 Tiny Reflow v1 dodany do naszego 600W -> 1200W zmodernizowanego małego pieca
Piec został zmodernizowany do 1200W i zaizolowany od wewnątrz. Tutaj widać go z otwartymi drzwiczkami i czujnikiem temperatury
Widok modyfikacji dodatkowego dolnego elementu grzejnego (300W) i czujnika temperatury

Wyniki reflow

Tiny Reflow udostępnia pewne statystyki na swoim wyjściu RS-232. Użyj dowolnego programu terminala szeregowego w konfiguracji 115200 bps 8N1, aby zebrać informacje o temperaturze w czasie. Poniżej pokazano dwa wykresy profili rozpływu. Pierwszy z nich jest przed modyfikacją i izolacją pieca (600W), a drugi dla zmodyfikowanego pieca o mocy 1200W. Jak widać na drugim wykresie całkowity czas rozpływu wynosił około 415 sekund, podczas gdy pierwszy wykres pokazuje 500 sekund. Można również zauważyć, że profil rozpływowy 1200W osiągnął lepsze nachylenie temperatury wstępnego nagrzewania niż 600W, co oznacza, że łatwiej osiągnął pożądaną temperaturę. Piec 600W był trudny do wykonania.

Wnioski

Opisany w tyn projekcie sterownikzostał później zastąpiony przez Tiny Reflow Controller V2, którego projekt też możesz znaleźć na tym portalu.

Wideo
Do pobrania
Download icon reflowprofileszip Download icon tinyreflowcontrollerzip

Artykuł TINY REFLOW CONTROLLER WITH CHARACTER LCD opracowano w wersji polskiej na podstawie współpracy z portalem www.electronics-lab.com.

Firma:
AUTOR
Źródło
www.electronics-lab.com
Udostępnij
Zobacz wszystkie quizy
Quiz weekendowy
Edukacja
1/10 Jak działa rezystor LDR?
UK Logo
Elektronika dla Wszystkich
Zapisując się na nasz newsletter możesz otrzymać GRATIS
najnowsze e-wydanie magazynu "Elektronika dla Wszystkich"