Shop OBEX P1 Docs P2 Docs Learn Events
problem in propeller 1 code please help — Parallax Forums

problem in propeller 1 code please help

Hi , i made a simple program, read pressure and temperature values from a HoneyWell pressure sensor type SSCMANV030PA2A3. A Servo puls is generated via de Servo32v9 object.
In the PUB the Servo.Set(Servo_1,1500), is set the servo and works well. But after a delay time in the main loop, Servo.set(Servo_1,1500) is called again, the Sensor data becomes zero. Before that the values are good. The HoneyWell sensor works well on an other propeller 1. The combination of both, Sensor and Servo output, on one propeller 1 is new. The Main program is ServoB_X AD contr v0.01.spin
I have done several tests and combinations but cannot find out what the problem/error is

Is there anyone who sees what might be causing this error?

Comments

  • avsa242avsa242 Posts: 467
    edited 2025-07-25 17:26

    @rob26,

    I doubt this is the cause, but in Get_Depth_TempI2C(), there are these three lines:

            data:=I2CPressSens.Read(i2cSCL,ACK)               '2e read
            if data <> 225
                databyte[1] := data
    

    In the other three surrounding if blocks, data is compared to 255, not 225 (I'm guessing 255/$ff signifies data not ready or invalid data from the sensor). Was this supposed to be 255 also?

    Also, I haven't yet found the configuration/programming info for this chip, but I don't see where you tell the sensor which register you want to read. In Get_Depth_TempI2C(), you read from the sensor, but I couldn't find where you tell it which register to read from (this could just be my ignorance - maybe it isn't necessary with this sensor).
    I find with most sensors (or other I2C devices), you usually have to do something like this to read data from them:

    i2c.start()
    i2c.write(SLAVE_ADDRESS | 0)
    i2c.write(SENSOR_REGISTER)    ' tell the sensor: I'm interested in the data in this register
    i2c.stop()
    
    i2c.start()
    i2c.write(SLAVE_ADDRESS | 1)
    i2c.read(i2c.ACK)
    ...
    i2c.stop()
    
    

    Cheers

  • RaymanRayman Posts: 15,391

    Does it work if you comment out the servo.set lines?

  • @avsa242,
    Thank you for your reaction.
    The 225 is a typo, it should also be 255. If have changed it, but the result is the same.

    The Address of the sensor is PressSensorAddr = %0101_0000, see CON
    The I2C commands such as read and write to the sensor are in the Basic_I2C_Driver.
    I have had this Pressure sensor part working for years, but not in combination with the
    Servo32v9 software. And i have also been using the Servo32v9 for a while now.
    I'm not an expert in making drivers, this was working quickly, so there was no need toe change it.

    first step:

    • ackbit := I2CPressSens.write(i2cSCL,PressSensorAddr + %0000_0001)
      than 4 bytes to read

    • data:=I2CPressSens.Read(i2cSCL,ACK)

    @Rayman,
    Thanks also, yes, when i comment the { Servo.Set(Servo_1,1500) } in the repeat loop, the data of the pressure sensor stays good

    attached the I2C communication protocol for the Honeywell sensor

  • RaymanRayman Posts: 15,391

    That is odd. Wonder is it’s some timing thing….

    Try replacing servo.set with a waitcnt maybe to see if that breaks it too.

  • Maybe a power or noise issue too. Are the servos powered from the same power supply as the Propeller? If possible, you could try to connect them to a separate supply to see if that helps.

  • @Rayman,
    I have placed waitcnt before and after, no difference.

    @avsa242, i use different power supplies, but even without connected the power supply for the Servo. the problem is still there.

    the funny thing is that the Servo.Set() in the initAll, is not a problem, but after the delay in the main repeat the data of the pressure sensor stops

    very strange problem!

  • I think i have find the problem;
    this was the original I2C routine to communicate with the SSC pressure sensor. If i disable the else and
    activate the I2CPressSens.stop(i2cSCL) always, then it looks good.

    I2CPressSens.start(i2cSCL)
    ackbit := I2CPressSens.write(i2cSCL,PressSensorAddr + %0000_0001)

    if (ackbit==ACK)                                 'write ok acbit = 0 OK
        data:=I2CPressSens.Read(i2cSCL,ACK)               '1e read
        if data <> $FF  '$FF ipv 255 maakt niet uit
            databyte[0] := data
    
        data:=I2CPressSens.Read(i2cSCL,ACK)               '2e read
        if data <> $FF
            databyte[1] := data
    
        data:=I2CPressSens.Read(i2cSCL,ACK)               '3e read
        if data <> $FF
            databyte[2] := data
    
        data:=I2CPressSens.Read(i2cSCL,NAK)               '4e read
        if data <> $FF
            databyte[3] := data
    

    else
    I2CPressSens.stop(i2cSCL)

    But i have also made a new version on ideas of @avsa242, and probably this is a better version?
    It works also, please give your opinion:
    I2CPressSens.start(i2cSCL)
    I2CPressSens.write(i2cSCL,PressSensorAddr | 0) 'tell the sensor: I'm interested in the data in this register
    I2CPressSens.stop(i2cSCL)

    I2CPressSens.start(i2cSCL)
    I2CPressSens.write(i2cSCL,PressSensorAddr | 1)
    
    if (ackbit==ACK)                                 'write ok acbit = 0 OK
      data:=I2CPressSens.Read(i2cSCL,ACK)               '1e read
      if data <> $FF
         databyte[0] := data
    
    if (ackbit==ACK)
      data:=I2CPressSens.Read(i2cSCL,ACK)               '2e read
      if data <> $FF
         databyte[1] := data
    
    if (ackbit==ACK)
      data:=I2CPressSens.Read(i2cSCL,ACK)               '3e read
      if data <> $FF
         databyte[2] := data
    
    if (ackbit==ACK)
      data:=I2CPressSens.Read(i2cSCL,NAK)               '4e read
      if data <> $FF
         databyte[3] := data
    
    I2CPressSens.stop(i2cSCL)
    
  • sorry the layout is not what i want, i tray it again

  • I think i have find the problem;
    this was the original I2C routine to communicate with the SSC pressure sensor. If i disable the else and
    activate the I2CPressSens.stop(i2cSCL) always, then it looks good.

    I2CPressSens.start(i2cSCL)
    ackbit := I2CPressSens.write(i2cSCL,PressSensorAddr + %0000_0001) 'alleen eerste keer

    if (ackbit==ACK)                                 'write ok acbit = 0 OK
        data:=I2CPressSens.Read(i2cSCL,ACK)               '1e read
        if data <> $FF  '$FF ipv 255 maakt niet uit
            databyte[0] := data
    
        data:=I2CPressSens.Read(i2cSCL,ACK)               '2e read
        if data <> $FF
            databyte[1] := data
    
        data:=I2CPressSens.Read(i2cSCL,ACK)               '3e read
        if data <> $FF
            databyte[2] := data
    
        data:=I2CPressSens.Read(i2cSCL,NAK)               '4e read
        if data <> $FF
            databyte[3] := data
    
    else
      I2CPressSens.stop(i2cSCL)
    
  • sorry forget the last posts (8/9/10)

    as attachments:
    I2C protocol1.spin >> modified original
    I2C protocol2.spin >> new version

  • avsa242avsa242 Posts: 467
    edited 2025-07-27 13:14

    @rob26
    The way you have it now:

        I2CPressSens.start(i2cSCL)
        I2CPressSens.write(i2cSCL,PressSensorAddr | 0)   'tell the sensor: I'm interested in the data in this register
        I2CPressSens.stop(i2cSCL)
    

    This doesn't really do anything other than "ping" the sensor (if you were to read the return value from the I2CPressSens.write(), it should return either ACK or NAK). In my original example, note also the write of the register number after addressing the sensor itself.

    This is the intended flow, in general:

    i2c.start() ' <- Take control of the I2C bus
    i2c.write(SLAVE_ADDRESS | 0)  ' <- to the entire bus: "I want to talk to any device listening at address 'SLAVE_ADDRESS' (or `PressSensorAddr` in your code). Because the R/W bit is set to 'W', expect the register in my next write to the bus"
    i2c.write(SENSOR_REGISTER)    ' <- tell the sensor: "I'm interested in the data in the device's register number 'SENSOR_REGISTER' "
    i2c.stop() ' <- release control of the I2C bus
    

    ...then the device prepares the data...

    i2c.start() ' <- Take control of the I2C bus
    i2c.write(SLAVE_ADDRESS | 1)  ' <- to the entire bus: "I want to talk to any device listening at address 'SLAVE_ADDRESS' (or `PressSensorAddr` in your code). Because the R/W bit is set to 'R', please prepare to send the data to the bus."
    variable := i2c.read(i2c.ACK)    ' <- read a byte from the bus, and acknowledge it (or don't, typically if it's the last byte to read)
    i2c.stop() ' <- release control of the I2C bus
    
    

    This is just FYI though - looking at the PDF you attached before, it seems this is the only data that can be read from the sensor, so while it's unusual, it doesn't seem to be necessary to tell it which register to read from. I think you could safely remove this part:

        I2CPressSens.start(i2cSCL)
        I2CPressSens.write(i2cSCL,PressSensorAddr | 0)   'tell the sensor: I'm interested in the data in this register
        I2CPressSens.stop(i2cSCL)
    

    EDIT: To sum up, the version you have in 'I2C protocol1.spin' under the 'works well' section looks good.

    Cheers

  • @avsa242
    thank you very much, for your very clear explanation!
    it is now clear for me.

Sign In or Register to comment.