#include #include "16c84-cloud-sensor.h" /* Detect the presence of clouds or A CLEAR SKY */ /* use an mlx90614 IR thermometer sensor to measure */ /* the sky temperature. If the difference between */ /* sky and ambient is high (the sky being colder) */ /* that signifies a clear sky. */ /* (c) Peter Lynch, December 2010 */ /* use watchdog to waken the processor after the alarm has triggered */ /* __CONFIG(XT & PWRTDIS & UNPROTECT); */ __CONFIG(XT & UNPROTECT); #define _XTAL_FREQ 4000000 #define LCD_DATA RB0 #define LCD_CLOCK RB1 #define LCD_CLK_PULSE LCD_CLOCK=1; LCD_CLOCK=0 /* definitions for MLX90614 SMBus device interface pins */ #define SCK RB2 #define SDA RB3 /* Also need to set the Data pin as either an output or an input */ #define Set_SDA_In TRISB3=1; #define Set_SDA_Out TRISB3=0; void bin2bcd(); unsigned char TenK, Thou, Hund, Tens, Ones; chars_t Temp; void lcd_str(const char *); void lcd_char(unsigned char); void lcd_4bit(unsigned char, unsigned char); void SMBus_Stop(); void SMBus_Read(unsigned char); void wait_ms(int); void main(void) { OPTION = 0xf; /* pullups enabled - B7 => 0 */ /* prescaler to WDT - 0x08 */ /* prescaler = 128 (WDT mode) - 0x07 */ GIE = 0; /* disable all interrupts */ TRISA = 0; /* All pins are outputs */ TRISB = 0; PORTA = 0; PORTB = 0b00000000; /* Force MLX90614 out of PWM mode > 1.44mSec */ /* Initialise the LCD */ wait_ms(1000); /* let things settle down */ lcd_4bit(3,0); /* reset the display */ wait_ms(5); /* allow it to complete */ LCD_DATA = 1; LCD_DATA = 0; __delay_us(160); LCD_DATA = 1; LCD_DATA = 0; __delay_us(160); lcd_4bit(2,0); /* set to 4-bit mode */ __delay_us(160); lcd_4bit(2,0); lcd_4bit(8,0); lcd_4bit(0,0); lcd_4bit(8,0); lcd_4bit(0,0); /* these two commands clear the display */ lcd_4bit(1,0); wait_ms(5); lcd_4bit(0,0); lcd_4bit(6,0); lcd_4bit(0,0); lcd_4bit(0xc,0); wait_ms(5); lcd_str("Object Chip Temp"); SMBus_Stop(); /* force SMBus into reset state */ while(1) { RA1 = 0; wait_ms(25); RA1 = 1; wait_ms(70); /* time for it to initialise */ lcd_4bit(12, 0); /* start of second row */ lcd_4bit(0,0); /* first position in */ SMBus_Read(7); /* read Tobj1 from IR thermometer at defined SA */ Temp.ui = Temp.ui * 2; bin2bcd(); lcd_char('0'+TenK); lcd_char('0'+Thou); lcd_char('0'+Hund); lcd_char('.'); lcd_char('0'+Tens); lcd_char('0'+Ones); SMBus_Read(6); /* read Tamb from IR thermometer at defined SA */ Temp.ui = Temp.ui * 2; bin2bcd(); lcd_char(' '); lcd_char('0'+TenK); lcd_char('0'+Thou); lcd_char('0'+Hund); lcd_char('.'); lcd_char('0'+Tens); lcd_char('0'+Ones); lcd_char(0xdf); lcd_char('K'); wait_ms(400); } } /* send a string to the LCD */ void lcd_str(const char *p) { while(*p) { lcd_char(*p++); // lcd_4bit((*p) >> 4, 1); // lcd_4bit((*p) & 0xf, 1); // p++; } } /* send a character to be displayed */ void lcd_char(unsigned char c) { lcd_4bit(c >> 4, 1); lcd_4bit(c & 0xf, 1); } /* Routine to send 4 bits to the LCD (since we only have 4 data wires connected) */ /* 123 uSec at 4 MHz */ void lcd_4bit(unsigned char c, unsigned char cmd) { LCD_DATA = 0; LCD_CLK_PULSE; LCD_CLK_PULSE; LCD_CLK_PULSE; LCD_CLK_PULSE; LCD_CLK_PULSE; LCD_CLK_PULSE; LCD_DATA = 1; /* preload a 1 to set ENABLE later */ LCD_CLK_PULSE; /* strobe it in */ LCD_DATA = cmd && 1; /* set RS bit, 1 == data, 0 == command */ LCD_CLK_PULSE; LCD_DATA = (c >> 3) & 1; LCD_CLK_PULSE; /* Send top bit of nibble first */ LCD_DATA = (c >> 2) & 1; LCD_CLK_PULSE; LCD_DATA = (c >> 1) & 1; LCD_CLK_PULSE; LCD_DATA = c & 1; LCD_CLK_PULSE; LCD_DATA = 1; LCD_DATA = 0; /* send the preloaded ENABLE bit */ } /* Set an SMBus STOP condition */ void SMBus_Stop() { Set_SDA_Out; SCK = 1; __delay_us(5); SDA = 1; __delay_us(10); } /* Set an SMBus START condition */ void SMBus_Start() { Set_SDA_Out; SDA = 0; __delay_us(7); SCK = 0; __delay_us(10); /* must not have SCK low for > 45uSec */ } /* Send a Restart on the SMBus */ void SMBus_Restart() { Set_SDA_Out; NOP(); SDA = 1; // __delay_us(5); SCK = 1; // __delay_us(10); SDA = 0; // __delay_us(7); SCK = 0; // __delay_us(10); } /* Send one bit on the SMBus */ void SMBus_Tx_Bit(unsigned char c) { Set_SDA_Out; if(c) SDA = 1; else SDA = 0; // __delay_us(5); SCK = 1; /* data clocked on rising edge */ // __delay_us(10); SCK = 0; // __delay_us(5); } /* Receive one bit on the SMBus */ unsigned char SMBus_Rx_Bit() { unsigned char b; Set_SDA_In; // NOP(); NOP(); SCK = 1; /* data clocked on rising edge */ b = SDA; // __delay_us(5); SCK = 0; if(b) return (1); return(0); } /* Receive a byte of the SMBus */ unsigned char SMBus_Rx_Byte() { unsigned char c = 0; c = SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); c = c << 1; c |= SMBus_Rx_Bit(); return (c); } /* Send a read command on the SMBus and receive an ACK */ void SMBus_Read(unsigned char addr) { SMBus_Start(); SMBus_Tx_Bit(SA & 0x40); /* 7 bit Slave Address, send top bit first */ SMBus_Tx_Bit(SA & 0x20); SMBus_Tx_Bit(SA & 0x10); SMBus_Tx_Bit(SA & 0x08); SMBus_Tx_Bit(SA & 0x04); SMBus_Tx_Bit(SA & 0x02); SMBus_Tx_Bit(SA & 0x01); SMBus_Tx_Bit(0); /* 8th bis is a read command */ SMBus_Rx_Bit(); /* get ACK / NACK */ SMBus_Tx_Bit(addr & 0x80); /* device memory to read */ SMBus_Tx_Bit(addr & 0x40); SMBus_Tx_Bit(addr & 0x20); SMBus_Tx_Bit(addr & 0x10); SMBus_Tx_Bit(addr & 0x08); SMBus_Tx_Bit(addr & 0x04); SMBus_Tx_Bit(addr & 0x02); SMBus_Tx_Bit(addr & 0x01); SMBus_Rx_Bit(); /* second ACK / NACK */ SMBus_Restart(); /* Send second start, followed by SA (again) */ SMBus_Tx_Bit(SA & 0x40); /* 7 bit Slave Address, send top bit first */ SMBus_Tx_Bit(SA & 0x20); SMBus_Tx_Bit(SA & 0x10); SMBus_Tx_Bit(SA & 0x08); SMBus_Tx_Bit(SA & 0x04); SMBus_Tx_Bit(SA & 0x02); SMBus_Tx_Bit(SA & 0x01); SMBus_Tx_Bit(1); /* read command */ SMBus_Rx_Bit(); /* get ACK / NACK */ Temp.ucL = SMBus_Rx_Byte(); SMBus_Tx_Bit(0); /* ACK the first byte */ Temp.ucH = SMBus_Rx_Byte(); SMBus_Tx_Bit(0); /* second ACK */ SMBus_Rx_Byte(); /* PEC byte - ignore */ SMBus_Tx_Bit(0); SMBus_Stop(); } /* wait a given number of milliseconds */ void wait_ms(m) { unsigned int i; for(i = 0; i < m; i++) { __delay_us(978); } }