Greetings, so we are working on a project. We have rsx-um7 orientation sensor and are trying to get euler angles. Sensor is connected to Raspberry pi using spi pins. The datasheet we have tells us register 0x70 contains roll and pitch angle estimates. Whereas, we can only extract Roll from it. And the register 0x71 is for the yaw angle estimate, which we are getting as well. I’m pasting the Python code and datasheet.
Please guide us through.
UM7_Datasheet_1-3.pdf (1.7 MB)
import spidev
import struct
import time
# SPI Configuration
SPI_BUS = 0
SPI_DEVICE = 0
SPI_SPEED = 1000000 # 1 MHz
UM7_YAW_REG = 0x71 # Yaw register (Euler Psi)
UM7_ROLL_PITCH_REG = 0x70 # Roll and pitch register (Euler Phi & Theta)
# Initialize SPI
spi = spidev.SpiDev()
spi.open(SPI_BUS, SPI_DEVICE)
spi.max_speed_hz = SPI_SPEED
spi.mode = 0 # SPI Mode 0 (CPOL=0, CPHA=0)
def read_um7_register(register_address):
"""Reads a 4-byte register from UM7 over SPI."""
spi.xfer2([0x00, register_address]) # Send read command
time.sleep(5e-6) # Small delay for UM7 to process
rx_data = spi.xfer2([0x00] * 4) # Read 4 bytes response
print(f"Raw SPI Response (0x{register_address:02X}): {rx_data}") # Debugging: Print raw SPI response
if len(rx_data) != 4:
print("Error: Incomplete data received")
return None
return rx_data
def get_roll_pitch():
"""Reads roll and pitch from UM7 and converts them to degrees."""
rx_data = read_um7_register(UM7_ROLL_PITCH_REG)
if rx_data is None:
return None, None
# Extract roll (first two bytes) and pitch (last two bytes)
roll_raw = struct.unpack('>h', bytes(rx_data[:2]))[0] # Roll (Phi)
pitch_raw = struct.unpack('>h', bytes(rx_data[2:]))[0] # Pitch (Theta)
# Convert to degrees
roll_degrees = roll_raw / 91.02222
pitch_degrees = pitch_raw / 91.02222
return roll_degrees, pitch_degrees
def get_yaw():
"""Reads yaw from UM7 and converts it to degrees."""
rx_data = read_um7_register(UM7_YAW_REG)
if rx_data is None:
return None
# Extract yaw (first two bytes)
yaw_raw = struct.unpack('>h', bytes(rx_data[:2]))[0] # Yaw (Psi)
# Convert to degrees
yaw_degrees = yaw_raw / 91.02222
return yaw_degrees
try:
while True:
roll, pitch = get_roll_pitch()
yaw = get_yaw()
if roll is not None and pitch is not None and yaw is not None:
print(f"Roll: {roll:.2f}°, pitch: {pitch:.2f}°, Yaw: {yaw:.2f}°")
else:
print("Invalid data received")
time.sleep(0.1) # Read at 10Hz
except KeyboardInterrupt:
print("Exiting...")
finally:
spi.close() # Close SPI when done
Hello.
Just to clarify, it sounds like when you run the code you attached your Raspberry Pi will print roll and yaw angles, but it will not print anything for pitch; is that correct? Can you post a sample of the output?
Another good troubleshooting step would be to check if the UM7 behaves as expected if you use it with the Redshift Serial Interface Software. You can download that software from the UM7 product page under the “Resources” tab.
- Patrick
1 Like
Thanks for the response. I’m able to get the output of pitch as well. Pasting the output.
Now we need help to sort out the drift in euler angles. I don’t see any documentation regarding it. Your guidance will be highly appreciated.
Roll: 5.71°, Pitch: 42.87°, Yaw: 51.68°
Roll: 5.90°, Pitch: 43.04°, Yaw: 51.88°
Roll: 6.03°, Pitch: 43.19°, Yaw: 52.02°
Roll: 6.17°, Pitch: 43.33°, Yaw: 50.76°
Roll: 6.37°, Pitch: 43.51°, Yaw: 50.95°
Roll: 6.50°, Pitch: 42.24°, Yaw: 51.11°
Roll: 6.69°, Pitch: 42.43°, Yaw: 51.30°
Roll: 6.81°, Pitch: 42.56°, Yaw: 51.44°
I am glad to hear that all of the angles are updating now; thanks for letting us know.
As for sorting out the drift, I recommend you try the procedures demonstrated in these YouTube videos:
- Patrick
1 Like
Thank you for your response. I have tried these procedures already.
It is hard to offer any useful additional advice about addressing the drift with the information you provided; can you post more details, like some quantification of the drift?
You might also try checking the DREG_HEALTH register and let us know what that reports.
- Patrick
1 Like
Sorry for the late response. This is the drift I’m talking about. I have done calibration quite a few times.
-32.12 32.40 -93.19
-32.16 32.42 -93.20
-32.19 32.44 -93.20
-32.23 32.48 -93.20
-32.26 32.50 -93.19
-32.30 32.53 -93.20
-32.33 32.56 -93.20
-32.37 32.59 -93.20
-32.40 32.62 -93.20
-32.43 32.64 -93.20
-32.48 32.67 -93.20
-32.51 32.70 -93.20
-32.54 32.73 -93.20
-32.57 32.76 -93.20
-32.61 32.78 -93.20
-32.64 32.82 -93.20
-32.67 32.85 -93.20
-32.71 32.88 -93.20
-32.74 32.90 -93.20
-32.78 32.94 -93.21
-32.82 32.96 -93.21
-32.85 32.99 -93.21
-32.88 33.02 -93.21
-32.92 33.06 -93.21
-32.95 33.08 -93.21
-32.98 33.11 -93.22
-33.02 33.15 -93.22
-33.06 33.17 -93.22
Just to confirm, what is the order of the measurements? Also, what is the time period for them?
- Patrick
1 Like
I have shifted to Esp32, here is the code.
#include <SPI.h>
#define UM7_CS 5 // Chip Select (Slave Select) GPIO5
float roll, pitch, yaw;
void sendSPICommand(uint8_t reg) {
digitalWrite(UM7_CS, LOW);
SPI.transfer(0x00);
SPI.transfer(reg);
delayMicroseconds(10);
digitalWrite(UM7_CS, HIGH);
}
void readEulerAngles() {
uint8_t response[4];
// Read Roll & Pitch (DREG_EULER_PHI_THETA, 0x70)
sendSPICommand(0x70);
digitalWrite(UM7_CS, LOW);
for (int i = 0; i < 4; i++) {
response[i] = SPI.transfer(0x00);
}
digitalWrite(UM7_CS, HIGH);
roll = ((int16_t)(response[0] << 8 | response[1])) / 91.02222;
pitch = ((int16_t)(response[2] << 8 | response[3])) / 91.02222;
// Read Yaw (DREG_EULER_PSI, 0x71)
sendSPICommand(0x71);
digitalWrite(UM7_CS, LOW);
for (int i = 0; i < 4; i++) {
response[i] = SPI.transfer(0x00);
}
digitalWrite(UM7_CS, HIGH);
yaw = ((int16_t)(response[0] << 8 | response[1])) / 91.02222;
}
void setup() {
Serial.begin(115200);
SPI.begin(18, 19, 23, 5);
pinMode(UM7_CS, OUTPUT);
digitalWrite(UM7_CS, HIGH);
delay(500);
}
void loop() {
readEulerAngles();
Serial.print("Roll: "); Serial.print(roll);
Serial.print(" Pitch: "); Serial.print(pitch);
Serial.print(" Yaw: "); Serial.println(yaw);
delay(100);
}
If you leave the program running for a while, do the values eventually stabilize at a particular point?
Since the yaw looks pretty stable, we think calibrating the accelerometer’s alignment could help. There is a CALIBRATE_ACCELEROMETERS - 0xB1 (177) command mentioned in the UM7 datasheet, so you might try that. Unfortunately though, there is not much detail about how it works or what it is actually doing.
If you are not already doing so, calibrating the gyro zero rates might help too. There is a command for that in the Redshift Serial Interface Software under the “Commands” tab, or you could call if from your ESP32 program.
- Patrick
1 Like
No, neither of the values stabilizes. Yaw also drifts when changes occur.
Already tried. Even if I use an accelerometer and gyro to get the Euler angle, the same issue appears.
Thank you for checking that. I am out of troubleshooting suggestions, so at this point we should probably just try getting you a replacement. Can you email us with your order information and a reference to this thread so we can get that going?
- Patrick
1 Like
Great, let me have a word with my supervisor.