After way too much time I got code that works with the MLX90614 temperature sensor. It may not be the most elegant but given the timing required by the SMBus this works.
I wish this sensor would have used the I2C standard. Things would have been a lot easier.
Code:'**************************************************************** '* Name : MLX90614_final.BAS '* Author : Tom Baraniak [email protected] '* Notice : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] '* : All Rights Reserved '* Date : 4/4/2015 '* Version : 1.0 '* Notes : '* : '**************************************************************** ' ' MLX90614 test using PIC16F688 running at 8MHz ' ' ' DEFINE OSC 8 '8 MHz clock frequency, others not supported by PBP define HSER_RCSTA 90h 'enable the serial port receiver define HSER_TXSTA 24h 'set up the serial port, enable transmit for fast clock define HSER_BAUD 9600 'select the baud rate, run slow for the RF xmitter define HSER_CLROERR 1 'automatically clear the buffer overrun error DEFINE SHIFT_PAUSEUS 20 'slow down the shift in clock or it is too fast for the MLX reg var word addr var byte TLOW var byte THI var byte tir var word j var byte command var byte ACK var byte FIXHI var byte tempir var word tout var word SDA var portc.2 SCL var portc.1 TxD var portc.4 RxD var portc.5 ' CMCON0 = %00000111 'comparator off OSCCON = %01110111 'runs at 8 MHz internal clock ADCON0 = %10000000 'ADC is disabled ANSEL = %00000000 'all digital TRISA = %11111111 'set up port A where 1 = input, 0 = output TRISC = %11101001 'set up port C where 1 = input, 0 = output ' ' '========================================================================================================================================== ' ' IR GROUND TEMPERATURE SENSOR ' ' The RAM address 0x07 contains the linearied object temperature data, low byte first ' The slave address that is the MLX90614 is 0xB4 ' ' sda = 1 'at the start scl = 1 pause 1000 luup: hserin 1000, luup, [command] if command = "B" then 'typing a "B" calls the temperature reading code. This is not part of the MLX code. call bitbang endif goto luup bitbang: SDA = 0 'start pauseus 15 'Can't be too fast so I added some delay. Easier to see on the scope too. SCL = 0 pauseus 15 'This segment generates salve address B4 1011010x where x is the 8th (unused) bit (actually W). Since W is a 0 anyway the x = 0. 'There may be a more elegant way of sending these 8 bits but this way works and all the timing and sequencing is correct. sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 pauseus 15 scl = 1 ' W pauseus 15 scl = 0 pauseus 15 input sda 'make sda an input for acknowledge A part of sequence pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 output sda 'make sda an output again to send register 0x07 sda = 0 pauseus 15 for j = 1 to 5 'for/next loop is quick for the 5 leading zeroes scl = 1 pauseus 15 scl = 0 pauseus 15 next sda = 1 'for/next loop for the three 1's for j = 1 to 3 pauseus 15 scl = 1 pauseus 15 scl = 0 next pauseus 15 input sda 'make sda an input for acknowledge A pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 output sda 'make sda an output again for S pauseus 15 sda = 1 pauseus 15 scl = 1 pauseus 15 sda = 0 pauseus 15 scl = 0 pauseus 15 'Like the code for B4 this segment generates B5 1011010x where x is the 8th (unused) bit (actually R). The x=1 (0101 == 5) which R is. 'Again, there may be a more elegant way of sending these bits but this works and the timing and sequence are correct. sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 '1 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 0 '0 pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 sda = 1 pauseus 15 scl = 1 ' R pauseus 15 scl = 0 pauseus 15 sda = 0 pauseus 15 input sda 'make sda an input for acknowledge A part of sequence. It remains an input heading into shiftin pauseus 15 scl = 1 pauseus 15 scl = 0 pauseus 15 shiftin SDA, SCL, 0, [TLOW, ack\1, thi] 'Now we can use the shiftin command to read the 8 least significant bits, the single acknowledge 'bit, and the 8 most significant bits. tempir = thi * $100 'shifts 8 bits to the left to move this byte to the upper 8 bits of a word tempir = tempir + tlow 'add the lower byte to the upper byte to make a word tout = tempir/50 'each bit is .02 degrees K so either multiply by .02 or divide by 50 tout = tout - 273 'subtract 273.15 (to get temperature in degrees C hserout ["T = ", dec tout, 9, dec tempir, 9, dec THI, 9, dec TLOW, 13] pause 1000 'added for readability during testing trisc.1 = 0 'both sda and scl are outputs to reset for the next time thru trisc.2 = 0 sda = 1 'they both start high scl = 1 pause 100 'not needed return end




Bookmarks