Announcement

Collapse
No announcement yet.

Melexis IR sensor on Diablo I2C

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Melexis IR sensor on Diablo I2C

    Has anyone had any success interfacing a Melexis IR sensor (in SMBus mode) to the I2C on Diablo or Picaso? I've attempted to use both display types and have met with no luck.

    I'm using external 2k pullups.

    Here's my [Diablo] code:

    Code:
    // Program definitions
    #constant #define $#constant
    #CONST
    scl := $PA10
    sda := $PA11
    true := 1
    false := 0
    #END
    
    func main()
        repeat
    print ("I2CWord: ", [HEX4] I2C_readword(0x5A,0x07),"\n");    //Using all-devices address 0x00 and RAM register 0x07
        pause (50);
        gfx_Cls ();
        forever
    endfunc
    
    
      func I2C_readword(var device, var address)
    
    var lsb,msb,PEC, WR:=1;
    
        I2C1_Open(I2C_10KHZ,scl,sda);
        I2C1_Idle();                        // Wait for bus Idle
        I2C1_Start();                    // Generate Start condition
        I2C1_Write(device);                // send slave address
        I2C1_Idle();                        // Wait for bus Idle
        I2C1_Write(address);        // Send register address
        I2C1_Idle();                        // Wait for bus Idle
        I2C1_Restart();                    // Generate Restart
        I2C1_Write(device+WR);            // send control byte for Read
        I2C1_Idle();                        // Wait for bus Idle
        lsb := I2C1_Read();                // read the byte
        I2C1_Ack();                  //acknowledge you've received the LSB
        msb:= I2C1_Read();
        I2C1_Ack();                 //acknowledge you've received the MSB
        PEC:=I2C1_Read();
        I2C1_Nack();
        I2C1_Stop();                        // Send Stop Condition
        I2C1_Close();
    
        return ((msb<<8)+lsb);                       // return the value word
    
    endfunc
    Thanks to Animalector for most of the above code.


    I was hoping that someone had a resolution to offer. Otherwise I will start picking apart the waveforms on my teeny-tiny DSO Quad to try to figure out why it works on my Coridium and PI but not on this super-cool Diablo 7".

    Much thanks!
    J.Dyess

  • #2


    Perhaps take the code that works on the Coridium and PI and turn it back into 4DGL? Hopefully that is a trivial task (as I've seen, sometimes it is, sometimes it isn't)
    Mark

    Comment


    • #3


      In order to port the I2C hardware interface library from my other device to 4DGL I would need micro-second timer granularity. Something I don't see available.
      J.Dyess

      Comment


      • #4


        But just for posterity here is what I've translated so far:
        (Maybe someone else would like to give it a go?)

        #constant #define $#constant



        #define USE_I2C
        #define I2CwaitTime 1


        func I2Cwait ()
        var start;
        start := sys_T();
        while ((sys_T() - start) < I2CwaitTime);
        endfunc


        func waitCLKstretch (var SCLpin)
        while (pin_Read(SCLpin) == 0);
        I2Cwait ();
        endfunc


        func i2c_start (var SDApin, var SCLpin)
        var start;

        pin_Set(PIN_INP, SDApin);// allow them to float
        pin_Set(PIN_INP,SCLpin);
        I2Cwait ();

        pin_LO(SDApin);
        I2Cwait ();

        pin_LO(SCLpin);
        endfunc


        func i2c_stop (var SDApin, var SCLpin)
        pin_LO(SDApin);

        pin_Set (PIN_INP,SCLpin); // release SCL high
        I2Cwait ();
        pin_Set(PIN_INP,SDApin); // release SDA high
        endfunc


        // shift out 8 bits, return ACK, leave SCL low, SDA float

        func i2c_shift (var SDApin, var SCLpin, var value) // returns TRUE when ACK'd
        var i;

        i := 0x80;
        while (i)
        pin_LO (SCLpin);
        I2Cwait();
        if (i & value)pin_Set (PIN_INP,SDApin); else pin_LO(SDApin);

        pin_Set (PIN_INP,SCLpin); // release SCL high
        waitCLKstretch (SCLpin);
        i := i >> 1;
        wend

        pin_LO(SCLpin);
        pin_Set (PIN_INP,SDApin); // let SDA float
        I2Cwait;
        pin_Set (PIN_INP,SCLpin); // release SCL high
        waitCLKstretch (SCLpin);

        i := pin_Read(SDApin); // check ACK here (save value in i, 0 was ACK'd

        pin_LO(SCLpin);

        if (i ==0) return 1;
        if (!(i==0)) return 0; // was it ACK'd
        endfunc

        // the following does the writes to the i2c, but does not do a STOP

        func send_i2cout (var SDApin, var SCLpin, var addr, var OUTcnt, var OUTlist)
        var itsOK;
        var i;

        i2c_start(SDApin, SCLpin);
        itsOK := i2c_shift(SDApin, SCLpin, (addr & 0xfe));
        i := 0;

        if (itsOK)
        repeat
        if (OUTcnt < 0) return 0;
        if (OUTcnt == 0)
        if (OUTlist[i] == 0) return 0;
        endif
        if (i2c_shift(SDApin, SCLpin, OUTlist[i]) == 0)
        itsOK := 0;
        return 0;
        endif
        i++;

        until (i == OUTcnt);
        endif

        return (itsOK);
        endfunc


        // returns 1 if i2c device responding

        func I2COUT (var SDApin, var SCLpin, var addr, var OUTcnt, var OUTlist)
        var itsOK;

        itsOK := send_i2cout (SDApin, SCLpin, addr, OUTcnt, OUTlist);

        i2c_stop(SDApin, SCLpin);
        return itsOK;
        endfunc

        // set OUTcnt to -1 to only send an address

        func I2CIN (var SDApin, var SCLpin, var addr, var OUTcnt, var OUTlist, var INcnt, var INlist)
        var itsOK; // also set to 0 when last data sent
        var value;
        var i;
        var j;

        itsOK := 1;
        if (OUTcnt >= 0)
        itsOK := send_i2cout (SDApin, SCLpin, addr, OUTcnt, OUTlist);
        endif

        if (itsOK)

        i2c_start(SDApin, SCLpin);

        i := 0;
        if (i2c_shift(SDApin, SCLpin, (addr | 1))) // read this time
        while (1)
        value := 0;
        j := 0x80;
        while (j)
        pin_LO(SCLpin);
        I2Cwait ();
        pin_Set (PIN_INP,SCLpin); // release SCL high
        I2Cwait ();
        value := (pin_Read(SDApin) & j) + value;
        j := j >> 1;
        wend

        if (INcnt == 0)
        if (value == 0) return;
        endif

        INlist[i] := value;
        i++;
        if (i == INcnt) return;

        pin_LO(SCLpin);
        // master (me would ACK here for a sequential read
        pin_LO(SDApin);
        I2Cwait();
        pin_Set (PIN_INP,SCLpin); // release SCL high
        I2Cwait();

        pin_LO(SCLpin);
        pin_Set(PIN_INP,SDApin); // release SDA high

        wend // internal checks exit this loop
        pin_LO(SCLpin);
        I2Cwait();
        pin_Set(PIN_INP,SCLpin); // release SCL high -- this time with no ACK
        I2Cwait();
        pin_LO(SCLpin);

        endif
        endif

        INlist[i] := 0;

        i2c_stop(SDApin, SCLpin);

        endfunc



        The above could be saved as a .fnc and inherited.
        (replace the #constant #define $#constant with a suitable ifdef if you already use #define as such)

        and instantiated from main () as such:

        HTML Code:
        //inherits...
        
        #CONST
        scl := $PA10
        sda := $PA11
        true := 1
        false := 0
        #END
        var message[100];
        var response[100];
        
        func main()
        //[...]   
            message[0]:= 0x07;// Read TOb from RAM (0x07)
            message[1]:=0;
            I2CIN(sda, scl, 0x00, 1,message, 2, response);
            print (response);
        //[...]
        J.Dyess

        Comment


        • #5


          Hopefully someone else has one of these sensors that they have gotten going.

          So the Coridium and PI do bit banged I2C? Not exactly helpful, try generating short timing delays using empty for loops, it will certainly be faster than ms delays everywhere.

          Maybe the scope will be easier, what often happens is that some chips are very picky about where they expect stop+start vs restart, this is usually pretty obvious when the scope is brought in to play.
          Mark

          Comment


          • #6


            I've gotten it going on uLCD-70DT.

            Using the following code:

            [HTML] func I2C_readword(var device, var address)

            var lsb,msb,PEC, WR:=1;

            I2C1_Open(I2C_SLOW,scl,sda);
            I2C1_Start(); // Generate Start condition
            I2C1_Write(device); // send slave address
            I2C1_Write(address); // Send register address
            I2C1_Restart(); // Generate Restart
            I2C1_Write(device+WR); // send control byte for Read
            lsb := I2C1_Read(); // read the byte
            I2C1_Ack(); //acknowledge you've received the LSB
            msb:= I2C1_Read();
            I2C1_Ack(); //acknowledge you've received the MSB
            PEC:=I2C1_Read();
            I2C1_Nack();
            I2C1_Stop(); // Send Stop Condition
            I2C1_Close();
            return ((msb
            J.Dyess

            Comment


            • #7


              Great!
              Mark

              Comment

              Working...
              X