'****************************************************************
'* Name : Reflow oven *
'* Author : Stijn Coenen [Stynus] *
'* Notice : Copyright (c) 2010 Stijn Coenen [Stynus] *
'* : Licenced under Creative Commons *
'* : Attribution-Noncommercial 2.0 Belgium Licence *
'* : http://creativecommons.org/licenses/by-nc/2.0/be/ *
'* Date : 08/05/2010 *
'* Version : 1.32 *
'* Notes : http://www.elektronicastynus.be/ *
'* : Projecten/Gereedschap/Reflow_oven/index.php *
'****************************************************************
Device 16F877A
Config WDT_OFF, PWRTE_ON, HS_OSC, LVP_OFF
Xtal 20
All_Digital = true
'****************************************************************
'Declaraties pinnen en variabelen
'Lcd
Declare LCD_DTPin PORTD.4
Declare LCD_ENPin PORTC.5
Declare LCD_RSPin PORTC.4
Declare LCD_Interface 4
Declare LCD_Lines 2
'Verwarmingsweerstanden
Symbol Rboven = PORTA.1 : PORTA.1 = 0
Symbol Ronder = PORTA.0 : PORTA.0 = 0
'Case temp sensor
Symbol SDA = PORTA.5
Symbol SLC = PORTA.3
Dim CaseTemp As Byte
'Oven temp sensor
Symbol ChipSelect = PORTD.2 : TRISD.2 = 0
Symbol Sck = PORTD.1
Symbol SO = PORTD.3
Dim OvenTemp As Word
'RS232
Hserial_Clear = On
Hserial_Baud 4800
Hserial_RCSTA = %10010000
Hserial_TXSTA = %00100000
'Keypad
Declare Keypad_Port PORTB
Dim Toets As Byte
Dim Toets_W As Byte
Dim TempToets As Byte
Dim InstelTemp As Word
Symbol Pijl_up = 10
Symbol Pijl_down = 11
Symbol Enter = 12
Symbol Back = 13
'Diverse
Symbol fan = PORTE.2 : TRISE.2 = 0
Symbol zoemer = PORTC.2 : PORTC.2 = 0
'************************************************************
'Menu
Dim Menu_Item As Byte
'PID interrupt
Symbol GIE = INTCON.7 'Global Interrupt Enable
Symbol T0IE = INTCON.5 'TMR0 Overflow Interrupt Enable
Symbol T0IF = INTCON.2 'TMR0 Overflow Interrupt Flag
T0IF = 0
Symbol PS0 = OPTION_REG.0 'Prescaler bit-0
Symbol PS1 = OPTION_REG.1 'Prescaler bit-1
Symbol PS2 = OPTION_REG.2 'Prescaler bit-2
PS0 = 1
PS1 = 1
PS2 = 1
Symbol PSA = OPTION_REG.3 'Prescaler Assignment
PSA = 0
Symbol T0CS = OPTION_REG.5 'Timer0 Clock Source Select
T0CS = 0
TMR0 = 0
On_Hardware_Interrupt GoTo interrupt_routine
Dim setpoint As Dword 'Gewenste temperatuur
Dim tempnu As Dword 'Huidige temperatuur
Dim Error_now As Dword 'Huidige fout
Dim Error_last As Dword 'Fout laatste cyclus
Dim P As Dword 'P waarde
Dim I As Dword 'I waarde
Dim D As Dword 'D waarde
Dim PID As Dword 'PID waarde
Symbol Kp = 15 'Proportionele actie
Symbol Ki = 0 'Integratietijd
Symbol Kd = 5 'Differentiatietijd
Dim DoBit As Bit 'Zorgt ervoor dat de pid lus niet kan uitge-
'voerd worden als de pwm lus niet voltooid is
Dim pwm_teller As Byte 'Teller voor de PWM lus
'Programma variabelen
Dim teller As Byte 'houd het menu item bij
Dim tijd As Byte 'Stap in de programma's
Dim chrono As Byte 'timing in de programma's
Dim digit As Byte 'Digit bij het instellen temperatuur
'****************************************************************
Clear 'Variabelen leeg maken
GoTo oversub 'Over de sub routines heen springen
'****************************************************************
'Subroutines
'************************************************************
'Subroutine om de temperatuur van de controllerprint in te lezen
CaseTempInlezen:
I2Cin SDA, SLC,$91,[CaseTemp]
Return
'************************************************************
'Subroutine om de temperatuur van de oven in te lezen
OvenTempInlezen:
Low ChipSelect
SHIn SO,Sck,0,[OvenTemp\16]
High ChipSelect
OvenTemp = OvenTemp >> 5
Return
'************************************************************
'Subroutine om de knoppen in te lezen
KnoppenInlezen:
Toets_W = InKey 'Toetsenbord inlezen
'Opzoeken welke waarde deze toets heeft
Toets = LookUpL Toets_W, [13,12,11,10,255,9,6,3,0,8,5,2,255,7,4,1,255]
If Toets < 15 Then 'Als de toets lager is dan 15 hier
While Toets_W = InKey : Wend 'blijven hangen tot de toets is losgelaten
DelayMS 10 '10mS delay tegen contact dender
EndIf
Return
'************************************************************
'Subroutine om data over de oven naar de pc te sturen via een RS232 interface
RS_Uit:
HSerOut ["Oven:'", Dec OvenTemp , "' "]
HSerOut ["Case:'", Dec CaseTemp , "' "]
HSerOut ["Setp:'", Dec setpoint , "' "]
HSerOut ["P:'" , SDec P , "' "]
HSerOut ["I:'" , SDec I , "' "]
HSerOut ["D:'" , SDec D , "' "]
HSerOut [13,10]
Return
'************************************************************
'Subroutine die een biepje uit de zoemer geeft.
Zoemen:
Sound zoemer, [120,250]
Return
'************************************************************
'Subroutine die de pid bereken sub aanroept, vervolgens de setwaarde dat deze geeft
'op het display zetten en de sub aanroepen die deze uitstuurt via de RS232 verbinding
Regel:
If DoBit = 1 Then
GoSub Bereken_PID
Print At 2,1, "T", Dec3 OvenTemp, "C S", Dec3 setpoint, "C ", Dec3 PID, "% "
GoSub RS_Uit
EndIf
Return
'************************************************************
'Subroutine die de pid waardes berekent
Bereken_PID:
Error_now = setpoint - OvenTemp 'De huidige fout berekeken
If Error_now < 0 Then 'Als de fout kleiner is dan 0 (overshoot)
P = 0 'dan de P waarde 0 maken anders de P
Else 'waarde berekenen
P = Kp * Error_now
EndIf
I = I + (Ki * Error_now) 'I waarde berekenen
D = Kd * (Error_now - Error_last) 'D waarde berekenen
Error_last = Error_now 'fout van nu in error_last zetten voor de
'volgende keer de D waarde te berekenen
PID = P + I + D 'P, I en D actie optellen
If PID > 100 Then PID = 100 'Als PID groter is dan 100 > 100 maken
If PID < 0 Then PID = 0 'Als PID kleiner is dan 0 > 0 maken
Return
'************************************************************
interrupt_routine:
If T0IF = 1 Then 'Kijken of de interrupt wel van timer0 komt
'****************************************************
'Temperatuur sensoren inlezen
Inc teller 'Teller + 1
If teller = 100 Then 'Bij de 100ste interrupt de oven temperatuur inlezen
'OvenTempInlezen
Low ChipSelect
SHIn SO,Sck,0,[OvenTemp\16]
High ChipSelect
OvenTemp = OvenTemp >> 5
DoBit = 1
EndIf
If teller = 200 Then 'Bij de 200ste interrupt de case temperatuur inlezen
I2Cin SDA, SLC,$91,[CaseTemp]
If CaseTemp > 29 Then 'Fan aanzetten indien nodig
Low fan 'Low = aan
EndIf
If CaseTemp < 25 Then
High fan 'High = uit
EndIf
EndIf
'****************************************************
'Pwm routine om de verwarmingsweerstanden aan te sturen
If pwm_teller < PID Then
High Rboven
High Ronder
Else
Low Rboven
Low Ronder
EndIf
If pwm_teller = 100 Then
pwm_teller = 0
Else
Inc pwm_teller
EndIf
'****************************************************
T0IF = 0 'Timer 0 interrupt vlag terug uitzetten
EndIf
Context Restore
'****************************************************************
oversub:
Cls
DelayMS 300
Print At 1,1, "Reflow oven V1.3"
Print At 2,1, "Elek Stynus 2010"
HSerOut ["******************************", 13,10]
HSerOut ["* ElektronicaStynus.be *", 13,10]
HSerOut ["* Reflow oven V1.32 *", 13,10]
HSerOut ["* Laatste update: 08/05/2010 *", 13,10]
HSerOut ["******************************", 13,10]
DelayMS 1000
Menu:
Cls
Low Rboven
Low Ronder
Menu_Item = 0
While 1 = 1
'Tekst op lcd display zetten
Select Menu_Item
Case 0 '1234567890123456
Print At 1,1, "-> - Pre-heat "
Print At 2,1, " - Reflow "
Case 1 '1234567890123456
Print At 1,1, "-> - Reflow "
Print At 2,1, " - Desolder "
Case 2 '1234567890123456
Print At 1,1, "-> - Desolder "
Print At 2,1, " - Fixed temp "
Case 3 '1234567890123456
Print At 1,1, "-> - Fixed temp "
Print At 2,1, " - Pre-heat "
EndSelect
'Knoppen inlezen
GoSub KnoppenInlezen
'Bladeren in menu:
If Toets = Pijl_down Then
DelayMS 20
If Menu_Item < 3 Then
Inc Menu_Item
Else
Menu_Item = 0
EndIf
EndIf
If Toets = Pijl_up Then
DelayMS 20
If Menu_Item > 0 Then
Dec Menu_Item
Else
Menu_Item = 3
EndIf
EndIf
'Menu item enteren
If Toets = Enter Then
Select Menu_Item
Case 0
GoTo Preheat
Case 1
GoTo Reflow
Case 2
GoTo Desolder
Case 3
GoTo Fix_temp
EndSelect
EndIf
DelayMS 100
Wend
GoTo Menu
'****************************************************************
Preheat:
Cls '1234567890123456
Print At 1,1, " - Pre-heat - "
setpoint = 75
T0IE = 1
GIE = 1
While 1 = 1
GoSub Regel
GoSub KnoppenInlezen
If Toets = Back Then
T0IE = 0
GIE = 0
GoTo Menu
EndIf
Wend
GoTo Menu
'****************************************************************
Reflow:
Cls
T0IE = 1
GIE = 1
setpoint = 0
For tijd = 0 To 38
'1234567890123456
Print At 1,1, "- Reflow - ", Dec2 tijd, "/38"
setpoint = LookUpL tijd, [20,37,53,70,86,102,118,129,140,150,155,160,165,169,172,175,177,179,180,197,213,230,230,230,213,197,180,170,160,150,140,130,120,110,100,90,70,40,20]
For chrono = 0 To 100
GoSub Regel
GoSub KnoppenInlezen
If Toets = Back Then
GoTo Menu
EndIf
DelayMS 100
Next
Next
setpoint = 0
GoSub Regel
T0IE = 0
GIE = 0
While 1 = 1
GoSub Zoemen
DelayMS 250
GoSub KnoppenInlezen
If Toets = Back Then
GoTo Menu
EndIf
Wend
'****************************************************************
Desolder:
Cls
T0IE = 1
GIE = 1
setpoint = 0
For tijd = 0 To 38
'1234567890123456
Print At 1,1, "-Desolder- ", Dec2 tijd, "/38"
setpoint = LookUpL tijd, [20,37,53,70,86,102,118,129,140,150,155,160,165,169,172,175,177,179,180,197,213,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230,230]
For chrono = 0 To 100
GoSub Regel
GoSub KnoppenInlezen
If Toets = Back Then
GoTo Menu
EndIf
DelayMS 100
Next
Next
setpoint = 0
GoSub Regel
T0IE = 0
GIE = 0
While 1 = 1
GoSub Zoemen
DelayMS 250
GoSub KnoppenInlezen
If Toets = Back Then
GoTo Menu
EndIf
Wend
'****************************************************************
Fix_temp:
Cls '1234567890123456
Print At 1,1, " - Fixed temp - "
digit = 1
setpoint = 0
While 1 = 1
GoSub KnoppenInlezen
Print At 2,1, "Temp: ", Dec setpoint, "°C "
If Toets < 10 Then
Select digit
Case 1
setpoint = Toets
Inc digit
Case 2
setpoint = (setpoint * 10) + Toets
Inc digit
Case 3
setpoint = (setpoint * 10) + Toets
EndSelect
EndIf
If Toets = Enter Then
Break
EndIf
If Toets = Back Then
If digit = 0 Then
GoTo Menu
EndIf
Dec digit
setpoint = setpoint / 10
EndIf
Wend '1234567890123456
Print At 2,1, " Start? "
While 1 = 1
GoSub KnoppenInlezen
If Toets = Back Then
GoTo Fix_temp
EndIf
If Toets = Enter Then
Break
EndIf
Wend
T0IE = 1
GIE = 1
While 1 = 1
GoSub Regel
GoSub KnoppenInlezen
If Toets = Back Then
T0IE = 0
GIE = 0
GoTo Menu
EndIf
Wend
'****************************************************************
End