ANROT Tutorial

Qt C++ Desktop Reading Tutorial

Build a lightweight Qt SerialPort desktop tool to read ANROT packets, validate live data, and prototype GUI workflows.

Updated Jan 1, 2025 Products 9
  • qt
  • cplusplus
  • serial
  • tutorial

Qt C++ example

Protocol Support

Protocol / frameSupportHow this example handles it
0x91 IMUSOLSupportedDecodes a single-device float frame into receive_imusol and updates the UI.
0x62 GWSOLSupportedDecodes gateway float collection frames into receive_gwsol.
0x63 GWSOL CompactSupportedDecodes compact int16 gateway frames with 0x93 node blocks, converts them to float values, and displays them.
0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xD1SupportedParses loose single-field output modes.
0xF0 PressureSkippedThe decoder skips this item and the UI does not display pressure.

Source code (download and unzip): demo-qt-cplusplus-en.zip

test environment:

  • QT 5.9.9 + Win10
  • Only applicable to the new version of the transmission protocol (0x91, 0x62, see the manual for details)

Step 1. include and .pro settings

  1. There are packet, imu_data_decode headers and cpp files under the include folder, respectively. Add these 4 files in QT.

  2. Add QT += serialport to the QT .pro file to use the serial port, and include header in the main window

     #ifndef MAINWINDOW_H
     #define MAINWINDOW_H
    
     #include "include/imu_data_decode.h"
     #include "include/packet.h"

Step 2. main function

Initialize the module before starting reception

imu_data_decode_init();

packet_decode(c) receives and parses a single uint8_t character from the sequence, and continues to receive and parse in the loop:

void MainWindow::read_serial()
{
    auto NumberOfBytesToRead = m_reader.bytesAvailable();

    if(NumberOfBytesToRead > 0 && m_reader.isReadable())
    {
        QByteArray arr = m_reader.readAll();

        for (int i=0;i<NumberOfBytesToRead;i++) {
            uint8_t c=arr[i];
            packet_decode(c);
        }
    }
}

While decoding, receive_imusol_packet_t will be updated instantly based on the data received by the IMU. If using a Hi221Dongle (wireless receiver), receive_gwsol_packet_t will be the received data, which is a combination of multiple receive_imusol_packet_t. For example, to get Euler angles:

int euler_x,euler_y,euler_z;
euler_x=receive_imusol_packet_t.eul[0];
euler_y=receive_imusol_packet_t.eul[1];
euler_z=receive_imusol_packet_t.eul[2];

Following is the declared structure of receive_imusol_packet_t and receive_imusol_packet_t:

   typedef struct receive_imusol_packet_t{
    uint8_t tag;
    uint8_t id;
    float acc[3];
    float gyr[3];
    float mag[3];
    float eul[3];
    float quat[4];
   }receive_imusol_packet_t;

   typedef struct receive_gwsol_packet_t{
       uint8_t tag;
    uint8_t gw_id;
    uint8_t n;
    receive_imusol_packet_t receive_imusol[MAX_LENGTH];
   }receive_gwsol_packet_t;

Step3. Understand the packet type

0X91( IMUSOL)

A total of 76 bytes, the newly added data packet is used to replace A0, B0, C0, D0, D1 and other data packets. The raw sensor output and attitude solution data of the IMU are integrated.

| byte offset | type | bytes | unit | description | | -------- | -------- | ----- | -------------------- | ---- -------------------------------------------------- ------ | | 0 | uint8_t | 1 | - | Packet label: 0x91 | | 1 | uint8_t | 1 | - | ID | | 2 | - | 6 | - | Reserved | | 8 | uint32_t | 4 | ms | Timestamp information, accumulated since the system is powered on, increments by 1 every millisecond | | 12 | float | 12 | 1G (1G = 1 gravitational acceleration) | X, Y, Z axis acceleration, note that the unit is different from 0xA0 | | 24 | float | 12 | deg/s | Angular velocity of X, Y, Z axis, note that the unit is different from 0xB0 | | 36 | float | 12 | uT | Magnetic field strength of X, Y, Z axis (supported by Hi229, note that the unit is different from 0xC0) | | 48 | float | 12 | deg | Node Euler angle set, the order is: Roll (Roll), Pitch (Pitch), Yaw (Yaw) (note that the order and unit are different from 0xD0 packets) | | 60 | float | 16 | - | Node quaternion set, in order WXYZ |

0x62 (GWSOL)

The first 8 bytes of the Hi221Dongle (wireless receiver) data packet are receiver information. The latter is divided into N data blocks. Each data block describes the attitude data of a node (up to 16 nodes are supported). The size of each data block is 76 bytes, and the data structure is the same as 0x91. This protocol has a large amount of data. It is recommended to adjust the baud rate to above 460800 to obtain a stable frame rate output.

The protocol structure is as follows:

| byte offset | bytes | type | unit | description | | ------------------------ | ----- | ------- | ---- | ----- -------------------- | | 0 | 1 | uint8_t | - | Packet label: 0x62 | | 1 | 1 | uint8_t | - | GWID, receiver network ID | | 2 | 1 | uint8_t | - | N, this frame contains the number of node data blocks | | 3 | 5 | - | - | Reserved | | ----Start of node data block---- | - | - | - | Data structure is the same as 0x91 | | 8+76N(N=0-15) | 1 | uint8_t | - | Packet label: 0x91 | | 9+76N(N=0-15) | 1 | uint8_t | - | ID of node N | | 10+76N | 10 | - | - | Reserved | | 20+76N | 12 | float | - | Node N triaxial acceleration | | 32+76N | 12 | float | - | Node N triaxial angular velocity | | 44+76N | 12 | float | - | Node N-axis magnetic field strength | | 56+76N | 12 | float | - | Node N Euler angles | | 68+76N | 16 | float | - | Node N Quaternion | | ----End of node data block---- | - | - | - | ----------- |