Lanciers: Difference between revisions
| Line 369: | Line 369: | ||
svn://repos.gbar.dtu.dk/jcan/regbot/regbot | svn://repos.gbar.dtu.dk/jcan/regbot/regbot | ||
An introduction is found here [[Regbot firmware]]. | An introduction is found here: [[Regbot firmware]]. | ||
The mission command language is described here: [[Regbot command interface]]. | The mission command language is described here: [[Regbot command interface]]. | ||
More [[Regbot]] items. | More [[Regbot]] items. | ||
Revision as of 12:13, 24 November 2025
Lanciers demo robots
Eight of these robots are planned to perform a group performance, similar to one of the tours in Lanciers.
Therefore, the robot is called a dancer, and the robot group manager a dance master.
Hardware
The robot
Each of the robots consists of two motors and a driver board of the same type used by Regbot.
- Motor is type JGB37-545 with 1:10 or 1:19 gearing and 17 pole encoder (68 ticks per rev).
- The external gear has 84/24 teeth.
- The wheel distance is 14.5cm
- Wheel diameter 7.3cm
- The robot's total mass is 1.35 kg.
- Motor mass is 270g each.
- The PCB mass is 98g.
- The 2.2 Ah battery mass is 167g.
Dance master
The dance master is a Raspberry Pi.
The communication between the two is a (maybe one-way) LoRa radio connection at 433 MHz.
The dance master obtains the position of each dancer from either Optitrack or by using a camera. The robots are then either equipped with a unique pattern of reflectors or a unique ArUco code.
LoRa radio
The LoRa radio connection uses an RFM98W radio module from HOPERF Electronics.
Connections on RFM98W
ant GND GND top DIO5 DIO3 view reset DIO4 NSS (CS) 3.3V RFM SCK DIO0 98W MOSI DIO1 MISO DIO2 GND
Antenna 16cm wire.
Dancer side
Hardware
Radio RFM98W to Regbot 6.3 board
Connector 1 (5-pin JST-ph 2mm)
1 black - 3.3V 2 red - SCK 3 white - MOSI 4 yellow - MISO 5 orange - GND
Connector 2 (line sensor 10-pin IDC connector 2.54mm)
1, 2 NC 3 blue - DIO0 (tx int) 4 green - DIO5 5 yellow - reset 6 orange - NSS (CS) 7 red - DIO1 8 brown - DIO4 9,10 NC
Software
On the dancer side, the library used is the RFM98W_library from https://github.com/weustace/LoRaLib.
The configuration is controlled by 6 register values, of which only 4 are used:
/* # data sheet
* # register
* # byte 1: reg 1D, 4msb = BW 7 = 125 kHz, 9 = 500 kHz, 4 = 15.6 kHz
* # 4lsb = error coding 2 = 4/5, 8=4/8
* # byte 2: reg 1E, 4msb spreading factor: 7=128 chips / symbol, 9=512 c/s, c=4096 c/s
* # 4lsb mode: 4 = CRC on
* # byte 3: reg 09, bit 7=PAboost 1=used, 0=not, bit 6-4 = base power 0=10.8dBm,
* 4lsb power reduction 0=full power, 8 = half power f=minimum power (1dBm)
* # byte 4,5 not used.
* # byte 6: reg 26, 4msb = 0,
* # 4lsb: 4=AGC internal, not mobile, C= AGC internal + mobile node
*/
// byte my_config[6] = {0x72,0x74,0x8F,0xAC,0xCD, 0x0C}; // fair - Pi ok (too slow)
byte my_config[6] = {0x92,0x74,0x8F,0xAC,0xCD, 0x0C}; // faster - Pi ok (ca. 15-20 ms per message (10 chars))
radio.configure(my_config);
radio.setFrequency(434700000);
This gives the following:
- The bandwidth used is 125kHz with coding rate of 4/5 (minimal overhead of 25%).
- Spreading factor 7 increases the sensitivity by 7.5dB
- Automatic AGC loop and flag as mobile.
The first two values need to be equal on both the receiver and the transmitter.
An interrupt is activated when a message is received. This should enable the rapid implementation of new mission plans without the need for constant polling for messages.
Note that at times, garbage is received, but then the CRC will return false.
Dance master side
The dance master is on the Raspberry Py and uses the pyLoraRFM9x library.
This is configured with 3 bytes:
from pyLoraRFM9x import LoRa, ModemConfig import time from enum import Enum class MC(Enum): Bw125Cr45Sf128 = (0x72, 0x74, 0x04) # Radiohead default fast = (0x92, 0x74, 0x0C) # a bit too much (500kHz bandwidth) fair = (0x72, 0x74, 0x0C) # mobile bit set (used)
The full setup is when the radio is instantiated:
# LoRa(CS pin, interrupt, ID, port, reset, frq, Tx power, modem config, ack lora = LoRa(1, 24, 127, 0, 25, 434.7, 10, MC.fair, True)
- Uses chip select pin 1 (GPIO7, NSS on radio), reset is pin GPIO25, and tx-interrupt is GPIO 24 (DIO0 on radio side).
- The device port is 0 (pins GPIO9 (MISO), GPIO10 (MOSI), and GPIO11 (CLK).
- Additionally, 3.3V and ground are connected.
- In total, 10 pins of the Raspberry Pi connector are used.
Dance master radio interface
Interface cable
IDC on Raspberry to radio 1(red) 17 3.3V 18 GPIO24 - DIO0 - interrupt 3 19 MOSI 20 Ground 5 21 MISO 22 GPIO25 - reset 7 23 CLOCK 24 GPIO08 - NC 9 25 Ground 26 GPIO07 - CS/NSS
On the Raspberry Pi side, a 10-pin header is used, which requires cutting pins 15, 16, 27, and 28.
Python:
from pyLoraRFM9x import LoRa, ModemConfig
import time
from enum import Enum
import timeit
#
# Called when message is received
def on_recv(payload):
print("From:", payload.header_from)
print("Received:", payload.message)
print("RSSI: {}; SNR: {}".format(payload.rssi, payload.snr))
#
#
class MC(Enum):
Bw125Cr45Sf128 = (0x72, 0x74, 0x04) # Radiohead default
fast = (0x92, 0x74, 0x0C) # 500kHz BW, mobile bit set
fair = (0x72, 0x74, 0x0C) # 125kHz BW, mobile bit set
# register ModemConfig
# byte 1: reg 1D, 4msb = BW 7 = 125 kHz, 9 = 500 kHz, 4 = 15.6 kHz
# 4lsb = error coding 2 = 4/5, 8=4/8
# byte 2: reg 1E, 4msb spreading: 7=128 chips/symbol, 9=512 ch/sy, c=4096 ch/sy
# 4lsb mode: 4 = CRC on
# byte 3: reg 26, 4msb = 0, 4lsb: 4=AGC internal, static node, c= AGC internal + mobile node
# LoRa(CS pin, interrupt, ID, port, reset, frq, Tx power, modem config, ack
lora = LoRa(1, 24, 127, 0, 25, 434.7, 10, MC.fair, True)
lora.on_recv = on_recv
#
# Send a message to a recipient device with address 10
# Retry sending the message twice if we don't get an acknowledgement from the recipient
message = "Hello there!"
cnt = 0
while True and message != "quit":
start = time.time()
status = lora.send_to_wait(message, 10, retries=0)
end = time.time()
print("# msg time")
print(end - start)
time.sleep(0.01)
if status is True:
print("Message sent: " + message)
else:
print("No acknowledgment from recipient")
cnt += 1
message = input("quit or msg to send >>")
- It takes about 60ms to send 10 characters with this setting (tested with two only).
- All receivers get the same message (i.e. the ID number is vital)
- Runs in a virtual venv environment:
Python virtual environment
Create a virtual environment.
python3 -m venv ~/.venv source .venv/bin/activate
Install pyLoraRFM9x (from within venv)
pip install --upgrade pyLoraRFM9x
Enable SPI interface on the Raspberry PI
sudo raspi-config -> interface options -> SPI -> enable
Default activation of venv from .bashrc
Part of .bashrc
# give Python priority to virtual environment (LoRa - comm with RFM98W) source .venv/bin/activate
Dancer Control
Velocity
The transfer function from motor voltage to wheel velocity gives this Bode plot (from simulation)
This is a standard low-pass system that calls for a PI controller.
On OK design:
- PI-zero at 30 rad/s, tau_i = 0.043 sec,
- Feed forward = 7
- phase margin of 77 degrees,
- cross-over at 13 rad/s,
- Kp = 10
- Low pass in return path tau_pole = 0.007 sec
- output limit 10V (same for integrator)
Balance
- Kp = -0.55
- tau_i = 0.1 (PI integrator)
- tauii = 0.1 (post integrator)
- alpha = 0.1 (lead in return path)
- tau_d = 0.15 (lead in return path)
- output limit 1.0 (m/s)
Velocity in balance
P-controller
- Kp = -1.5
Works fine in simulation, but in practice, an integrator is needed.
After hand-tuning, this seems better.
- Kp = -2
- Lag in forward: tau_zero=0.03 sec, tau_pole=0.1 sec
- Lead in return: tau_zero=0.06 sec, tau_pole=0.012 sec
- Integrator: tau_zero=1 sec, limit = 0.3 rad.
- Output limit 0.3 rad.
Gives the following step response in simulation and on the robot:
Heading
P-controller
- Kp = 1.0;
- lead in feedback path: tai_zero=0.22 sec, tau_pole=0.07 sec.
- integrator: tau_zero=0.1 sec, limit = 0.15 m/sec (wheel velocity difference);
Position
The position controller is hand-tuned:
- Kp = 2
- Lead in feedback path: tau_zero=0.5 sec, tau_pole=0.075 sec
- Integrator: tau_zero=0.8 sec, limit = 1m/sec
- The output limit is not set, but is implemented in software to match mission velocity.
The integrator is stopped if any limit in the control chain is limiting.
Issues
Heading angles are positive clockwise. This may be a consequence of the left and right motor connections on board being swapped. It is reversed to account for IMU board mounting.
This may have issues for mission parameters. ... testing
Dancer software
Dancer software is an extended version of the Regbot software, where IO is extended to accept commands from the LoRa receiver. No return channel is enabled.
Version 0 control parameters:
Firmware
The Lanciers firmware is identical to Regbot firmware.
The radio communication is enabled by
rfmuse 1
The LoRa coding has three configurations hard-coded; configuration one is reasonably fast. Changing the configuration requires a reboot. Ten 8-bit characters take about 16ms to transmit.
rfmcfg 1
It can then be enabled at boot by saving the status to flash
eew
A reboot may be needed.
reboot
This allows commands to be sent through the radio channel.
Dance master software
To be made.
Matlab (mm)
A MATLAB/Simulink model is available in an SVN repository.
SVN is short for Subversion and is a repository like GIT, but a bit older.
The command line to get the Lanciers files is
svn checkout svn://repos.gbar.dtu.dk/jcan/lanciers
This works after the installation of SVN support:
- Linux: install the subversion package:
sudo apt install subversion
- Windows: Install e.g. svn Tortoise:
https://tortoisesvn.net/downloads.html
Matlab model
The relevant files are:
robot_locomotion_2_ctrl.slx (The Simulink model) robot_script_2.m (Script for variables - and all PID control calculations)
LoRa Radio test
In the rfm9x directory is a Python script for testing the radio connection:
radio.py
Robot software
The robot firmware is a modified version of the Regbot software. The software is written in C++ in an Arduino-style. With minor adaptations, it can be maintained by VS Code.
This is available in a different SVN repository:
svn://repos.gbar.dtu.dk/jcan/regbot/regbot
An introduction is found here: Regbot firmware.
The mission command language is described here: Regbot command interface.
More Regbot items.