Collecting Sensors Data Using Raspberry Pi

Hi, has anyone tried to collect the sensor data using raspberry pi ? I tried setting the

thruster device_address = 0x29

Temp = 0x0A

(steinhart equation)

print(“value is:%f” %steinhart)

but the value of the temperature is so weird, sometimes it gives 85 or 369 which is wrong. Can anyone provide some guidance / tips ? thanks in advance

Could you share the complete code you are using? It will be difficult to pinpoint the issue otherwise.

Hi Jacob, thanks for your reply. Below are my code

import smbus
import math
bus = smbus.SMBus(1)
DEVICE_ADDRESS = 0x29
#The BlueESC’s I2c address
TEMP = 0x0A

print(“The BlueESC’s Raw Temperature is:”)
print(bus.read_word_data(DEVICE_ADDRESS,TEMP))

thermistornominal = 10000
#thermistor resistance at 25 deg C
temperaturenominal = 25
#temp for nominal resistance
bcoefficient = 3900
#beta coefficient of the thermistor
seriesresistor = 3300
#resistance of other resistor
#extracted from bluerobotics blueesc documentation
#Temperature measured by a 10k themistor(NCP18XH103J03RB) and a 3.3k resistor
#calculated using steinhart-hart equation
#1/T = 1/T0 + 1/B * ln(l/T)
resistance = seriesresistor / (65535/(bus.read_word_data(DEVICE_ADDRESS,TEMP))-1)
steinhart = resistance / thermistornominal #(R/R0)
steinhart = (math.log(steinhart) / bcoefficient

  • 1/(temperaturenominal + 273.15)) #ln(R/R0) * 1/B + 1/T0
    steinhart = 1/steinhart - 273.15
    print (“value is:%f” %steinhart)

If i use TEMP = 0x0A the value would give 34 if I use TEMP = 0x06, it would give 85, 369, both of which are wrong. Am i getting the wrong sensor signal ?

Ok, you are not retrieving the raw voltage reading correctly

From the BlueESC documentation:

0x02 = pulsecount_high byte (8 bits)

0x03 = pulsecount_low byte (8 bits)

0x04 = voltage_high byte (8 bits)

0x05 = voltage_low byte (8 bits)

0x06 = temp_h

0x07 = temp_l

0x08 = current_h

0x09 = current_l

0x0A = 0xab (identifier to see if blueesc is alive) (You dont want to be reading this for temperature measurements)

The voltage is a 16 bit unsigned integer, with the upper (most significant) 8 bits at 0x06 and the lower 8 bits at 0x08.

What you need to do is read the upper bits, shift them left 8 bits, then read the lower 8 bits.

uint8_t v_high = byte at 0x06

uint8_t v_low = byte at 0x08

uint16_t actualvoltageraw = (v_high << 8) | (v_low)

 

See the example code here for more details. Arduino_I2C_ESC/Arduino_I2C_ESC.cpp at master · bluerobotics/Arduino_I2C_ESC · GitHub

-Jacob

Hi I see now that you are reading a word at a time instead of a byte, so you shouldn’t have to do the bit shifting operations above in order to form a 16 bit number.

I think the issue is that read_word is reading the data as a little-endian number, when it is actually stored as big-endian, so the bits are in completely wrong places when it returns. If this is the case you will have to manipulate the bits to put them in the right place, but it would probably be easier to just read a byte at a time and do the operations above.

See read_word_data here:

https://www.kernel.org/doc/Documentation/i2c/smbus-protocol

Can you print the output when using 0x06 as the address?

Hi Jacob,

Thanks for your reply. Using read_word_data at 0x06 will give me a value of 170.

I will go try it and post my result here. But when you said

The voltage is a 16 bit unsigned integer, with the upper (most significant) 8 bits at 0x06 and the lower 8 bits at 0x08.

What you need to do is read the upper bits, shift them left 8 bits, then read the lower 8 bits.

uint8_t v_high = byte at 0x06

uint8_t v_low = byte at 0x08

 

Since its voltage and according to blue documentation shouldn’t it be 0x04 and 0x05 ?

now the code i’m using is this

import smbus
import math

bus = smbus.SMBus(1)
DEVICE_ADDRESS = 0x29
#The BlueESC’s I2c address

TEMP_h = bus.read_byte_data(DEVICE_ADDRESS,0x06)
TEMP_l = bus.read_byte_data(DEVICE_ADDRESS,0x07)

TEMP = (TEMP_h<<8) | TEMP_l

#The temperature’s I2c register (it’s 2 bytes 0x06 and 0x07)
thermistornominal = 10000
#thermistor resistance at 25 deg C
temperaturenominal = 25
#temp for nominal resistance
bcoefficient = 3900
#beta coefficient of the thermistor
seriesresistor = 3300
#resistance of other resistor
#extracted from bluerobotics blueesc documentation
#Temperature measured by a 10k themistor(NCP18XH103J03RB) and a 3.3k resistor
#calculated using steinhart-hart equation
#1/T = 1/T0 + 1/B * ln(l/T)
resistance = seriesresistor / ((65535/TEMP)-1)
steinhart = resistance / thermistornominal #(R/R0)
steinhart = (math.log(steinhart) / bcoefficient

  • 1/(temperaturenominal + 273.15)) #ln(R/R0) * 1/B + 1/T0
    steinhart = 1/steinhart - 273.15
    print (“value is:%f” %steinhart)

the output value is 35.065166. Is this correct ?

I think the reading is correct, i tried to cool the thruster down then measure the temperature again, it seems legit. Anyway for the RPM equation, I used

starttime = time.time()

RPM_h = bus.read_byte_data(DEVICE_ADDRESS,0x02)
RPM_l = bus.read_byte_data(DEVICE_ADDRESS,0x03)

endtime = time.time

changetime = endtime - starttime

RPM = (RPM_h<<8) | RPM_l

realRPM = RPM / (changetime *12) * 60 # Number of poles for t100 is 12

but the value is way too high and the equation on bluerobotics seems to be a little weird, the number of poles mentioned at (BlueESC Documentation) but in the code (br-esc-examples/I2CControl.ino at master · bluerobotics/br-esc-examples · GitHub) they divided by 6 (no of poles) and dt ( i guess is change of time) by 1000000

 

The rpm registers tell you the pulses since the last time the register is read. So the time elapsed between reads is what you should use for your dt (like if you call your function to read the registers and calculate the rpm once per second, then your dt = 1 second). This is not the same as the time that it takes to read the register, which will be very, very short (this is what you are currently using as dt, and why your rpm after calculations is so high);

-Jacob

Oh i see. Thanks for your tips and help all these while