2023-02-21 11:36 AM
I'm trying to configure and collect data from a BNO055 IMU over UART/RS232, using an STM32L552ZET6Q. The BNO055 is on a remote board, connected via cable to the STM32L5 microcontroller. Additionally, I am using a MAX3232CUE+T on either side of the cable to convert the signal from UART to RS232 and back again.
Unfortunately, I am running into a problem, where when I try to read data from the BNO055, the UART doesn't seem to pick it up. I checked with a logic analyzer and I can confirm that the BNO055 is responding as expected, but the STM32 doesn't seem to realize that anything has arrived. I set the wait time for HAL_UART_RECEIVE to HAL_MAX_DELAY, and it just waits forever.
In the below picture, a request is sent for the BNO055's id (0xA0). This command is composed of a start byte (0xAA), Read or Write (0x01 for read), What is being read (0x00) and how many bytes of data the BNO055 should send back (1, 0x01).
The response back from the BNO055 is success (0xBB), length of the data (0x01) and the data (0xA0).
I took this capture very close to the STM32 UART GPIO, so I can be reasonably confident that the transmission reached the other side successfully, and the BNO055 successfully interpreted the command and responded appropriately. However, the STM32 doesn't seem to have realized that anything has arrived.
Here's the function that corresponds to the above image, specifically the uartRead line:
void BNO055_beginUART(bno055_uart *chip)
{
uint8_t val = 0x00;
bno055_resetUART(chip);
uint8_t id[3];
uartRead(chip, BNO055_CHIP_ID, 1, id);
if (id[2] != BNO055_ID) {
printf("Can't find BNO055, id: 0x%02x. Please check your wiring.\r\n", id[2]);
}
bno055_setPageUart(chip, 0);
// Select BNO055 config mode
bno055_setOperationModeConfigUART(chip);
uartWrite(chip, BNO055_SYS_TRIGGER, 1, &val);
bno055_delay(10);
}
And here's uartRead:
void uartRead(bno055_uart *chip, uint8_t reg, uint8_t len, uint8_t *data)
{
uint8_t status;
uint8_t transmit_buf[128] = {0xAA, 0x01, reg, len};
uint8_t receive_buf[128];
status = HAL_UART_Transmit(&chip->uart_bus, transmit_buf, 4, 50);
if(status != HAL_OK)
{
printf("ERROR: %d", status);
return;
}
//bno055_delay(10);
status = HAL_UART_Receive(&chip->uart_bus, receive_buf, (len+2), 5000);
if(status != HAL_OK)
{
printf("ERROR: %d", status);
return;
}
if(receive_buf[0] != 0xBB)
{
switch(data[1])
{
case 0x02:
printf("Read Failure");
break;
case 0x04:
printf("Register Map Invalid Address");
break;
case 0x05:
printf("Register Map Write Disabled");
break;
case 0x06:
printf("Wrong Start Byte");
break;
case 0x07:
printf("Bus over run error");
break;
case 0x08:
printf("Max length error");
break;
case 0x09:
printf("Min length error");
break;
case 0x0A:
printf("receive character timeout");
}
}
}
This is the current configuration I have for UART4, which I am using to try to communicate with the BNO055.
edit: Include datasheet and UART application notes for BN055
https://cdn-shop.adafruit.com/datasheets/BST_BNO055_DS000_12.pdf
2023-02-22 08:21 AM
So no overrun error reported here ...
2023-02-22 08:26 AM
I'm wondering if the BNO055 is simply responding before the L5 starts polling for a response. Going by the logic analysis, there's about 0.2mS between the end of the transmission and the start BNO055's response. I commented out the delay between the read request and the command to start polling for data, and I doubt that's what's going on, but I still can't help but wonder
2023-03-08 06:58 AM
Hello! It's been a while, but I solved what was going wrong initially with the UART! Apparently, old data was, for want of a better term, clogging up the buffer and preventing the UART from being able to read data arriving on the bus, causing it to run the full length of its maximum time-out limit. I fixed it by running HAL_UART_AbortReceive() before calling HAL_UART_Receive(). On UART4, everything is running perfectly. I'm writing commands to and reading data back from the BNO055 without problem
However, now I'm having that ORE flag being set on UART 5 when I come to the same spot in the code: UART4 runs first and runs fine, but when UART5 is called using the same code, it reaches one point in the code and the HAL_UART_Transmit() function always returns HAL_BUSY. I double-checked, and the OREflag is switching from 0x0 to 0x1. Do you have any suggestions to fix this problem or prevent it outright?
2023-03-08 07:57 AM
Hi @ESpra.1
HAL_UART_Transmit() and HAL_UART_Receive() are blocking functions, meaning that when you start a transmission, you will exit the function only when the complete buffer has been transmitted. Then you cannot perform Tx and Rx sequences simultaneously when using those APIs.
When your Tx is ongoing, if some data are received on RX line, as no code could be executed for handling the received datas, you will get ORE bit set to 1 in Status register.
It would be better to use Interrupts/DMA based routines (as HAL_UART_Transmit_IT()/HAL_UART_Receive_IT()/HAL_UART_Transmit_DMA()/HAL_UART_Receive_DMA() ) in order to be able to handle simultaneously TX and Rx sequences. Completion of requests would be indicated thanks to callbacks.