Shop OBEX P1 Docs P2 Docs Learn Events
Old MLX90614 Module vs. the actual MLX90614 device - programming ? — Parallax Forums

Old MLX90614 Module vs. the actual MLX90614 device - programming ?

xanatosxanatos Posts: 1,120
edited 2014-11-07 14:50 in General Discussion
I'm working with an MLX90614 directly, ie., not with the SX chip translating serial data into the SMBus format.

The I2C protocol supported by the BS2px should work for actually doing the talking - but what seems to be confusing me is all the stop & ack bits that get stuck in between data bytes. I've looked over both the old Parallax data for the Module, as well as the manufacturer's spec for the MLX device itself. Since there is the very real possibility I could write a command into this thing that would render it dumber than even I am, I am wondering if there are any gurus out there who have had experience with directly I2C'ing to one of these, OR... if the program code for the SX interpreter chip (From the Parallax Manual for the MLX Module: "Each sensor communicates with an SX20AC/SS-G coprocessor over a digital SMBus, which Parallax has programmed to simplify an otherwise fairly complex communication protocol.") might be available for me to peruse and see how they took the serial data sent to the SX, and turned it into the SMBus/I2C data format that the MLX needs to see (and vice versa).

I can't think of a better way to spend a snowed-in weekend. Well, actually I can, but... :-)

Thanks folks!

Dave

Manuals and a relavent forum post attached...

IR_Temp_Sens_Melixis_MLX90614.pdf
28040-28042-IRThermometer-v2.0.pdf
ParallaxPost-Trouble-commun.pdf

Comments

  • xanatosxanatos Posts: 1,120
    edited 2013-02-08 17:15
    Hi,

    Added info - my crappy code attempt. Below is the "Pseudo Code" from Melixis' application note on communicating with the MLX90614. It is the specific code for reading RAM address $07, where one of the temperature measurements gets stored by the device. Below that is where I have attempted to turn that code into real I2C code for my BS2p... Anyone want to take a poke at helping me understand how I have misinterpreted the pseudo-code, or the way I2C works, based on the example below? My debugs all yield 255s. Even with the MLX device removed from the circuit, unsurprisingly...
    ' 1. Send START Bit
    ' 2. Send Slave Address (0x00* FOR example) + Rd\-Wr Bit**
    ' 3. Send Command (0b000x_xxxx + 0b0000_0111 -> 0b0000_0111)     Command to read address 7 in RAM.
    ' 4. Send Repeated START_bit
    ' 5. Send Slave Address + Rd\-Wr Bit**
    ' 6. READ DATA Byte LOW (master must send ACK Bit)
    ' 7. READ DATA Byte HIGH (master must send ACK Bit)
    ' 8. READ PEC (master can send ACK OR NACK)
    ' 9. Send STOP Bit
    
    ' I2COUT Pin, SlaveID, { Address { \LowAddress }, } [ OutputData ]
    ' I2CIN Pin, SlaveID, { Address { \LowAddress }, } [ InputData ]
    
      I2COUT irD, $5A, [%1, $5A, $07, %1, $5A]     '$5A is factory default slave address for MLX
      I2CIN irD, $5A, [irVal]
      I2COUT irD, $5A, [%1]     '$5A is factory default slave address for MLX
      I2CIN irD, $5A, [irVal2]
      I2COUT irD, $5A, [%1]     '$5A is factory default slave address for MLX
      I2CIN irD, $5A, [posX]
      I2COUT irD, $5A, [%1]     '$5A is factory default slave address for MLX
    
      DEBUG "Val: ", DEC irVal, " ", DEC irVal2, " ", DEC posX, " ", CR
    

    Thanks...
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-08 21:08
    Hi Dave,

    I don't have direct experience with that device, but it seems to me that you might be making it more complicated than it needs to be. (I may have to eat those words!)

    What are all the %1 values you are sending?

    The slave address is usually a 7-bit address and has to be shifted one left to make room for the R/W bit. So a slave address of $5A=%1011010 becomes $B5=%10110101 when sent to the device, the final 1 calling out a read operation. When using I2CIN the Stamp will put a 1 in the least significant bit anyway.

    The command to read register 7 could be, my guess,
    I2CIN irD,$B5,$7,[irVal0,irVal1,pek]

    The Stamp will send the necessary command, the repeated start, and then it will read in the word of data, and the checksum. I don't think you have to use any I2COUTs at all. Declare the working variable as,
    irVal VAR Word
    irVal0 VAR irVal.byte0
    irVal1 VAR irVal.byte1
    pec VAR byte

    You can discard the checksum or not even bother to receive it. However, it appears that if you want to write to the configuration eeprom, it will expect a correct checksum or else it will abort.
  • xanatosxanatos Posts: 1,120
    edited 2013-02-09 09:28
    Hi Tracy, and thanks for the info. Unfortunately that - and several other shots-in-the-dark of my own, have not changed the output. I started with your suggestion above, and got all FFs on the values - same as before.

    So I thought I'd try examining the possibility that either my slave address was wrong, or possibly my understanding of the read addresses for the device were wrong, so I created a for/next loop that stepped through $00 to $FF for the slave address, and stepped from $00 to $09 for the RAM address on each step of the slave address. I got a very long column of FF FF.

    I must be fundamentally misunderstanding how to implement the I2C protocol with the MLX90614 in some way. I would have expected that SOMETHING I've tossed at the thing would have wiggled at least one bit on the output at some point, but I am apparently wrong in that expectation! :-)

    Still holding out hope that the code that Parallax used in the SX interpreter chip on board their module-ized version of the MLX90614 is still available somewhere, since the module has been discontinued.

    Thanks again for your ideas on this item... other ideas are always welcome! :-)

    Dave

    PS., Here's a summary of what I know about I2C and what I know about communications with the MLX90614. Maybe someone with Eagle Eyes and a truly saint-like willingness to help figure this out can see something I'm missing...
    'Currently using this I2C line:
    
      I2CIN irD, $5A, $07,[irVal0,irVal1,pec]      'irD is pin 0; 
                                                   '$5A is listed as default slave addr for the MLX (also tried $00 and $B5... and $00 - $FF); 
                                                   '$07 is a ram location to be read (also tried $00 to $09)...
    
    ' I2C Protocol for the IR Temp Sensor:
    ' The SDA and SCL pins must have 1k - 4.7k pull-up resistors. (using 4.7k pull-ups now)
    ' Pins MUST be either 0 & 1, or 8 & 9.  If 0, 0=SDA, 1=SCL; if 8, 8=SDA, 9=SCL  (using 0 & 1)
    ' Datarate on a px is 83kb/s (MLX must have datarate < 100khz for stability)
    '
    ' I2CIN Pin, SlaveID, { Address { \LowAddress }, } [ InputData ]                    ' From Stamp Manual
    ' I2COUT Pin, SlaveID, { Address { \LowAddress }, } [ OutputData ]
    '
    ' I2COUT 0, $A0, 5, [100]
    ' This code will transmit a "write" command to an I2C device (connected to I/O pins 0 AND 1), followed by an address of 5 AND finally will transmit the number 100.
    '
    ' value VAR Byte(13)
    ' I2CIN 0, $A1, 0, [value] ' receive the ASCII value for "V"   (example had an eeprom with ascii val 101 (v) stored
    ' I2CIN 0, $A1, 0, [DEC value] ' receive the number 3
    ' I2CIN 0, $A1, 0, [HEX value] ' receive the number $3A
    ' I2CIN 0, $A1, 0, [BIN value] ' receive the number %101
    ' I2CIN 0, $A1, 0, [STR value\13] ' receive the string "Value: 3A:101"
    '
    ' All the usual formatters apply...  incl. SPSTR L (drop vals into SPRAM), STR ByteArray \L, and WAITSTR ByteArray
    ' See the Stamp Manual pdf when actually coding - lots of info about addressing (or not), etc.
    '
    '
    ' Commands needed for communication with MLX90614, from MLX90614 datasheet/tech manual.
    ' 000x xxxx* RAM Access
    ' 001x xxxx* EEPROM Access
    ' 1111 0000** READ Flags
    ' 1111 1111 Enter SLEEP mode
    ' Note *: The xxxxx is the address of the cell that has to be accessed. READ/WRITE is selected via the READ/WRITE Bit
    ' Note**: Behaves like read command. The MLX90614 returns PEC after 16 bits data of which only 4 are meaningful
    ' and IF the MD wants it, it can STOP the communication after the first Byte. The difference between READ AND READ flags
    ' is that the latter does NOT have a repeated start Bit.
    '
    ' Most important RAM registers. For other registers in RAM and EEPROM memory refer TO MLX90614 datasheet.
    ' Ambient sensor DATA 0x03
    ' IR sensor 1 data 0x04
    ' IR sensor 2 data 0x05
    ' Linearized ambient temperature TA 0x06
    ' Linearized object temperature Tobj1 0x07
    ' Linearized object temperature Tobj2 0x08
    '
    ' All bytes are sent AND received with MSb first.
    
    ' RAM memory is read only via SMBus. The reading data are divided by two, due to a sign bit (Sn) in RAM (FOR example, TOBJ1 - RAM address 0x07h will sweep
    ' between 0x27ADh to 0x7FFF as the object temperature rises from -70.01°C to +382.19°C). The MSb READ from RAM is an error flag (active HIGH) FOR the linearized
    ' temperatures (TOBJ1, TOBJ2 AND Ta). The MSb for the raw DATA (e.g. IR sensor1 DATA) is a sign Bit (sign and magnitude format).
    ' Pseudo code example: Reading RAM address 0x07 (Tobj1)
    ' 1. Send START Bit
    ' 2. Send Slave Address (0x00* FOR example) + Rd\-Wr Bit**
    ' 3. Send Command (0b000x_xxxx + 0b0000_0111 -> 0b0000_0111)     Command to read address 7 in RAM.
    ' 4. Send Repeated START_bit
    ' 5. Send Slave Address + Rd\-Wr Bit**
    ' 6. READ DATA Byte LOW (master must send ACK Bit)
    ' 7. READ DATA Byte HIGH (master must send ACK Bit)
    ' 8. READ PEC (master can send ACK OR NACK)
    ' 9. Send STOP Bit
    '
    ' Note* : Any MLX90614 will respond TO address 0x00
    ' Note**: Bit Rd\-Wr has no meaning FOR MLX90614
    
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-09 14:30
    Dave,
    What do you mean by,
    ' Note**: Bit Rd\-Wr has no meaning FOR MLX90614?

    The diagrams are quite explicit about the presence of the Rd/Wr bit.
    You can see in the data sheet example, that the default slave address $5A has been shifted up one bit and sent as $B4 for a write and $B5 for a read. There doesn't seem to be anything peculiar about the protocol.

    Screen shot 2013-02-09 at 2.12.38 PM.png

    Screen shot 2013-02-09 at 2.13.16 PM.png



    There is also a general call slave address, zero. In order to check or change the slave address, send the general call, and the device is supposed to respond no matter what its current SA. There has to be only one device on the buss for that to work.

    Just checking, do you have the 5V version of the chip (MLX90614ESF-AAA)?
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-09 15:01
    A project using a PIC with the MLX90614:
    building-your-own-ir-thermometer-part1
  • xanatosxanatos Posts: 1,120
    edited 2013-02-09 15:13
    What do you mean by,
    ' Note**: Bit Rd\-Wr has no meaning for MLX90614?

    The diagrams are quite explicit about the presence of the Rd/Wr bit.

    Just checking, do you have the 5V version of the chip (MLX90614ESF-AAA)?

    That "Note" is actually from the MLX90614 datasheet - that whole block of text was copied and pasted from their material. So, I have no idea what it means! :-) And yes, I do have the 5V version. Also, not only have I tried $5A, and $B4 and B5, but I created a counter loop and tried every address from $00 to $FF! So far a complete exercise in futility.

    I'm looking at that PIC code again - also found one for Arduino. Pertinent PIC Code extract is here, although I'm not very fluent in PICese...:
    MLX90614_ReadSensorTemp
    	global	MLX90614_ReadSensorTemp
    	
    	; start
    	call	SMBusSendStart
    	
    	; send slave addr
    	movlw	0x00		; b'0000000X' Slave addr + b'XXXXXXX0' ReadBit
    	call	SMBusSendByte
    	; send commando
    	movlw	0x06		; Read sensor temp
    	call	SMBusSendByte
    	; send re-start
    	call	SMBusSendReStart
    	; send slave addr
    	movlw	0x00		; b'0000000X' Slave addr + b'XXXXXXX0' ReadBit
    	call	SMBusSendByte
    	
    	SwitchToRead
    	; read LSB
    	call	SMBus_ReadByte
    	movwf	TempSensorL
    	; read MSB
    	call	SMBus_ReadByte
    	movwf	TempSensorH
    	; read PEC
    	call	SMBus_ReadByte
    	SwitchToWrite
    
    	call	SMBus_Delay_7us
    	call	SMBus_Delay_7us
    	call	SMBus_Delay_7us
    	call	SendStop
    	return
    	
    MLX90614_ReadObjectTemp
    	global	MLX90614_ReadObjectTemp
    	; start
    	call	SMBusSendStart
    	
    	; send slave addr
    	movlw	0x00		; b'0000000X' Slave addr + b'XXXXXXX0' ReadBit
    	call	SMBusSendByte
    	; send commando
    	movlw	0x07		; Read object temp
    	call	SMBusSendByte
    	; send re-start
    	call	SMBusSendReStart
    	; send slave addr
    	movlw	0x00		; b'0000000X' Slave addr + b'XXXXXXX0' ReadBit
    	call	SMBusSendByte
    	
    	SwitchToRead
    	; read LSB
    	call	SMBus_ReadByte
    	movwf	TempObjectL
    	; read MSB
    	call	SMBus_ReadByte
    	movwf	TempObjectH
    	; read PEC
    	call	SMBus_ReadByte
    	SwitchToWrite
    
    	call	SMBus_Delay_7us
    	call	SMBus_Delay_7us
    	call	SMBus_Delay_7us
    	call	SendStop
    	return
    
    SMBusSendByte
    	global	SMBusSendByte
    	
    	movwf	Byte
    	movlw	.8
    	movwf	Counter
    SMBusSendByte_Loop	
    	bsf		BIT			; set the correct value into BIT
    	btfss	Byte, 7		;  "
    	bcf		BIT			;  "
    	call	SendBit     ; write BIT to the bus
    	rlf		Byte, F		; prepare for next round
    	decfsz	Counter
    	goto	SMBusSendByte_Loop
    	
    	; read the ACK bit
    	SwitchToRead
    	call	ReadBit
    	bsf		ACK_BIT		; store the ACK bit into ACK_BIT
    	btfss	BIT			;  "
    	bcf		ACK_BIT		;  "
    	SwitchToWrite		; switch back to normal state
    	
    	call	SMBus_Delay_7us ; wait a bit to show a cap between each byte+ack transaction
    	return
    
    SMBus_ReadByte
    	global	SMBus_ReadByte
    	
    	movlw	.8
    	movwf	Counter
    SMBus_ReadByte_Loop
    	rlf		Byte, F
    	call	ReadBit
    	bsf		Byte, 0
    	btfss	BIT
    	bcf		Byte, 0
    	decfsz	Counter
    	goto	SMBus_ReadByte_Loop
    
    	SwitchToWrite
    	bcf		BIT			; ACK == 0
    	call	SendBit
    	SwitchToRead
    
    	movfw	Byte
    	return
    		
    SendBit
    	; pre-condition is that the CLOCK is LOW
    	
    	; set the SDA line according to the requested value
    	DATA_LOW
    	btfsc	BIT
    	DATA_HIGH
    
    	call	SMBus_Delay_4_5us
    	
    	; next, wait T_su:dat (250ns) before raising the CLK
    	if CLOCKSPEED == .4000000
    		nop
    	else 
    		if CLOCKSPEED == .8000000
    			nop
    			nop
    		else
    			error	"Unimplemented clockspeed"
    		endif
    	endif
    	
    	; set clock to high, signalling that the value from SDA can now be read
    	CLOCK_HIGH
    	call	SMBus_Delay_7us ; HIGH_time should be between 4.0us and 50us
    	
    	; now the receiver is finished reading the SDA line, lower the CLK and get ready to send the next bit
    	CLOCK_LOW
    	call	SMBus_Delay_4_5us ; at least 4.7us, timeout after 27ms
    	
    	; done
    	return
    
    
    

    Hmmmmmm....
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-09 15:26
    Interesting, the PIC code uses the general call address, zero, not the default address, $5A.

    It might be interesting to probe the line with a Salae logic analyzer to be sure everything matches up with the example in the data sheet.
  • xanatosxanatos Posts: 1,120
    edited 2013-02-09 15:30
    Wish I had a Salae logic analyzer... :-)

    Also found this Swordfish Basic code for the PIC and the MLX:
    Device = 18F2620
    Clock = 20
    Include "usart.bas"
    Include "convert.bas"
    Include "mlxir.bas"
    Dim TAC As Float
    Dim TAF As Float
    Dim TOC As Float
    Dim TOF As Float
    // main program...
    USART.SetBaudrate(br9600)
    Repeat
    If MLXIR.ReadMLXTemps(TAC,TAF,Ambient) And MLXIR.ReadMLXTemps(TOC,TOF) Then
    USART.Write("Ambient Temp: ",FloatToStr(TAF,1),
    "F Object Temp: ",FloatToStr(TOF,1),"F",13,10)
    Else
    USART.Write("ERROR - Unable to read sensor")
    End If
    DelayMS(1000)
    Until false
    Module code:
    Module MLXIR
    Include "i2c.bas"
    //Ram Register addresses
    Public Const
    Ambient_Sensor_Data = $03,
    IR_Sensor1_Data = $04,
    IR_Sensor2_Data = $05,
    Ambient = $06,
    Object1 = $07,
    Object2 = $08,
    Ta1_PKI = $0A,
    Ta2_PKI = $0B,
    Scale_Alpha_Ratio = $13,
    Scale_Alpha_Slope = $14,
    IIR_Filter = $15,
    Ta1_PKI_Fraction = $16,
    ta2_PKI_Fraction = $17,
    FIR_Filter = $1B
    //Rom Register addresses
    Public Const
    TOmax = $00,
    TOmin = $01,
    PWMctrl = $02,
    Ta_Range = $03,
    Ke = $04,
    ConfigR1 = $05,
    SMBus_Address = $0E,
    ID_1 = $1C,
    ID_2 = $1D,
    ID_3 = $1E,
    ID_4 = $1F
    Public Const
    Rom = true,
    Ram = false
    Const Tries = 5 //number of read/write tries until error is declared
    Dim CRC As Byte
    Swordfish Wiki | SwordfishUser / MLX90614 browse Page 1 of 4
    http://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.MLX90614 2/8/2013
    {
    *******************************************************************************
    * Name : CRC8smb *
    * Purpose : local helper function to provide SMB bus CRC8 calculations *
    * : module level variable CRC contains the old CRC value *
    *******************************************************************************
    }
    Function CRC8smb(pData As Byte) As Byte
    Dim Index As Byte
    pData = pData Xor CRC //xor new byte and old crc to get remainder + byte
    For Index = 0 To 7 //check all 8 bits
    If pData.7 =1 Then //if bit 7 is a 1
    pData = pData << 1 //shift it out
    pData = Pdata Xor $07 //then xor with the polynomial
    Else //if the bit is not a 1
    pData = pData << 1 //just shift it out
    End If
    Next //check next bit
    Result = pData
    End Function
    {
    *******************************************************************************
    * Name : ReadMLX *
    * Purpose : Reads Ram or Rom location. Defaults to reading RAM at Slave *
    * : address 0. pRegister should be selected from the constants list. *
    * : Function returns a false if the read is not successful. *
    *******************************************************************************
    }
    Public Function ReadMLX(ByRef pData As Word,pRegister As Byte,
    pRom As Boolean = false,
    pSAddress As Byte = 0) As Boolean
    Dim SAddressRead As Byte
    Dim SAddressWrite As Byte
    Dim PEC As Byte
    Dim ReadTries As Byte
    SAddressRead = (pSAddress << 1) + 1 //construct slave address for read
    SAddressWrite = pSAddress << 1 //construct slave address for write
    pRegister.5 = 0 //working with RAM
    If pRom Then
    pRegister.5 = 1 //working with ROM
    End If
    ReadTries = Tries
    ReadStart:
    I2C.Start //follow spec for register reads
    I2C.WriteByte(SAddressWrite)
    I2C.WriteByte(pRegister)
    I2C.Restart
    I2C.WriteByte(SAddressRead)
    pData.Byte0 = I2C.ReadByte(0) //contents are 16 bits wide
    pData.Byte1 = I2C.ReadByte(0)
    PEC = I2C.ReadByte(0)
    I2C.Stop
    //calculate CRC after communications to not affect SMB bus timing
    CRC = 0 //initialize CRC
    CRC = CRC8smb(SaddressWrite) //accumulate CRC
    CRC = CRC8smb(pRegister)
    CRC = CRC8smb(SaddressRead)
    CRC = CRC8smb(pData.byte0)
    CRC = CRC8smb(pData.byte1)
    CRC = CRC8smb(PEC) //CRC should = 0 with no error
    While CRC <> 0 //If CRC is not zero
    Dec(ReadTries) //count down 1 try
    If ReadTries = 0 Then //if timeout is zero
    Result = false //the function failed after
    Exit //TimeOut tries
    End If
    GoTo ReadStart //otherwise try again
    Wend
    Result = true
    End Function
    {
    *******************************************************************************
    * Name : ReadMLXTemps *
    * Purpose : Reads temperature in C and F *
    * : pRegister should be Ambient, Object1 or Object2. Default is *
    * : Object1 at Slave Address 0. Function returns a false if read *
    * : is not successful. *
    *******************************************************************************
    }
    Public Function ReadMLXTemps(ByRef pTC As Float,ByRef pTF As Float,
    pRegister As Byte = Object1,
    pSAddress As Byte = 0) As Boolean
    Swordfish Wiki | SwordfishUser / MLX90614 browse Page 2 of 4
    http://www.sfcompiler.co.uk/wiki/pmwiki.php?n=SwordfishUser.MLX90614 2/8/2013
    Dim RawData As Word
    If ReadMLX(RawData,pRegister,Ram,pSAddress) Then
    pTC = RawData*0.02 - 273.15 //kelvin to C
    pTF = (pTC*9)/5 + 32 //C to F
    Result = true
    Else
    Result = false
    End If
    End Function
    {
    *******************************************************************************
    * Name : WriteMLXRom *
    * Purpose : Writes to Rom location. pRegister should be selected from the *
    * : constants list. pSAddress defaults to Slave Address 0. *
    * : Use with care, writes to some ROM locations will erase device *
    * : calibration constants. *
    *******************************************************************************
    }
    Public Function WriteMLXRom(pData As Word,pRegister As Byte,
    pSAddress As Byte = 0) As Boolean
    Dim SAddressWrite As Byte
    Dim TimeOut As Byte
    Dim WriteTries As Byte
    SAddressWrite = pSAddress << 1 //construct slave address for write
    pRegister.5 = 1 //construct cmd, ROM + Reg address
    //calculate CRC before initiating communications so SMB bus timing won't
    //be affected. SMB bus can be stalled but unlike I2C it has a timeout.
    //this eliminates having to write timing routines.
    CRC = 0 //initialize CRC
    CRC = CRC8smb(SAddressWrite) //accumulate CRC
    CRC = CRC8smb(pRegister)
    CRC = CRC8smb(pData.byte0)
    CRC = CRC8smb(pData.byte1)
    WriteTries = Tries
    WriteStart:
    I2C.Start //follow spec for ROM writes
    I2C.WriteByte(SAddressWrite)
    I2C.WriteByte(pRegister)
    I2C.WriteByte(pData.byte0)
    I2C.WriteByte(pData.byte1)
    I2C.WriteByte(CRC)
    TimeOut = $FF
    While NotAcknowledged //look for ack, if no ack then
    Dec(TimeOut) //count down 1 loop
    If TimeOut = 0 Then //if timeout with no ack
    I2C.Stop //place stop on SMB bus
    Dec(WriteTries) //decrement number of tries
    If WriteTries = 0 Then //when # of tries reach 0
    I2C.Stop //stop everything
    Result = false //and fail with error
    Exit
    End If //if # of tries not exceeded
    GoTo WriteStart //then try again
    End If
    Wend
    I2C.Stop
    Result = true
    End Function
    //Initialize
    I2C.Initialize
    

    Still confused.......
  • xanatosxanatos Posts: 1,120
    edited 2013-02-09 17:33
    Also... just tried using a second MLX90614 just in case, and also switched the BS2p pins from 0/1 to 8/9 to eliminate that as a possibility as well. Still all FFs.

    I'm stumped for the moment.

    Dave
  • xanatosxanatos Posts: 1,120
    edited 2013-02-10 18:46
    OK, here's the issue, apparently. My BS2p40 doesn't like I2C. Pretty simple. So here's what I am seeing....

    When I watch the SDA or SCL lines with my scope (I have a 4.7k pull-up on each line) and I issue the I2CIN command as in the program below, I get nothing. The line stays a solid DC 5v.

    So I thought the BS2p40 might be fried on those output lines, and I wrote the little HIGH/LOW loop you'll see in the code below (currently commented out). I then commented out the I2C line. The pin cycles perfectly.

    I2C Command - nothing. HIGH/LOW loop, nice square wave.

    Is there something I'm supposed to do to "prime" the Stamp for I2C??? Why would the stamp NOT respond to I2C? It should be noted that the stamp also outputs SEROUT just fine (to a video overlay system), and does SHIFTOUT and SHIFTIN just fine as well (DS1302). Just - nothing - with I2C.

    Ideas?
    ' {$PBASIC 2.5}
    ' {$STAMP BS2p}
    ' -----[ I/O Definitions ]-------------------------------------------------
    
    irD             PIN     0                ' MLX IR Temp Sensor SDA
    irC             PIN     1                ' MLX IR Temp Sensor SCL
    
    ' -----[ Variables ]-------------------------------------------------------
    
    irVal           VAR     Word
    irVal0          VAR     irVal.BYTE0
    irVal1          VAR     irVal.BYTE1
    pec             VAR     Byte
    
     ' -----[ Program Code ]----------------------------------------------------
    
    main:
    
      I2CIN 0, $5A, $07, [irVal0,irVal1,pec]
    
      'OUTPUT 0
      'HIGH 0
      'PAUSE 40
      'LOW 0
      'PAUSE 40
    
    GOTO main
    
  • homosapienhomosapien Posts: 147
    edited 2013-02-10 20:11
    I use the MLX90614 with the propeller chip and have no issues. I haven't used the Basic Stamp since the SX came out, so I'm a little rusty with the syntax of the language, but I'll give it a shot:

    You need to make sure the I2CIN command is working, which it probably is. I believe in the code you posted, the delays of your manual toggling (40ms, I believe) are waaay longer than the clock pulses which will be sent out by the I2CIN command. (I think <but may be wrong> that the I2C clock pulses for the BS2p I2CIN command will be ~10us). Attach your probe to SCL line and make sure your time divisions on the O-scope are short enough to pick up the clock pulses. When you have that nailed down, we can move on...


    Nate
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-02-10 21:26
    Just to be sure there is not something fishy in the connection of the pullup resistors, do an open drain test sequence.
    out0 = 0
    DO
      dir0 = ~dir0  ' pullup high, drive low.
    LOOP
    

    Same with p1. The fact that the pins is stuck high means either that the i2c command is not pulling the line low to send the $5A (unlikely), or the MSX is forcing the line high (unlikely, although the MSX does have a pwm mode), or that you are not seeing the $5A zip by on the 'scope.

    Is your 'scope analog or digital? In either case, in the code add a pulse right before the i2c command and use that pulse to sync the scope. Improves the chance to see what is there.
    DO
      HIGH 2   ' sync 'scope sweep to rising edge on p2.
       I2CIN 0, $5A, $07, [irVal0,irVal1,pec]
      LOW 2
    LOOP
    

    The i2c command does work. I use it extensively. Do you have another i2c chip on hand that you could try, a memory or rtc or something?
  • xanatosxanatos Posts: 1,120
    edited 2013-02-11 10:54
    Hi Tracy & Homosapien,

    Tracy: I did go cannibalize another BS2p chip from another project, and I now see the I2C data on my scope, so it was an issue with my BS2p40 (and I did check to be sure I was in MAINIO). However, I am still seeing only FF's on my three variables. I've tried slave address 00, 5A, B4, B5..... but as I now understand, the I2C command apparently takes care of those bits and shifts. I'm not sure what else I have around here that uses I2C. I'll look around and see. As for my scope... embarrased to say it's a DSO Nano :-) But it does do the job - and it does display the I2C data line, just not in a readable format. It displays it as a jittery, shifting-all-over bunch of square 0-5v pulses. When I change the SA and RA between 00 and FF I can tell the difference, but that's about it! lol...

    Homosapien: The code I listed above has comment characters in it. Those 40ms delays are not in play with the I2CIN command - that's a segment I wrote only to test to see if the BS2p40's pin 0 was stuck high, or would toggle. So when I run THIS line ONLY:
    main:
    
      I2CIN 0, $5A, $07, [irVal0,irVal1,pec]
    
      PAUSE 100
    
    GOTO main
    

    I saw only a high level on my scope. But when I ran THIS code only:
    main:
    
      OUTPUT 0
      HIGH 0
      PAUSE 40
      LOW 0
      PAUSE 40
    
    GOTO main
    

    I saw the pin toggling properly. These two sections of code were not used simultaneously. One was only used to verify that the pin wasn't stuck high. But I have - as mentioned above - subsequently found that there is something wrong with that one BS2p40 chip.

    SO..... since you've used the Prop with the MLX, and we now know that I have a working I2C pin set on the new chip, and I can see the I2C data now... can you offer some ideas? One thing I'm wondering is if somehow I managed to configure my MLX to be operating in PWM (although the spec sheet states that Power On Default mode is SMBus). I know that it's possible to write to an EEPROM location that changes the POD mode.... but if that were true, would I not see the PWM signal continuously from the SDA line on the MLX on power up? I'm just shooting in the dark at this point......

    Thanks for ideas folks. I'm going to call Parallax as well and see who wrote the code that was in the on-board SX chip on the original MLX Modules... maybe I can glean some info from that side.

    Dave
  • homosapienhomosapien Posts: 147
    edited 2013-02-11 12:08
    Hi Dave,

    I realize you probably were not running both bunches of code at the same time, but I was wondering if you ran the 'manual toggle' section, saw it on the scope, and then tried to run the I2CIN part with the scope on the same settings, perhaps the I2CIN output was flashing by so fast that you were not seeing it (not that this is a mistake I have ever made..err...umm.... anyhow...).

    Very strange that the pins seem to work but do not output I2CIN. Any chance it is not a BS2p chip, but a different one? I recall that not all Stamps run the I2CIN function, I cannot remember if the software tells you there is an error when you say in the program {@STAMP BS2p} but download it to a different kind of Stamp. (Please don't take offence at my silly mistake suggestions, I have pretty much made them all myself, I'm just trying to long-distance diagnose and not miss the obvious ones...).

    In any case, I can probably look at my code this evening (which is a mashup of OBEX code and my modifications), but right now can tell you some things from (hazy) memory: When I was planning on using the MLXxx sensor, I googled it and found many people were having issues with the device address. The code I am using just uses the 'general' addressing (ie 0 for the address) because there are no other devices on the I2C lines, so I never really got into the address issue. Also, I supply power to the MLXxx from a pin on the prop, I believe there were issues if the device was powered up at the same time as the uP (device getting into unknown state due to rising voltages on the device power/I2C lines at power up (I think). So my code allows the prop to start, then pauses for ~1s, then turns power to the MLXxx on, gives it ~1s to settle, then begins I2C comms. I would recommend you try those two things and see if you can get any response from the device.

    I will say from experience, it really helps to have a scope that can see (as in actual high/lows) the I2C comms for trouble shooting (I had a device <NOT MLXxx>. which unbeknownst to me was using 'clock stretching' which had me scratching my head for the better part of a day...O'scope saved my butt).


    Nate
  • xanatosxanatos Posts: 1,120
    edited 2013-02-11 12:22
    Hi Nate,

    Thanks for the ideas. It is, however, VERY difficult to mistake a BS2p40 for any of the other BS2 chips... :-)

    And my scope was able to differentiate the I2C signal on the same settings I had for the 40ms 50% duty cycle. I expanded it out a little, but again - it turned out that the first BS2p40 is, for some reason, simply not interested in doing I2C ... but the one I am using now is. I am actually waiting for the BS2px chips, which unfortunately won't ship until March 1st or thereabouts. Those are the ones that will be used in the final version of this project, which is doing a number of things in addition to, hopefully, reading MLX90614 data...

    Plus I believe (but have not tested) that the chips that do not support I2C will error out when tokenizing the code, if you make an I2C call in them... they probably say it's undefined or something.

    I'll try the delayed start thing and let you know.

    Best,

    Dave
  • xanatosxanatos Posts: 1,120
    edited 2013-02-11 13:18
    Some interesting finds. Below find two photos, one of them, with the data pattern clear as day, is the SDA line (pin 0 of the Stamp) when the SCL line is DISCONNECTED. The other is the SAME pin (0, SDA), but the SCL line is connected. There are transitions in those little spikes in between the square waves, but they are much higher in frequency and impossible to resolve enough to take a picture - I can expand the display out, but can't trigger with this scope reliably enough to photograph them. It looks like data - but just an enormous amount of high level, followed by the tiny data spike, then another long high...

    Just wondering if this sheds any light on anything for anyone who is more knowledgable on the I2C protocol than I (meaning most of you).

    Thanks,

    Dave

    SCL Line (pin 1) DISconnected:
    I2C-NoSCL.jpg


    SCL Line CONNECTED:
    I2C-SCL_Connected.jpg


    Note that SCL and SDA both have 4.7k pullups on them as spec'd by the MLX Manufacturer.
    1000 x 750 - 180K
    1000 x 750 - 148K
  • homosapienhomosapien Posts: 147
    edited 2013-02-12 07:09
    Hi Dave,

    Did you try using 0 as your device address and controlling the MLXxx power with a Stamp pin so you can do a 'reset' in software? I would highly recommend it to know that you are starting from the most basic, clean configuration that you can.

    Re the screen shots: I think they may be confusing the issue, that is why I think you should start with the above basic configuration before getting into the bits, so to speak. If the above basic configuration does not give you any results, then a screen shot may be helpful, esp if you can send one simultaneously showing 2 channels, the SDA and SCL lines, and the code that is driving the lines.


    Nate
  • xanatosxanatos Posts: 1,120
    edited 2013-02-12 12:47
    I have tried address 00 for the SA, same results - but I will try the power resetting function you describe, and I'll post my findings.

    Dave
  • xanatosxanatos Posts: 1,120
    edited 2013-02-13 17:40
    The continuing saga of my I2C issues:

    I hooked up a 24LC32A EEPROM, which is an I2C device, and loaded a small program to write to an address, then clear the value in the program and read it back. Works like a CHARM. I can write to and read from any address in the 24LC32A without a single hitch using the wiring setup I have to my BS2p40. This eliminates the BS2p40 AND my wiring as being an issue.

    Hooked up the MLX90614 to the exact same wiring/chip, and got the exact same bunch of FFs I've been getting all along. So I tried the power-on to the Stamp with the MLX device being controlled by the pin on the stamp, issued a 1000ms power down, then powered up the pin and started reading from the device after another 500ms "settle" time. All FFs.

    So I wrote the little program here, which polls EVERY address from $00 to $FF, and every location at EACH of those addresses, from $00 to $08, and - all FFs.

    There is NO DOUBT possible any longer that the issue could be with the BS2p40 or the SDA/SCL wiring. It's something about either what the MLX is looking for, or about the MLX Device itself.
    ' =========================================================================
    '
    ' {$STAMP BS2p}
    ' {$PBASIC 2.5}
    
    ' =========================================================================
    
    ' -----[ I/O Definitions ]-------------------------------------------------
    
    SDA            PIN      0              ' I2C Serial Data Line
    SCL            PIN      1              ' I2C Serial Clock Line
    
    ' -----[ Variables ]-------------------------------------------------------
    
    value          VAR      Byte           ' Variable Used To Store Value
    irAddr         VAR      Byte
    irLoc          VAR      Nib
    
    ' -----[ Main Routine ]----------------------------------------------------
    DO
      FOR irAddr = $00 TO $FF
        FOR irLoc = $00 TO $08
          PAUSE 10
          value = 0
          I2CIN SDA, irAddr, irLoc, [value]
          DEBUG CR, "Value stored at location ",HEX irAddr, " in location ", HEX irLoc, " is ", DEC value, CR
          IF value <> 255 THEN END
        NEXT
      NEXT
    LOOP
    

    The line at the end is just so that if I EVER got any result other than 255 for the value, the program would end so I could see what the addr and location values were where I got something other than 255. But the program never ends... :-)

    I refuse to give up................

    SO... I tried expanding the RAM locations - instead of just 0 to 8, I tried $00 to $FF (and expanded irLoc to a Byte from a Nib). Now something seemingly interesting happens...
    DO
      FOR x = 0 TO 2
      IF x = 0 THEN irAddr = $01
      IF x = 1 THEN irAddr = $B4
      IF x = 2 THEN irAddr = $B5
        FOR irLoc = $0 TO $FF
          value = 0
          I2CIN SDA, irAddr, irLoc, [value]
          DEBUG CR, "Value stored at address ",HEX irAddr, " in location ", HEX irLoc, " is ", HEX value, CR
          IF value <> 255 THEN PAUSE 2000
        NEXT
      NEXT
    LOOP
    

    Now, Slave Addresses 01, B4, B5, at RAM location F0 all = 1, instead of FF. That's it... no other change. EF and F1 for a given SA are all still FF, but F0 gives me a 1. Unfortunately the MLX Manual says that address doesn't exist...

    MLXRAM.jpg


    The saga continues. If anyone is still reading this, and this triggers any ideas... I'm all ears.
    1008 x 402 - 90K
  • homosapienhomosapien Posts: 147
    edited 2013-02-14 06:47
    Hi David,

    What model of the MLX90614ESF are you using? ie MLX90614-xxx-000-TU, what are the 3 letters that I have marked as xxx. They should be something like 'BAA', 'ACF' etc. The side of the device will have this printed on it. Can you tell me where you purchased it?


    Nate
  • xanatosxanatos Posts: 1,120
    edited 2013-02-14 16:12
    Hi there!

    From Digikey: MLX90614ESF-ACF-000-TU-ND

    Digikey website states it is: THERMOMETER IR 5V TO-39

    Anything of interest?

    Dave
  • xanatosxanatos Posts: 1,120
    edited 2013-02-15 19:47
    Trying another tack: Just use the original Parallax sensor board. Received one from SRLM which appears to work, but of course it's using SERIN and SEROUT via a single pin on an SX interpreter chip. So I can get a reading with this device - but it's NOT the 10 degree FOV unit... appears to be a 90 degree FOV unit, so unless the item under test is directly in front of the unit, it just gets lost in ambient. I tried putting the shroud from my 10 deg FOV unit onto the 90 deg FOV unit, but there seems to be more to making the 90 degree unit into a 10 degree unit than just putting teh lensed shroud onto it. Probably values programmed in.

    However, as I said, the sensor in that unit is working. Just not getting real comm with a direct Stamp to MLX90614 connection via I2C. And it appears I still need to go that route. Anyone still watching ? :-)

    Dave
  • xanatosxanatos Posts: 1,120
    edited 2013-02-17 07:56
    More light shed on the issue. Apparently Arduino users cannot use their standard I2C library to communicate with this device - there is some significant difference between standard I2C and the MLX90614's I2C. Instead, the Arduino people have to use the i2cmaster.h library, which is an open source thing that needs to still be modified in order to get the thing to run. From bilder.org:

    ..."Then, looking around, the MLX90614 seemed to be giving some people a hard time when trying to connect it to their Arduino. So… we at bildr did what we do best, we bought one, and took some time to make your lives easier and get this running. This is an I2C device like many sensors we have talked about before, but unlike all the I2C sensors we have written about before this, the MLX90614 can’t use the wire library to communicate with it, so we will be using another library, ...i2cmaster.h..." (http://bildr.org/2011/02/ - about half way down the page). So I'm guessing that teh standard I2C protocol in the Stamps probably has the same characteristics that makes the Arduino need a separate version of I2C in order to communicate with this device...
  • DomanikDomanik Posts: 233
    edited 2014-10-27 21:31
    Dave,
    I know this thread is old but was wondering if you've had success with your project and found more boards. From reading your posts it seems you are using several of these. Are you still looking for the original boards or does something else work?

    I'm very interested in doing some things with this part but I'm new to the Propeller, mostly dabling in C going thru tutorials. I just ordered a 10 degree MLX90614 from Digikey. What do you think?
    Thanks,
    Dom..
  • xanatosxanatos Posts: 1,120
    edited 2014-10-28 07:36
    Hi Dom,

    All I can say is good luck. You can't use any standard I2C on that part. The Propeller may well be equipped to create its own Franken-2C and talk to it, but the Stamp, which I could get to talk to a wooden door if I needed, cannot communicate with the MLX, it's just not capable of doing the fractional bit-shifting timing wierdness that the MLX needs. The original Parallax module solved this issue by having a separate microcontroller on board that handled the translation. I wound up finding an old Parallax module, then replacing the installed wide-angle MLX with the narrow angle MLX, and I got it to work with that. If you do get the mLX working with the Prop, I believe that'll be a welcome addition to the OBEX library for the MLX (if there isn't already some driver in there).

    When working, those MLX90614 devices are interesting. It was able to read a soldering iron crossing it's field at 3 feet (although it averages the soldering iron's temperature and radiative area in with the full field of vision, so at three feet the soldering iron showed up as being about 130 F with an ambient BG temp of about 70 F and at about 8 feet the soldering iron was nearly indistinguishable from BG).

    Good luck & keep us posted!

    Dave
  • DomanikDomanik Posts: 233
    edited 2014-10-28 23:16
    Dave,
    I just finished slugging my way through the 52 page datasheet. Based on their timing diagrams and descriptions I don't see any reason the Propeller can't do it. It's a little dicey and the datasheet is filled with caveats, but I made a list. The biggest problem I have is my lack of knowledge of C and writing a driver for it. I saw something in OBEX but it was in spin. That might be a template. Sure would like to get the thing to work. It is an incredible part, much more than just temperature sensing.
    Thanks for getting back to me.

    Dom...
  • DomanikDomanik Posts: 233
    edited 2014-11-07 14:50
    Dave,
    Spent several hours with MLX90614 and, using a scope, finally got it talking. Can now read anywhere in the eeprom and RAM including the device address 0x5A. It actually has 0xeb5A but only uses the lower 2 digits. When reading the temp Ta, Tobj1, Tobj2 the readings are ~0x3999. When I put my hand about 12" in front it reads about 0x3bbc or so from Tobj1. The config reg makes seems to have the right settings. I applied a couple of initialization commands applied to the SDA and SCL; will remove them and see if it still works.

    My first order of business will be to read and backup all of the device contents into the AB's eeprom for safe keeping. If you're interested I'll keep you posted.
    Dom..
Sign In or Register to comment.