#include <16F819.h> //#define __encoder__ #device adc=10 #FUSES INTRC_IO #FUSES WDT #FUSES NOPROTECT #FUSES NOBROWNOUT #FUSES MCLR #FUSES NOCPD #FUSES NOPUT #FUSES NOLVP #use delay(clock=4000000) #use i2c(Slave,Fast,sda=PIN_B1,scl=PIN_B4,restart_wdt,force_hw,address=0xAB) const char init1[] = "HEAT BED CONTROL"; #ifdef __encoder__ const char init2[] = " v2.3e "; #else const char init2[] = " v2.3 "; #endif const char gen1[] = "Target: 00.00C"; const char gen2[] = "Current: 00.00C"; volatile unsigned int16 i; volatile unsigned int8 j; unsigned int16 adc_raw; unsigned int16 adc_avg; volatile unsigned int16 target; unsigned int16 current; //204-GT thermistor with 10K in voltage divider #define TEMPS 28 unsigned int16 thermTable[TEMPS] = { 1010, 1000, 985, 963, 932, 889, 834, 768, 692, 610, //0-90 526, 446, 373, 308, 252, 206, 168, 137, 112, 91, //100-190 75, 62, 51, 43, 36, 30, 26, 22 // 200-270 }; BYTE incoming, state; BYTE address; BYTE buffer[4]; //[0] + [1]<<8 = TARGET TEMP; [2] + [3]<<8 = CURRENT TEMP BYTE changed; #int_SSP void SSP_isr(void) { state = i2c_isr_state(); if(state == 1){ incoming = i2c_read(); address = incoming; if (address > 3) address = 0; } if(state == 2){ incoming = i2c_read(); if (address > 1) address = 0; //only 0 and 1 are writable buffer[address] = incoming; if (address == 1) changed = 1; } if(state == 0x80){ i2c_write (buffer[address]); } } #ifdef __encoder__ volatile int8 encoder; #int_rb void detect_rb5_change() { //here we catch only RB4-RB7 encoder = 1; if (input(PIN_B5)) { if (input(PIN_B0)) { if(target<27000) target += 50; } else { if(target>49) target -= 25; } } else { if (!input(PIN_B0)) { if(target<27000) target += 50; } else { if(target>49) target -= 25; } } } #int_ext void detect_rb0_change() { //here we catch only RB0 encoder = 1; if (input(PIN_B0)) { if (!input(PIN_B5)) { if(target<27000) target += 50; } else { if(target>49) target -= 25; } } else { if (input(PIN_B5)) { if(target<27000) target += 50; } else { if(target>49) target -= 25; } } } #endif //RB3 - RS struct lcd_pin_map { BOOLEAN unused; int data : 4; BOOLEAN mclr; BOOLEAN rw; BOOLEAN enable; } lcd; #locate lcd = getenv("sfr:PORTA") #define set_tris_lcd(x) set_tris_a(x) #define lcd_type 2 #define lcd_line_two 0x40 BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6}; struct lcd_pin_map const LCD_WRITE = {1, 0,0,0,0}; // For write mode all pins are out struct lcd_pin_map const LCD_READ = {1,15,0,0,0}; // For read mode data pins are in BYTE lcd_read_byte() { BYTE low,high; set_tris_lcd(LCD_READ); lcd.rw = 1; delay_cycles(1); lcd.enable = 1; delay_cycles(1); high = lcd.data; lcd.enable = 0; delay_cycles(1); lcd.enable = 1; delay_us(1); low = lcd.data; lcd.enable = 0; set_tris_lcd(LCD_WRITE); return( (high<<4) | low); } void lcd_send_nibble( BYTE n ) { lcd.data = n; delay_cycles(1); lcd.enable = 1; delay_us(2); lcd.enable = 0; } void lcd_send_byte( BYTE address, BYTE n ) { //lcd.rs = 0; output_low(PIN_B3); while ( bit_test(lcd_read_byte(),7) ) ; //lcd.rs = address; if (address){ output_high(PIN_B3); }else{ output_low(PIN_B3); } delay_cycles(1); lcd.rw = 0; delay_cycles(1); lcd.enable = 0; lcd_send_nibble(n >> 4); lcd_send_nibble(n & 0xf); } void lcd_init() { BYTE i; set_tris_lcd(LCD_WRITE); //lcd.rs = 0; output_low(PIN_B3); lcd.rw = 0; lcd.enable = 0; delay_ms(15); for(i=1;i<=3;++i) { lcd_send_nibble(3); delay_ms(5); } lcd_send_nibble(2); for(i=0;i<=3;++i) lcd_send_byte(0,LCD_INIT_STRING[i]); } unsigned int16 getTemp(){ unsigned int16 tempVal; unsigned int16 lowValue; unsigned int16 highValue; unsigned int16 dataValue; unsigned int16 range; for(j=0; j tempVal){ #asm clrwdt #endasm lowValue = tempVal; highValue = thermTable[j-1]; range = highValue - lowValue; dataValue = adc_avg - LowValue; return j * 1000 - (dataValue * 1000 / range); } } return (55555); } void print_temp(int8 line, unsigned int16 temp){ // temperature is *100 unsigned int8 x; //hundreds x = temp / 10000; if (x == 0) { lcd_send_byte(0,0x80|(9+lcd_line_two*line)); lcd_send_byte(1,' '); } else { x = x + 48; lcd_send_byte(0,0x80|(9+lcd_line_two*line)); lcd_send_byte(1, x); } #asm clrwdt #endasm //tens x = ((temp / 1000 ) % 10) + 48; lcd_send_byte(0,0x80|(10+lcd_line_two*line)); lcd_send_byte(1, x); #asm clrwdt #endasm //ones x = ((temp / 100 ) % 10) + 48; lcd_send_byte(0,0x80|(11+lcd_line_two*line)); lcd_send_byte(1, x); #asm clrwdt #endasm // 1/10 x = ((temp / 10 ) % 10) + 48; lcd_send_byte(0,0x80|(13+lcd_line_two*line)); lcd_send_byte(1, x); #asm clrwdt #endasm // 1/100 x = (temp % 10) + 48; lcd_send_byte(0,0x80|(14+lcd_line_two*line)); lcd_send_byte(1, x); #asm clrwdt #endasm } void pid(){ //for start - very basic pid controller if (current < target){ output_low(PIN_B2); } else { output_high(PIN_B2); } } #ifndef __encoder__ //RB0, RB5 void menu(){ #asm clrwdt #endasm delay_ms(15); if (!input(PIN_B0)) if(target<27000) target += 50; if (!input(PIN_B5)) if(target>49) target -= 50; if (!input(PIN_B0) && !input(PIN_B5)){ write_eeprom(0, target & 0x00ff); write_eeprom(1, target >> 8 ); } print_temp(0, target); delay_ms(15); } #endif void main(){ setup_oscillator(OSC_4MHZ); setup_adc_ports(AN0); setup_adc(ADC_CLOCK_INTERNAL); setup_wdt(WDT_2304MS); set_tris_b(0x33); lcd_init(); output_high(PIN_B2); for (j=0;j<16;j++){ lcd_send_byte(0,0x80|j); lcd_send_byte(1,init1[j]); lcd_send_byte(0,0x80|(j+lcd_line_two)); lcd_send_byte(1,init2[j]); } #asm clrwdt #endasm changed = 0; address = 0; target = read_eeprom(1); target = target << 8; target |= read_eeprom(0); if (target > 30000) target = 7000; //70C current = 0; adc_raw = 0; adc_avg = 0; #asm clrwdt #endasm buffer[0]=buffer[1]=buffer[2]=buffer[3]=0; delay_ms(1000); for (j=0;j<16;j++){ lcd_send_byte(0,0x80|j); lcd_send_byte(1,gen1[j]); lcd_send_byte(0,0x80|(j+lcd_line_two)); lcd_send_byte(1,gen2[j]); } print_temp(0, target); set_adc_channel(0); #ifdef __encoder__ encoder = 0; enable_interrupts(INT_RB); //RB5 enable_interrupts(INT_EXT);//RB0 #endif enable_interrupts(INT_SSP); enable_interrupts(GLOBAL); while (TRUE){ #asm clrwdt #endasm adc_raw = read_adc(); adc_avg = (adc_avg *2 + adc_raw) / 3; current = getTemp(); pid(); print_temp(1, current); #ifdef __encoder__ if(encoder){ print_temp(0, target); encoder = 0; } #else if (!input(PIN_B0) || !input(PIN_B5)) menu(); #endif if (changed){ //something came via I2C target = buffer[1]; target = target << 8; target |= buffer[0]; print_temp(0, target); changed = 0; } //write data into buffer for I2C read buffer[2] = current & 0x00ff; buffer[3] = current >> 8; } }