Self standing balancing robot

nRF52 mesh of motion sensors, Gazebo for physics simulation, BLDC motors simulation and control, CAD with Fusion 360. Fully Open source.

Public Chat
Similar projects worth following
Open source hobby project to create a robot with an original structure that moves in a home environment.
The robot structure is a double sided inverted pendulum, with the ability to stand up switching from flat mode (car) to the standing mode (balancing robot), on each of its sides. Further dynamic behaviors to be expected.
So at the end, will it stand up ?
This project is just starting and won't be limited to a single design, rather open to a try and fail approach with multiple design paths. So if you'd like to contribute, you can post comments, ideas,... You can have a look at the shared design on google docs and onenotes.


  • A gazebo simulation approximates the robot's physics and allows the user to control it with a joystick to have a feeling of the robot's power depending on the weight and motors power.
  • nRF52840 Allows high throughput log with native usb uspport.
  • A custom RF protocol allows 1 ms order of magnitude for mesh network communication between the different robots part.
  • The Programmable peripheral Interconnect feature of the nRF family is leveraged to increase real time responsiveness of events. This is like having a small FPGA interconnect inside of a powerful micro controller.
  • C++ drivers wrappers and Standard library support.


  • The robot shall have a body and 4 limbs.
  • Each limb shall have a motorized joint connecting it to the body.
  • Each limb shall have a motorized wheel.
  • In flat mode, the robot shall be able to move like a tank.
  • The robot shall be able to go from flat mode to standing mode.
  • The robot shall be able to keep balance and move in standing mode.
  • All articulations shall be reversible, to allow force control loop (smooth interactive reaction).

Github repo structure

(includes 1 level of submodules)

Shared development on google drive

Shared notes on OneNote

  • notes : draft packing of all notes related to selections, development links, ongoing progress,...

Video of the gazebo simulation

Construction thoughts

The construction details are not set yet, thoughts go around BLDCs and pulleys.


jtag pogo adapter

BLDC Test bench

Encoder for testing purpose

Experiments with sensored motor

I used AH3503 so far which are 4.5 V min rated but under powered with 3.3, in the meantime I ordered some OH49E that are 2.3 - 10 V so should be fine with 3.3 V within the specs.

nRF52 SDK with nrfx drivers, c++11 and standard library

This example application is somehow a step forward, as I finally managed to :

  • use the latest nrfx API and get rid of the clumsy nrf_drv_ wrapper usage (at least for bldc.cpp as example)
  • get rid of the headache of sdk_config.h (at least for bldc and pwm config)
  • wrap usage in c++ so that as example the the bldc_c takes the config params in the constructor for a dead simple Arduino like c++ class usage.
  • add support for the standard library std::string and others after quite a search to find that I had to link the lib (-lstdc++) in the linker flag, as simple as that (see makefiel)

Line to mqtt with json payload

Only after all the previous listed enhancements, it because easy to parse a line text protocol. That allows to get rid of binary traslation of packets as this text like is jsonish in a way that it's a key:value structure but simple as it is unidimensional.

  • Encoder for the bldc test bench

    Wassim01/04/2019 at 21:15 0 comments

    Rotary encoder 600 steps

    nRF52 Firmware

    After the failure to use the qdec peripheral, fallback was on pio, interrupt, but that gives another advantage, the one of capturing timestamp on the nRF for every event, so that the log to the pc does not induce any speed signal distortion.

    This is how the mqtt messages look like

    jNodes/75/text {"ts": "597185480", "A": "1432", "B": "1428", "H": "1660"}
    jNodes/75/text {"ts": "597191402", "A": "1432", "B": "1429", "H": "1661"}
    jNodes/75/text {"ts": "597399004", "A": "1432", "B": "1430", "H": "1662"}
    jNodes/75/text {"ts": "597406683", "A": "1431", "B": "1430", "H": "1661"}
    jNodes/75/text {"ts": "597417026", "A": "1430", "B": "1429", "H": "1659"}
    jNodes/75/text {"ts": "597424182", "A": "1429", "B": "1428", "H": "1657"}

    Timesamped view of the motor position (angle step)

    • Note that the firmware does not always report at the highest sampling rate, rather report on change, with a minimal cycle, then when no changes, keep a slow (1 sec) alive signal to show the user on the live graph that the position did not change.
    • It is nice to see the data path, from the microcontroller that logs in rf, serial python to MQTT, then an MQTT browser client link it to plotly that can export the data to be shared on an iframe and embedded right here !
    • actually iframes are filtered out from hackaday, so simply a screenshot and the interactive plot is availabe through the link : interactive plot

  • BLDC Static torque Test bench

    Wassim01/03/2019 at 11:37 0 comments


    • Identify the BLDC motor static torque
    • simply put : How many grams can it hold how far  ?

    PC Gui repo :

    firmware repo :

    Run the web app and the python serial to mqtt gateway

    start python py_rf_serial/
    start live-server web_plot

     Web gui :

    Monitor MQTT messages

    pi@rfserv:~ $ sub 'jNodes/75/#' -t 'Nodes/75/#' -v | ts

    Motor under test

    Torque measure

    The photo was taken without pressure on the motor, so the 8.9 grams pointed out are not relevant, see results for measures summary


    a current limit is set and when the measure is performed, it is simply checked if the current limit is reached by checking if the voltage drops or not.


    only direct pio permanent enable is shown, the pwm sine control is excluded for the moment

    ESCCoil4 cm measure1 cm conversionNm
    7.2 V3.8 V 310 mA75 g300 g.cm0.029


    • It's important to make sure the voltage measure is at the motor coil not at the power supply or ESC input.
    • The torque measures are descent for such  motor size, still quite disappointing when it comes to direct motor drive expectations.
    • The pwm sine flow control does not provide the highest possible torque, which was to be expected. In the pwm sine control, when one coil pwm is at its maximum, the other two do have partial triggering as well, which is counter productive when it comes to maintain the motor holding its step.
    • a simple set of one enable pin (one coil) to high voltage, provided a higher torque and higher current consumption


    • use a different angle function for the pwm values generation that is not sinus rather one that gives full throttle to one channel by having both others at zero in some angles.

    Open points

    • How to define what is the maximum possible voltage/current to be applied without burning out the motor ? The wire thickness is 0.15 mm, and expected usage in static permanent conditions.

View all 2 project logs

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates