How to communicate with MLX90614 IR sensor


Closed Thread
Results 1 to 7 of 7
  1. #1
    Join Date
    Oct 2014
    Posts
    17

    Default How to communicate with MLX90614 IR sensor

    The MLX90614 IR sensor communicates using SMBus which requires the Start bit be repeated without a stop bit in between. I saw one posting that looked like PBP that showed the I2CREAD as as working with the 90614.

    sensortemp = 0
    reg = $07
    addr = 0
    I2CRead Tda, Tcl, addr, reg, [sensortemp.lowbyte, sensortemp.highbyte]

    where reg 7 is the location of the temperature data and addr 0 is the device address.

    The I2CREAD command has Control and Address, so maybe Control == addr and Address == reg? What about the repeated Start bit?

  2. #2
    Join Date
    Oct 2011
    Posts
    54

    Default Re: How to communicate with MLX90614 IR sensor

    8.4.6 of the datasheet shows how to read the temp. So going by this:-

    Default slave address is $5A. This is bits 1 to 7 of the first byte. Bit 0 is the read or write bit and as we are writing to the sensor this will be 0. The first byte sent will be $B4 (5A * 2 + 0).

    Next byte sent will be $07 the ram address of the data.

    Next byte sent will be the read address byte. Bit 0 of the read address is 1 so this will be $B5 (5A * 2 + 1). The PBP command will take care of this and the restart.

    The I2C address needs to be a constant. So I would try:-

    TEMP VAR BYTE[3]

    I2CREAD DataPin,ClockPin,$B4,$07,[STR TEMP\3]

    You may also need to add 'DEFINE I2C_HOLD 1'

    Best of luck
    Phil
    Last edited by Archangel; - 22nd February 2015 at 20:54.

  3. #3
    Join Date
    Oct 2004
    Posts
    440

    Default Re: How to communicate with MLX90614 IR sensor

    This is snippet from working MLX90614 code (other compiler) to give you a guideline:

    Code:
      Low I2C_SCL_Pin
      Low I2C_SDA_Pin
    
      I2C_Start()
      I2C_WriteByte($00) 'SLAVE ADDRESS
      I2C_WriteByte($07) '$07 = �000111 ADDRESS
      I2C_Restart()
      I2C_WriteByte($01) 'READ CMD
      sdTEMP_C.Byte0 = I2C_ReadByte()
      I2C_Ack()
      sdTEMP_C.Byte1 = I2C_ReadByte()
      I2C_Ack()
      yPEC = I2C_ReadByte()
      I2C_Stop()
    Norm
    Last edited by Archangel; - 22nd February 2015 at 20:56.

  4. #4
    Join Date
    Oct 2011
    Posts
    54

    Default Re: How to communicate with MLX90614 IR sensor

    Have you got 4k7 pullup resistors on the SDA and SCK lines?
    What PIC are you using?
    Show us your code and schematic and we may be able to help more.
    Phil
    Last edited by Archangel; - 22nd February 2015 at 20:55.

  5. #5
    Join Date
    Oct 2014
    Posts
    17

    Default Re: How to communicate with MLX90614 IR sensor

    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
    Last edited by Archangel; - 5th April 2015 at 04:36. Reason: code tags

  6. #6
    Join Date
    Oct 2014
    Posts
    17

    Default Re: How to communicate with MLX90614 IR sensor

    For my previous post I suggest replacing all the "pauseus 15" with:

    call wate

    And then add the subroutine;
    wate:
    pauseus 15
    return

    This should use less compiled code than having to integrate the assembly code for puaseus every time it is needed

  7. #7
    Join Date
    Oct 2014
    Posts
    17

    Default Re: How to communicate with MLX90614 IR sensor

    I said in my previous post there is probably a more elegant way to write this code. I used a combination of shiftin and shiftout along with some bit setting and reduced the number of lines of code compared to my previous post.

    Feel free to contact me if you have any questions.

    This code works for the MLX90614:

    '************************************************* ***************
    '* Name : MLX90614_shifts.BAS
    '* Author : Tom Baraniak [email protected]
    '* Notice : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS]
    '* : All Rights Reserved
    '* Date : 4/5/2015
    '* Version : 1.0
    '* Notes :
    '* :
    '************************************************* ***************
    '
    ' MLX90614 test using PIC16F688 at 8MHz
    '
    ' DOES WORK!!!
    '

    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

    reg var word
    addr var byte
    templo var byte
    temphi var byte
    temp var byte[3]
    TLOW var byte
    THI var byte
    sa var byte
    sb var byte
    sc var byte
    sd var byte
    tir var word
    j var byte
    command var byte
    ACK var byte
    tout var word
    TEMPIR var word


    SDA var portc.2
    SCL var portc.1
    TxD var portc.4 'transmitted data - hardware serial port
    RxD var portc.5 'received data


    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] 'used for testing, not part of the actual MLX code

    if command = "B" then
    call bitbang
    endif

    goto luup

    '================================================= ================================================== =======================================

    bitbang:

    SDA = 0 'start
    call wate
    SCL = 0 'clock idles low
    call wate

    reg = $07
    addr = $B4 'B4 sets W = 0 too
    shiftout sda, scl, 1, [addr] 'shift the address B4, 8 bits where LSB is W = 0
    'clock idles low mode!!

    input sda 'make sda an input for acknowledge A
    call wate
    scl = 1
    call wate
    scl = 0
    call wate
    output sda 'make sda an output again for 07


    shiftout sda, scl, 1, [reg] 'register is 07, clock idles low


    input sda 'make sda an input for acknowledge A
    call wate
    scl = 1
    call wate
    scl = 0

    call wate
    output sda 'make sda an output again for S
    call wate
    sda = 1
    call wate
    scl = 1
    call wate
    sda = 0
    call wate
    scl = 0
    call wate


    addr = $B5
    shiftout sda, scl, 1, [addr] 'shift the address B5, 8 bits where LSB is R = 1, clock idles low

    call wate
    input sda 'make sda an input for acknowledge A part of sequence. It remains an input heading into shiftin
    call wate
    scl = 1
    call wate
    scl = 0
    call wate


    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. clock idles low


    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 = ", 9, dec tout, 9, dec tempir, 9, dec THI, 9, dec TLOW, 13]


    pause 1000

    trisc.1 = 0 'both sda and scl are outputs
    trisc.2 = 0

    sda = 1 'they both start high
    scl = 1
    pause 100

    return

    '================================================= ================================================== =======================================

    wate:
    pauseus 15 'use a subroutine for the 15 usec dealy - less compiled code
    return


    end

Similar Threads

  1. Replies: 6
    Last Post: - 5th August 2013, 15:43
  2. Cheapest way to communicate
    By koossa in forum Off Topic
    Replies: 22
    Last Post: - 25th May 2009, 13:06
  3. Communicate PC-to-PC using PIC
    By aje_azam in forum USB
    Replies: 3
    Last Post: - 16th March 2009, 08:35
  4. What's the best way to communicate?
    By BobK in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 2nd October 2004, 07:54
  5. pc communicate with pic16f877
    By meyou in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 6th August 2004, 00:26

Members who have read this thread : 1

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts