#include "reflow.h"
#include "process.h"
#include <math.h>
// CPU IO
#define LCD_RS PIN_C1 // rizeni registru LCD displeje
#define LCD_E PIN_C2 // enable LCD displeje
#define LCD_DATA_LSB PIN_D0 // data LCD
#include "lcd.c"
#define TL1 PIN_B3 // tlacitko S1
#define TL2 PIN_B2 // tlacitko S2
#define TL3 PIN_B1 // tlacitko S3
#define TL4 PIN_B0 // tlacitko S4
#define POWER_T3 PIN_C4 // ovladani optotriaku T3
#define POWER_T4 PIN_C5 // ovladani optotriaku T4
#define POWER_T5 PIN_C6 // ovladani optotriaku T5
#define ADC_PIN PIN_A0 //info, nelze menit - pin pouzit jako input analog
#define ADC_PIN_NC PIN_A1 //info, nelze menit - pin pouzit jako input analog
#define REF_PIN PIN_A3 //info, nelze menit - pin pouzit jako input reference 2.5V
// interni
#define PowerOn() output_low(POWER_T4);output_low(POWER_T5)
#define PowerOff() output_high(POWER_T4);output_high(POWER_T5)
// global variables
struct time
{
volatile signed int8 hod;
volatile signed int8 min;
volatile signed int8 sec;
}cas;
unsigned int top_heat_power=0; // range 0-200% nad 100% je ale teleso jiz pretizene
unsigned int bottom_heat_power=0; // contains heating power range 0-100%
unsigned int period;
float temp_last=0;
float temp_slope=0;
void GeneralCpuInit() // inicializace
{
output_high(POWER_T4);
output_high(POWER_T5);
port_b_pullups(true);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64); //nepouzit
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // rizeni
setup_timer_2(T2_DIV_BY_16,249,10); //rtc 40ms
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_TIMER0);
setup_adc_ports(AN0_AN1_VSS_VREF); //A0 vstup cidla, A1 nepozit, A3 - ref. 2.5V
setup_adc(ADC_CLOCK_DIV_8);
SET_ADC_CHANNEL(0); //AN0, PIN_A0
}
void heat_failure() // exception in case of heating fail
{
top_heat_power=0;
bottom_heat_power=0;
lcd_gotoxy(1,2);
printf(lcd_putc,"HEATING FAILURE!");
while(true);
}
unsigned int16 adc(void) // adc read and filtering
{
unsigned int16 analog;
unsigned int8 a;
analog = 0;
for (a=0;a<32;a++)
{
analog += read_adc();
delay_us(50);
}
return (analog >> 5 ); // prumer = analog/32
}
float teplota(void) // temperature measuring
{
return (0.674201*adc() - 294.35); // temperature calculaton (linear aproximation)
}
void top_heating()
{
if (period < top_heat_power){
output_low(POWER_T4);
output_low(POWER_T5);
}
else{
output_high(POWER_T4);
output_high(POWER_T5);
}
}
void bottom_heating()
{
if (period < 2*bottom_heat_power){
output_low(POWER_T3);
}
else{
output_high(POWER_T3);
}
}
#int_TIMER0
void heating_control() //rizeni topnych teles pri preteceni casovace
{
float temp;
top_heating();
bottom_heating();
if ((period == 100) || (period == 0))
{
temp=teplota();
temp_slope=(temp - temp_last) /(100.0*256.0/62500.0); // vypocet strmosti narustu teploty ve stupnich/s
temp_last = temp;
printf("%02u %02u %3.3f \r\n",cas.min,cas.sec,temp); //vypis pro zaznam profilu
}
if (period < 200) period++;
else period=0;
}
#int_TIMER2
void Rtc(void) //40ms
{
static unsigned int8 ms40=0;
struct time* time;
time=&cas;
if ( ++ms40 < 25) return;
ms40=0;
if (++(time->sec) >= 60)
{
time->sec=0; //1min
if (++(time->min) >= 60)
{
time->min = 0; //1hod
(time->hod)++;
}
}
}
void slope_control(float ramp, unsigned int balance) // P proporcionalni rizeni narustu teploty predpoklada periodicke volani 1x/s
{
float slope_deviation;
slope_deviation = temp_slope - ramp; // vypocet strmosti a odchylky od pozadovane strmosti
if(slope_deviation < 0)
{
top_heat_power= 60 + balance;
bottom_heat_power= 100;
}
else{
top_heat_power=0;
bottom_heat_power=0;
}
}
void level_control(float level) // P proporcionalni rizeni teploty
{
if (teplota() > level)
{
top_heat_power=0;
bottom_heat_power=0;
}
else
{
top_heat_power=70;
bottom_heat_power=80;
}
}
void nullcas(struct time* time)
{
disable_interrupts(INT_TIMER2);
time->sec=0;
time->hod=0;
time->min=0;
enable_interrupts(INT_TIMER2);
}
void reflow_solder()
{
struct time process_time;
// ------------------- PREHEAT ---------------------
nullcas(&cas);
lcd_gotoxy(1,2);
printf(lcd_putc,"PREHEAT");
printf("#PREHEAT\r\n");
do {
slope_control(PREHEAT_SLOPE, 0); // hlida strmost predehrevu
lcd_gotoxy(1,1);
printf(lcd_putc,"%3.1f\21C ",teplota());
lcd_gotoxy(12,1);
printf(lcd_putc,"%02u:%02u",cas.min,cas.sec);
lcd_gotoxy(10,2);
printf(lcd_putc,"%1.1f\21C/s ",temp_slope);
delay_ms(200);
if (cas.min>4) heat_failure(); // hardcoded timeout to heating failure
}
while (teplota() < SOAK_TEMP);
// ----------- SOAK ---------------
nullcas(&cas);
process_time.min = SOAK_TIME/60;
process_time.sec = SOAK_TIME - process_time.min*60;
lcd_clr();
lcd_gotoxy(1,2);
printf(lcd_putc,"SOAK ");
printf("#SOAK\r\n");
while (process_time.sec!=0 || process_time.min!=0)
{
level_control(SOAK_TEMP);
lcd_gotoxy(1,1);
printf(lcd_putc,"%3.1f\21C ",teplota());
if ((process_time.sec = process_time.sec - cas.sec)<0) process_time.sec=59;
process_time.min = (SOAK_TIME - cas.min*60 - cas.sec)/60;
process_time.sec = (SOAK_TIME - cas.min*60 - cas.sec) - process_time.min*60;
lcd_gotoxy(9,1);
printf(lcd_putc,"%02u:%02u", process_time.min, process_time.sec);
delay_ms(200);
}
//----------------- solder ----------------------------
nullcas(&cas);
lcd_clr();
lcd_gotoxy(1,2);
printf(lcd_putc,"SOLDER");
printf("#SOLDER\r\n");
do {
slope_control(SOLDER_SLOPE, 10); // hlida strmost predehrevu
lcd_gotoxy(1,1);
printf(lcd_putc,"%3.1f\21C ",teplota());
lcd_gotoxy(12,1);
printf(lcd_putc,"%02u:%02u",cas.min,cas.sec);
lcd_gotoxy(10,2);
printf(lcd_putc,"%1.1f\21C/s ",temp_slope);
delay_ms(200);
if (cas.min>2) heat_failure();
}
while (teplota() < SOLDER_TEMP);
// ---------------- TAO ------------------------
while (process_time.sec!=0 || process_time.min!=0)
{
level_control(SOLDER_TEMP);
lcd_gotoxy(1,1);
printf(lcd_putc,"%3.1f\21C ",teplota());
if ((process_time.sec = process_time.sec - cas.sec)<0) process_time.sec=59;
process_time.min = (SOLDER_TIME - cas.min*60 - cas.sec)/60;
process_time.sec = (SOLDER_TIME - cas.min*60 - cas.sec) - process_time.min*60;
lcd_gotoxy(9,1);
printf(lcd_putc,"%02u:%02u", process_time.min, process_time.sec);
delay_ms(200);
}
// ---------------- COOLING ------------------------
top_heat_power=0;
bottom_heat_power=0;
lcd_clr();
lcd_gotoxy(1,2);
printf(lcd_putc,"REFLOW COMPLETE");
printf("COOLING \r\n");
while(true)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"%3.1f\21C ",teplota());
lcd_gotoxy(10,1);
printf(lcd_putc,"%1.1f\21C/s ",temp_slope);
}
}
void main() // main loop
{
GeneralCpuInit();
PowerOff();
lcd_init();
lcd_define_char(1,LCD_CHAR_STUPEN);
nullcas(&cas);
while(true)
{
delay_ms(300);
reflow_solder();
}
}