Motor encoder bug in BrickPi.py

Hello,
While doing some tests to find the motor encoder overflow value I found a bug in BrickPi.py.
My test code looks like this:

from BrickPi import *   #import BrickPi.py file to use BrickPi operations
BrickPiSetup()  # setup the serial port for communication
BrickPi.MotorEnable[PORT_A] = 1     #Enable the Motor A
BrickPi.MotorSpeed[PORT_A] = 100    #Set the speed of MotorA (-255 to 255)
BrickPiSetupSensors()       #Send the properties of sensors to BrickPi
BrickPiUpdateValues()
BrickPi.EncoderOffset[PORT_A] = BrickPi.Encoder[PORT_A] # Reset the encoder
BrickPiUpdateValues()
BrickPi.EncoderOffset[PORT_A] = -(0x3FFFFF00) # Give the encoder a very large offset (it overflows at 0x3FFFFFFF)

while True:
    result = BrickPiUpdateValues()  # Ask BrickPi to update values for sensors/motors
    if not result :                 # if updating values succeeded
        print ( BrickPi.Encoder[PORT_A] )#%720 ) /2   # print the encoder degrees 
    time.sleep(.1)		#sleep for 100 ms

Using this I got an error message from python about the use of an undefined variable Temp_ENC_DIR in the function BrickPiUpdateValues(). So, I fixed that, but then found another problem: After the encoder overflows it doesn’t wrap around to a negative number. Instead it becomes 0 and stays there.
Stopping the program and restarting it doesn’t reset the encoder anymore. The only thing that re-enables the encoder is a reboot of the BrickPi.

Hey Frans,

We’ll try to take a look at this. I assume there’s something happening with typecasting that’s limiting the EncoderOffset to a 4 byte number.

Out of curiosity, why are you using such a large offset?

Hello,
I don’t think overflow will ever occur in any real application. Even if you run the motor continuously at 180rpm it will take almost 6 days to overflow the encoder.
The reason I looked into this, is because I’m testing PID speed control of two lego motors (coupling them without a mechanical link). I read somewhere that the NXT encoder is limited to 16bits and therefore likely to overflow in real applications. So, I wanted to know if this is also the case with BrickPi. (Speed is determined by subtracting previous from current encoder value and dividing by elapsed time, so an overflow of the encoder could cause trouble.)

BrickPi.py limits the encoder-offset value to 30bits, because the message over the UART from RPi to BrickPi only has five bits to specify the number of bits used for the encoder offset value. A five bit number ranges from 0 to 31, one bit is used for direction, so 30bits are left for the encoder-offset magnitude. The message back from BrickPi to RPi uses the same layout for the encoder value.
I haven’t checked yet how the BrickPi firmware constructs the message to RPi, but I do know that it uses a 32bit signed integer to store the encoder values. Perhaps something goes wrong in translating the large 32bit signed encoder value to a 30bit unsigned number?

Another question: Why does the BrickPi firmware keep track of the encoder value? Why doesn’t it just report increments and let the driver code on RPi handle the summation? In general increments will be much smaller than the full encoder value, so this could shorten the message over the UART.

Hey,

i also got the problem “use of an undefined variable Temp_ENC_DIR in the function BrickPiUpdateValues().” when resetting the encoder with

“BrickPi.EncoderOffset[PORT_A] = BrickPi.Encoder[PORT_A]”

How did you fix it?

Hi,
I just added a declaration of the missing variable in the BrickPi.py code. However, I think that change has already been merged in the Github repo.

Hi,

thank you i will update my working copy or do it by myself. I also got problems with resetting the Encoders. It doesn’t work with “BrickPi.EncoderOffset[PORT_A] = BrickPi.Encoder[PORT_A]”. It starts to double the encoderValue.