Kart/serial link
(→Kart to SmartPhone) |
Axel.amand (Talk | contribs) (→Sensors) |
||
(53 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
− | |||
{{TOC right}} | {{TOC right}} | ||
== Serial link protocol == | == Serial link protocol == | ||
− | This section defines the serial link protocol used to communicate between the Kart and the | + | This section defines the serial link protocol used to communicate between the Kart and the BLE module / PC / Android Smartphone. |
+ | |||
+ | === General principle === | ||
+ | The system is using a [[Kart/Bluetooth|BLE]] module. | ||
+ | |||
+ | To avoid congesting the line, data are sent from the Kart to the User on specific '''events''' or if '''requested''' by the User. | ||
=== Serial port=== | === Serial port=== | ||
Communication is done with: | Communication is done with: | ||
− | * | + | * Resting state : HIGH |
− | * 8 bits | + | * Data bits : 8 |
− | * | + | * Parity : none |
− | * | + | * Stop bits : 1 |
+ | * Handshake : none | ||
+ | * Baudrate : 115'200 | ||
=== Message Format === | === Message Format === | ||
Line 21: | Line 27: | ||
! EoF (1 byte) | ! EoF (1 byte) | ||
|- | |- | ||
− | | | + | | 0xAA |
| UINT8 | | UINT8 | ||
− | | UINT16/INT16 | + | | UINT16/INT16/VECTOR16 (MSB first) |
+ | | [https://crccalc.com/ CRC8/ITU] | ||
+ | |} | ||
+ | |||
+ | The address is decomposed as follows: 0bMMWRRRRR | ||
+ | * MM : targeted module | ||
+ | ** 0b00 : DC Motor | ||
+ | ** 0b01 : Stepper Motor | ||
+ | ** 0b10 : Sensors | ||
+ | ** 0b11 : Control Registers | ||
+ | * W : defines if the data is saved to ('1') or read from ('0') the FPGA | ||
+ | ** The FPGA will '''respond to a request''' with the exact same address when W = '0' | ||
+ | ** The FPGA will '''save incoming data in the targeted register''' when W = '1' | ||
+ | ** The FPGA will '''send data on predefined events''' with the W bit set to '0' | ||
+ | * RRRRR : targeted register | ||
+ | |||
+ | ==== Frame example ==== | ||
+ | |||
+ | For the BLE module to light LED1 with it changing each 500 ms, the following frame is sent: | ||
+ | {| cellpadding="8" cellspacing="0" border="1" | ||
+ | ! SoF (1 byte) | ||
+ | ! Address (1 byte) | ||
+ | ! Data High (1 byte) | ||
+ | ! Data Low (1 byte) | ||
+ | ! EoF (1 byte) | ||
+ | |- | ||
| 0xAA | | 0xAA | ||
+ | | 0b10100001 | ||
+ | | 0b10000001 | ||
+ | | 0b11110100 | ||
+ | | 0x74 | ||
|} | |} | ||
== Registers == | == Registers == | ||
− | === | + | === DC Motor === |
+ | |||
+ | Reading range : 0x00 to 0x1F | ||
+ | |||
+ | Writing range : 0x20 to 0x3F | ||
{| cellpadding="4" cellspacing="0" border="1" | {| cellpadding="4" cellspacing="0" border="1" | ||
! Address | ! Address | ||
− | ! | + | ! Name |
+ | ! Type | ||
! Description | ! Description | ||
+ | ! Direction | ||
+ | ! Event | ||
|- | |- | ||
| 0 | | 0 | ||
− | | | + | | Prescaler |
− | | DC | + | | Uint16 |
+ | | DC PWM frequency, as fclk / (PWMsteps * prescaler) = 10M / (16 * prescaler) | ||
+ | | Smartphone -> Kart | ||
+ | | | ||
|- | |- | ||
| 1 | | 1 | ||
− | | | + | | Speed |
− | | | + | | Int5 |
− | + | | Desired speed, from -15 (0xFFF1) to 15 (0x000F) (negative = backward) | |
− | + | | Smartphone -> Kart | |
− | + | | | |
− | + | ||
− | |- | + | |
− | | | + | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | ||
|} | |} | ||
− | === | + | |
+ | === Stepper Motor === | ||
+ | |||
+ | Reading range : 0x40 to 0x5F | ||
+ | |||
+ | Writing range : 0x60 to 0x7F | ||
{| cellpadding="4" cellspacing="0" border="1" | {| cellpadding="4" cellspacing="0" border="1" | ||
! Address | ! Address | ||
− | ! | + | ! Name |
+ | ! Type | ||
! Description | ! Description | ||
+ | ! Direction | ||
+ | ! Event | ||
|- | |- | ||
| 0 | | 0 | ||
− | | | + | | Prescaler |
− | | | + | | Uint16 |
+ | | Stepper switching frequency, as 100k / prescaler | ||
+ | | Smartphone -> Kart | ||
+ | | | ||
|- | |- | ||
| 1 | | 1 | ||
− | | | + | | Target angle |
− | | | + | | Uint16 |
+ | | Desired steering angle, in motor steps (0 = end switch) | ||
+ | | Smartphone -> Kart | ||
+ | | | ||
|- | |- | ||
| 2 | | 2 | ||
− | | | + | | Actual angle |
− | | | + | | Uint16 |
+ | | Actual steering angle, in motor steps (0 = end switch) | ||
+ | | Kart -> Smartphone | ||
+ | | When a delta of at least STP_ANGLE_DELTA_DEG (3°) from the last registered value happens | ||
|- | |- | ||
| 3 | | 3 | ||
− | | | + | | Stepper HW |
− | | | + | | Uint14 + Vector2 |
+ | | Bit 0: stepper end | ||
+ | Bit 1: position reached | ||
+ | |||
+ | Bits 15 - 2 : actual steering angle | ||
+ | | Kart -> Smartphone | ||
+ | | Sent when stepper end is pressed (rising edge) or position reached (rising edge) | ||
+ | |} | ||
+ | |||
+ | === Sensors === | ||
+ | |||
+ | Reading range : 0x80 to 0x9F | ||
+ | |||
+ | Writing range : 0xA0 to 0xBF | ||
+ | |||
+ | {| cellpadding="4" cellspacing="0" border="1" | ||
+ | ! Address | ||
+ | ! Name | ||
+ | ! Type | ||
+ | ! Description | ||
+ | ! Direction | ||
+ | ! Event | ||
|- | |- | ||
− | | | + | | 0 |
− | | | + | | LED1 |
− | | | + | | Bit + Uint15 |
+ | | Bit 15: on / off/ | ||
+ | Bits 14 -> 0: half-period in ms (if 0, led status = bit 15) | ||
+ | | Smartphone -> Kart | ||
+ | | | ||
|- | |- | ||
− | | | + | | ... |
− | | | + | | |
− | | | + | | |
+ | | | ||
+ | | | ||
+ | | | ||
|- | |- | ||
− | | | + | | 7 |
− | | | + | | LED8 |
− | | | + | | Bit + Uint15 |
+ | | ''See LED1'' | ||
+ | | Smartphone -> Kart | ||
+ | | | ||
|- | |- | ||
− | | | + | | 8 |
− | | | + | | Voltage |
− | | | + | | Uint16 |
+ | | Battery voltage, U = register * 250e-6 * 7.8 [V] | ||
+ | | Kart -> Smartphone | ||
+ | | When a delta of at least SENS_BATT_DELTA_MV (50) from the last registered value happens | ||
|- | |- | ||
− | | | + | | 9 |
− | | | + | | Current |
− | | | + | | Uint16 |
+ | | Consumed current, I = register * 250e-6 / (100 * 5e-3) [A] | ||
+ | | Kart -> Smartphone | ||
+ | | When a delta of at least SENS_CURR_DELTA_MA (50) from the last registered value happens | ||
|- | |- | ||
− | | | + | | A |
− | | | + | | Range finder |
− | | | + | | Uint16 |
+ | | Distance to sensor, register * 25.4 / (147*e-6 * (10M / 10)) [mm] | ||
+ | Register zeroed if less than 152 mm (sensor min distance) or greater than 1500 mm (arbitrary max distance), event not sent in such case | ||
+ | | Kart -> Smartphone | ||
+ | | When a delta of at least SENS_RANGEFNDR_MM (60) from the last registered value happens | ||
|- | |- | ||
− | | | + | | B |
− | | | + | | End switches |
− | | | + | | Vector(16) |
+ | | Sensors current values, right justified (sensor 1 is bit 0) | ||
+ | | Kart -> Smartphone | ||
+ | | On any edge change of any sensor | ||
|- | |- | ||
− | | | + | | C |
− | | | + | | Hall1 |
− | | | + | | Uint16 |
+ | | Hall pulses count, zeroed on overflow of the register | ||
+ | | Kart -> Smartphone | ||
+ | | Each 100 ms if value changed from last time | ||
|- | |- | ||
− | | | + | | D |
− | | | + | | Hall2 |
− | | | + | | Uint16 |
− | | | + | | ''See Hall1'' |
− | + | | Kart -> Smartphone | |
− | + | | Each 101 ms if value changed from last time | |
− | + | ||
− | |- | + | |
− | | | + | |
− | + | ||
− | + | ||
|} | |} | ||
− | === | + | === Control Registers === |
+ | |||
+ | Reading range : 0xC0 to 0xDF | ||
+ | |||
+ | Writing range : 0xE0 to 0xFF | ||
{| cellpadding="4" cellspacing="0" border="1" | {| cellpadding="4" cellspacing="0" border="1" | ||
− | ! | + | ! Address |
− | ! | + | ! Name |
+ | ! Type | ||
! Description | ! Description | ||
+ | ! Direction | ||
+ | ! Comment | ||
|- | |- | ||
| 0 | | 0 | ||
− | | | + | | Hardware Control |
− | | | + | | Vector6 |
+ | | Bit 0: when '0', the Kart goes backwards when the motor turns foward | ||
+ | Bit 1: when '1', the Kart turns to the right as the stepper coils go from 1 to 4 | ||
+ | |||
+ | Bit 2: when '1', the angles are measured clockwise | ||
+ | |||
+ | Bit 3: emulates the end switch contact for the stepper motor | ||
+ | |||
+ | Bit 4: restart the stepperMotor module, stops the DC motor while '1' | ||
+ | | Smartphone -> Kart | ||
+ | | The end sensor always defines angle 0. Angles are always positive numbers in registers. | ||
+ | If bits 1 and 2 are different, the stepper motor phase sequence has to be inverted. | ||
+ | If the Bluetooth connection is lost, the DC motor has to be stopped. | ||
|- | |- | ||
| 1 | | 1 | ||
− | | | + | | BT Status |
− | | | + | | Vector1 |
− | |- | + | | Bit 0: when '0', the smartphone is disconnected |
− | | | + | | NRF -> Kart |
− | + | | The register is set by the NRF itself, since it is not possible to foresee the disconnection. | |
− | + | ||
|} | |} | ||
− | + | == Kart init == | |
− | + | To init the Kart, the following sequence should be sent to the Kart: | |
+ | * Write '''DC Motor | Prescaler''' to '''31''' (around 21 kHz PWM frequency) | ||
+ | * Write '''Stepper Motor | Prescaler''' to '''400''' (250 Hz coil switching frequency) | ||
+ | * Tell the smartphone is connected by writing '''Control Registers | BT status''' to 1 | ||
+ | * Write '''Control Registers | Hardware Control''' to restart the system (0b10xxx) | ||
+ | ** The stepper should turn until hitting the end switch, except if already on it | ||
+ | * Read '''Stepper Motor | Stepper HW''' and check the last bit | ||
+ | ** If is '1', it means we are already zeroed | ||
+ | ** If not, wait for an event from this register to tell the reset is complete | ||
+ | * Write '''Control Registers | Hardware Control''' to deassert the reset (0b00xxx) | ||
+ | |||
+ | The Kart is now ready to function ! | ||
+ | |||
+ | Note that the '''Control Registers | restart''' bit is automatically reset back to 0 when the | ||
+ | ''stepper_end'' input is activated. | ||
+ | |||
+ | == Testing through USB == | ||
+ | [[File:Kart_kci.jpg|450px|right|Kart Command Interpreter]] | ||
+ | To test the Kart from a PC directly, one can do as follows: | ||
+ | * Remove the [[Kart/Bluetooth|BLE]] from the [[Kart/Motherboard|motherboard]] (or, at least, do not connect to a smartphone) | ||
+ | * Power the [[Kart/Motherboard|motherboard]] with a DC voltage regulator (+12V) | ||
+ | * Wire the USB-C present on the daughterboard to your PC | ||
+ | ** Two new COM ports should be detected | ||
+ | * Download and open the '''Kart Command Interpreter''' utility (available in the VHDL project -> CommandInterpreter) | ||
+ | ** [https://github.com/hei-synd-2131-eln/eln-kart/blob/master/CommandInterpreter/KartCommandInterpreter_WIN.exe Windows 10] | ||
+ | ** [https://github.com/hei-synd-2131-eln/eln-kart/blob/master/CommandInterpreter/KartCommandInterpreter_LIN Linux] | ||
+ | ** [https://github.com/hei-synd-2131-eln/eln-kart/blob/master/CommandInterpreter/commandInterpreter.py Source code] | ||
+ | * In the top menu '''Serial -> Port''', select the correct COM port (should be the biggest of the two new ports) | ||
+ | ** You can also change the baudrate, by default '''115'200''' (the correct one if it was not modified) | ||
+ | |||
+ | To test the connection, click the '''Read''' button. The '''Tx''' and '''Rx''' values should change, and a text added to the text area. | ||
+ | |||
+ | === Simple operation === | ||
+ | The simplest way to test both motors are the three button at the bottom. | ||
+ | |||
+ | * '''Init Kart''' button | ||
+ | ** Will set the DC prescaler, stepper prescaler, and execute the restart sequence. '''Must be clicked first.''' | ||
+ | ** Answer the 4 prompts following your hardware configuration. | ||
+ | * '''DC Motor''' button | ||
+ | ** Will set the DC speed to full for 2s, quickly 0, then reversed full speed for 2s | ||
+ | * '''Stepper Motor''' button | ||
+ | ** Will set the stepper to 400 (30°) then 0 | ||
+ | |||
+ | === Custom operation === | ||
+ | Each register can be read and/or written by hand following their [[Kart/serial_link#Registers|data description]]. | ||
+ | |||
+ | For this, select the '''Module''' first, then which '''Register'''. | ||
+ | |||
+ | ==== Read ==== | ||
+ | To read, simply click the '''Read''' button. Successful read will be shown in green (CRC is ok) and logged, with extra info (e.g. for the DC prescaler, will give the motor frequency). | ||
+ | |||
+ | ==== Write ==== | ||
+ | To write, enter a value in the value box such as: | ||
+ | * Direct integer (only DC speed should be negative) | ||
+ | * '''0b'''xxxx binary values | ||
+ | * '''0x'''xxxx hexadecimal values | ||
+ | * ''Other values will throw an error'' | ||
+ | |||
+ | Then click on the '''Write''' button. | ||
+ | |||
+ | === Reset === | ||
+ | In case of problem, you can simply power-cycle the FPGA board to reset the registers. | ||
[[Category:Kart]] | [[Category:Kart]] |
Latest revision as of 11:49, 7 July 2023
|
Serial link protocol
This section defines the serial link protocol used to communicate between the Kart and the BLE module / PC / Android Smartphone.
General principle
The system is using a BLE module.
To avoid congesting the line, data are sent from the Kart to the User on specific events or if requested by the User.
Serial port
Communication is done with:
- Resting state : HIGH
- Data bits : 8
- Parity : none
- Stop bits : 1
- Handshake : none
- Baudrate : 115'200
Message Format
SoF (1 byte) | Address (1 byte) | Data (2 bytes) | EoF (1 byte) |
---|---|---|---|
0xAA | UINT8 | UINT16/INT16/VECTOR16 (MSB first) | CRC8/ITU |
The address is decomposed as follows: 0bMMWRRRRR
- MM : targeted module
- 0b00 : DC Motor
- 0b01 : Stepper Motor
- 0b10 : Sensors
- 0b11 : Control Registers
- W : defines if the data is saved to ('1') or read from ('0') the FPGA
- The FPGA will respond to a request with the exact same address when W = '0'
- The FPGA will save incoming data in the targeted register when W = '1'
- The FPGA will send data on predefined events with the W bit set to '0'
- RRRRR : targeted register
Frame example
For the BLE module to light LED1 with it changing each 500 ms, the following frame is sent:
SoF (1 byte) | Address (1 byte) | Data High (1 byte) | Data Low (1 byte) | EoF (1 byte) |
---|---|---|---|---|
0xAA | 0b10100001 | 0b10000001 | 0b11110100 | 0x74 |
Registers
DC Motor
Reading range : 0x00 to 0x1F
Writing range : 0x20 to 0x3F
Address | Name | Type | Description | Direction | Event |
---|---|---|---|---|---|
0 | Prescaler | Uint16 | DC PWM frequency, as fclk / (PWMsteps * prescaler) = 10M / (16 * prescaler) | Smartphone -> Kart | |
1 | Speed | Int5 | Desired speed, from -15 (0xFFF1) to 15 (0x000F) (negative = backward) | Smartphone -> Kart |
Stepper Motor
Reading range : 0x40 to 0x5F
Writing range : 0x60 to 0x7F
Address | Name | Type | Description | Direction | Event |
---|---|---|---|---|---|
0 | Prescaler | Uint16 | Stepper switching frequency, as 100k / prescaler | Smartphone -> Kart | |
1 | Target angle | Uint16 | Desired steering angle, in motor steps (0 = end switch) | Smartphone -> Kart | |
2 | Actual angle | Uint16 | Actual steering angle, in motor steps (0 = end switch) | Kart -> Smartphone | When a delta of at least STP_ANGLE_DELTA_DEG (3°) from the last registered value happens |
3 | Stepper HW | Uint14 + Vector2 | Bit 0: stepper end
Bit 1: position reached Bits 15 - 2 : actual steering angle |
Kart -> Smartphone | Sent when stepper end is pressed (rising edge) or position reached (rising edge) |
Sensors
Reading range : 0x80 to 0x9F
Writing range : 0xA0 to 0xBF
Address | Name | Type | Description | Direction | Event |
---|---|---|---|---|---|
0 | LED1 | Bit + Uint15 | Bit 15: on / off/
Bits 14 -> 0: half-period in ms (if 0, led status = bit 15) |
Smartphone -> Kart | |
... | |||||
7 | LED8 | Bit + Uint15 | See LED1 | Smartphone -> Kart | |
8 | Voltage | Uint16 | Battery voltage, U = register * 250e-6 * 7.8 [V] | Kart -> Smartphone | When a delta of at least SENS_BATT_DELTA_MV (50) from the last registered value happens |
9 | Current | Uint16 | Consumed current, I = register * 250e-6 / (100 * 5e-3) [A] | Kart -> Smartphone | When a delta of at least SENS_CURR_DELTA_MA (50) from the last registered value happens |
A | Range finder | Uint16 | Distance to sensor, register * 25.4 / (147*e-6 * (10M / 10)) [mm]
Register zeroed if less than 152 mm (sensor min distance) or greater than 1500 mm (arbitrary max distance), event not sent in such case |
Kart -> Smartphone | When a delta of at least SENS_RANGEFNDR_MM (60) from the last registered value happens |
B | End switches | Vector(16) | Sensors current values, right justified (sensor 1 is bit 0) | Kart -> Smartphone | On any edge change of any sensor |
C | Hall1 | Uint16 | Hall pulses count, zeroed on overflow of the register | Kart -> Smartphone | Each 100 ms if value changed from last time |
D | Hall2 | Uint16 | See Hall1 | Kart -> Smartphone | Each 101 ms if value changed from last time |
Control Registers
Reading range : 0xC0 to 0xDF
Writing range : 0xE0 to 0xFF
Address | Name | Type | Description | Direction | Comment |
---|---|---|---|---|---|
0 | Hardware Control | Vector6 | Bit 0: when '0', the Kart goes backwards when the motor turns foward
Bit 1: when '1', the Kart turns to the right as the stepper coils go from 1 to 4 Bit 2: when '1', the angles are measured clockwise Bit 3: emulates the end switch contact for the stepper motor Bit 4: restart the stepperMotor module, stops the DC motor while '1' |
Smartphone -> Kart | The end sensor always defines angle 0. Angles are always positive numbers in registers.
If bits 1 and 2 are different, the stepper motor phase sequence has to be inverted. If the Bluetooth connection is lost, the DC motor has to be stopped. |
1 | BT Status | Vector1 | Bit 0: when '0', the smartphone is disconnected | NRF -> Kart | The register is set by the NRF itself, since it is not possible to foresee the disconnection. |
Kart init
To init the Kart, the following sequence should be sent to the Kart:
- Write DC Motor | Prescaler to 31 (around 21 kHz PWM frequency)
- Write Stepper Motor | Prescaler to 400 (250 Hz coil switching frequency)
- Tell the smartphone is connected by writing Control Registers | BT status to 1
- Write Control Registers | Hardware Control to restart the system (0b10xxx)
- The stepper should turn until hitting the end switch, except if already on it
- Read Stepper Motor | Stepper HW and check the last bit
- If is '1', it means we are already zeroed
- If not, wait for an event from this register to tell the reset is complete
- Write Control Registers | Hardware Control to deassert the reset (0b00xxx)
The Kart is now ready to function !
Note that the Control Registers | restart bit is automatically reset back to 0 when the stepper_end input is activated.
Testing through USB
To test the Kart from a PC directly, one can do as follows:
- Remove the BLE from the motherboard (or, at least, do not connect to a smartphone)
- Power the motherboard with a DC voltage regulator (+12V)
- Wire the USB-C present on the daughterboard to your PC
- Two new COM ports should be detected
- Download and open the Kart Command Interpreter utility (available in the VHDL project -> CommandInterpreter)
- In the top menu Serial -> Port, select the correct COM port (should be the biggest of the two new ports)
- You can also change the baudrate, by default 115'200 (the correct one if it was not modified)
To test the connection, click the Read button. The Tx and Rx values should change, and a text added to the text area.
Simple operation
The simplest way to test both motors are the three button at the bottom.
- Init Kart button
- Will set the DC prescaler, stepper prescaler, and execute the restart sequence. Must be clicked first.
- Answer the 4 prompts following your hardware configuration.
- DC Motor button
- Will set the DC speed to full for 2s, quickly 0, then reversed full speed for 2s
- Stepper Motor button
- Will set the stepper to 400 (30°) then 0
Custom operation
Each register can be read and/or written by hand following their data description.
For this, select the Module first, then which Register.
Read
To read, simply click the Read button. Successful read will be shown in green (CRC is ok) and logged, with extra info (e.g. for the DC prescaler, will give the motor frequency).
Write
To write, enter a value in the value box such as:
- Direct integer (only DC speed should be negative)
- 0bxxxx binary values
- 0xxxxx hexadecimal values
- Other values will throw an error
Then click on the Write button.
Reset
In case of problem, you can simply power-cycle the FPGA board to reset the registers.