Shop OBEX P1 Docs P2 Docs Learn Events
LPS22HB click driver — Parallax Forums

LPS22HB click driver

I wanted to do some testing with these LS22HB pressure sensors for potential altitude control for a drone. I saw there is a LS22HB click board, so I thought I would try and write a driver that someone else also might be able to use. I used Jon's click module template and his I2C driver. I used the same I2C pin outputs that the click board uses. I wanted to set the LS22HB to output data at 75 samples a second, and have a cog running that polls the fifo buffer and reads new pressure and temperature data as it becomes available, and in the background updates the pressure and temperature variables in the object.
First I got the basic functionality working, setting the registers, reading the fifo status bits, everything was working. Then I started a new cog to do the polling on the fifo status bits, but none of the I2C methods would work in the new cog. The only way I could get it to work was by doing all of the I2C stuff in the new cog... am I missing something on scope or instances of objects? or is it something about the I2C object?

I am amazed at the resolution of these pressure sensors, being able to sense just a couple of feet difference in altitude. And how the two different sensors tracked each other. (I added a offset to the second sensor to bring it closer to the first sensor in the graphic output.)
And I love the new graphical output modes... plot, trace... really nice!

Comments

  • JonnyMacJonnyMac Posts: 8,918
    edited 2020-12-07 20:00
    ...but none of the I2C methods would work in the new cog.
    ...or is it something about the I2C object?
    Hmmm.... I'll have to do a test. The I2C code is inline which means it runs inside the interpreter cog that calls it.
  • JonnyMacJonnyMac Posts: 8,918
    edited 2020-12-07 20:49
    You can streamline your get_data() method like this:
    pub get_data() : reply1, replay2 
    
      i2c.start()
      i2c.write(LPS22_WR)
      i2c.write(PRESS_OUT_XL)
      i2c.start()
      i2c.write(LPS22_RD)
      reply1.byte[0] := i2c.read(i2c.ACK)
      reply1.byte[1] := i2c.read(i2c.ACK)
      reply1.byte[2] := i2c.read(i2c.ACK)
      reply2.byte[0] := i2c.read(i2c.ACK)
      reply2.byte[1] := i2c.read(i2c.NAK)
      i2c.stop()
    
      reply1 signx= 23                                              ' extend sign bit
      pressure := (reply1 * 10) sar 12                              ' convert to 1/10ths hPa
    
      reply2 signx= 15                                              ' extend sign bit
      temperature := reply2                                         ' return 1/100ths C
    
      counter++
    
  • JonnyMac wrote: »
    You can streamline your get_data() method like this:
    pub get_data() : reply1, replay2 
    
      i2c.start()
      i2c.write(LPS22_WR)
      i2c.write(PRESS_OUT_XL)
      i2c.start()
      i2c.write(LPS22_RD)
      reply1.byte[0] := i2c.read(i2c.ACK)
      reply1.byte[1] := i2c.read(i2c.ACK)
      reply1.byte[2] := i2c.read(i2c.ACK)
      reply2.byte[0] := i2c.read(i2c.ACK)
      reply2.byte[1] := i2c.read(i2c.NAK)
      i2c.stop()
    
      reply1 signx= 23                                              ' extend sign bit
      pressure := (reply1 * 10) sar 12                              ' convert to 1/10ths hPa
    
      reply2 signx= 15                                              ' extend sign bit
      temperature := reply2                                         ' return 1/100ths C
    
      counter++
    

    Jon,
    If i2c.read(i2cACK) returns a long, then...
    take this line for instance...

    "reply1.byte[2] := i2c.read(i2c.ACK) "

    do the 4 bytes that i2c.read() returns go into reply1.byte[2], reply1.byte[3], reply2.byte[0], reply2.byte[1]?

    That looks cleaner than all the shifting right I was doing, and I neglected the sign extensions.
    And the scaling...

    I will clean it up and try to post it to git hub. (or email i tto parallax and have them do it like you said in as earlier post)

    Mike

  • JonnyMacJonnyMac Posts: 8,918
    edited 2020-12-08 23:49
    Every method returns a long, but if your destination is a byte, as in my example, only byte 0 of the return value is used. I've done this many times.

    Here's a bit of test code that demonstrates:
      z := 0
      
      repeat x from 0 to 3
        y := getrnd()
        z.byte[x] := y
        term.fstr2(string("%.8x %.8x\r"), y, z)
    
    And here's the output:
    9DD7F218 00000018
    A768C0E3 0000E318
    28A7ADCE 00CEE318
    076EEFEC ECCEE318
    
    The value on the left is random, the value on the right is what we're building up one byte at a time. You can see at each step, only the target byte of the output value is affected, and it gets byte 0 of the return value. What this means is that the assignment operator behaves differently based on the size of the variable being assigned.
Sign In or Register to comment.