Bring GIMpolette to life

Hello, I am your very own GIMpolette. I may not look like an Arduino but I can be that and so much more. I only need you to build me up. I can sing, I can shine, I can measure, I can mime. I can do many other things which are limited only by that imagination of thine.

In the early days of GIM Robotics, the extensive knowledge and skill base was recognized within our squad and instead of constantly hunting for external talent, the company invested in the GIMsters, nurturing their skills and fostering an environment where innovation and creativity were encouraged. By providing continuous learning opportunities and promoting a culture of collaboration, the squad members grew both personally and professionally with the company.

GIMpolette is a USB connected microcontroller development board much like an Arduino, supporting a variety of sensors and outputs on the board. It can be programmed using either Arduino IDE, platformIO, STM32CubeIde or any tool which supports its STM32F0 processor. The example code and precompiled binaries are provided. To assemble a functional GIMpolette various surface mount components are needed – and the board should be good practice for assembling such devices!

The board can be built with the following features:

  • Arduino-style development board with 6 GPIO on the board edges, a 48 mHz 32-bit CPU with 32k flash and 6k RAM (STM32F042F6P)
  • 6x individually controllable RGB LEDs (WS2812)
  • 3-axis gyroscope and 3-axis accelerometer (MPU6050)
  • Temperature sensor (On the MPU6050, not super accurate 😉)
  • Piezo speaker
  • Native USB, supports serial CDC, HID (mouse, keyboard) etc.
  • Pushbutton input
  • Adorable physical shape mimicking a 2€ coin for unlocking shopping carts and such SWD debugging support


Only the CPU itself and some passive components are needed for a minimally functional Poletti, with the RGB LED’s, speaker and gyroscope/accelerometer (IMU) can be added at will! A list of the components and their places on the board for assembly are shown below:

Powered By EmbedPress

Powered By EmbedPress

Some example codes are shown below, and they can be uploaded through ArduinoIDE, or any of the other methods used for STM32 products. These have been created and tested with Arduino IDE with the STM32Duino addon to support the STM32 chip used in GIMPolette.


This makes GIMPoletti a USB mouse, controlled with the IMUs gyroscope
LED colors correspond to the movement axis

Interrupt driven IMU reading
Better scrolling
Gyro calibration triggered by button
Fancier LEDs

#include “Mouse.h” //Library for USB CDC mouse profile, must also select “USB Support: HID” from Tools
#include <Wire.h> //i2c bus library, used to talk to IMU (MPU6050)
#include <Adafruit_NeoPixel.h> //Library for addressable LEDs (WS2812b)

// ====== Pin definitions ======
const uint8_t pwmPin = PA0; //Drives the speaker, PWM frequency on this generates sound at that frequency. DO NOT LEAVE HIGH!
const uint8_t pwmChannel = 1; //Channel of PWM timer connected to above pin
const uint8_t buttonPin = PB8; //Connected to the button. Low when pressed, high otherwise
const uint8_t ledPin = PA1; //Connected to the beginning of addressable LED string
const uint8_t sdaPin = PF0; //Hardware sda pin for i2c bus connected to IMU
const uint8_t sclPin = PF1; //Hardware scl pin for i2c bus connected to IMU

// ====== IMU variables ======
const uint8_t mpu_address = 0x68; //i2c address of the MPU6050 IMU chip
int16_t gx, gy, gz; //Gyro data values

const int16_t gx_offset = 0; //Offset values saved on IMU chip, it adds these to it’s raw output
const int16_t gy_offset = 0; //Adjust these if mouse drifts!
const int16_t gz_offset = 30;

// ====== Misc variables ======
const uint8_t ledCount = 6; //Number of LEDs on the string. There are 6 on GIMPoletti.

// ====== Mouse behaviour variables ======
int responseDelay = 5; //Loop delay
bool lastClickState; //Last status of click, used to detect change
uint32_t clickStamp = 0; //Timestamp of last detected click
uint32_t clickInhibitTime = 180; //Inhibit mousee movement for this many ms after a click, to minimize mouse jerking on click
uint32_t scrollInhibitThreshold = 50; //Inhibit scrolling if mouse movement is greater than this to prevent accidental scrolling
const uint8_t outConst = 120; //Maximum output value sent for mouse movement

// ====== Classes ======
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800); //Addressable LED library
//HardwareTimer *MyTim = new HardwareTimer(TIM2); //Timer for generating speaker PWM

void setup() {
pinMode(buttonPin, INPUT);
pinMode(pwmPin, OUTPUT);

Wire.setSDA(sdaPin); //Set the i2c pins to the ones used in GIMPoletti circuit
Wire.begin(); //Start the i2c bus

strip.begin(); // Initialize NeoPixel strip object; // Turn off all pixels ASAP
strip.setBrightness(40); // Set brightness, maximum is 255

// MyTim->setMode(pwmChannel, TIMER_OUTPUT_COMPARE_PWM1, pwmPin);
// MyTim->setOverflow(4000, HERTZ_FORMAT);
// MyTim->setCaptureCompare(pwmChannel, 50, PERCENT_COMPARE_FORMAT); // 50%

delay(10); //Wait a bit before talking to IMU just in case

Wire.beginTransmission(mpu_address); //Begin i2c transaction to device at this address
Wire.write(0x6B); //Set which register to write to, this is power management to turn on IMU
Wire.write(0x00); //Write 0x00 there to turn MPU6050 on
Wire.endTransmission(); //End transaction

//Unpack gyro biases into an array of uint_8 for sending over i2c
uint8_t toGyro[] = {gx_offset >> 8, gx_offset, gy_offset >> 8, gy_offset, gz_offset >> 8, gz_offset};

delay(10); //Wait a bit before talking to IMU just in case
Wire.beginTransmission(mpu_address); //Gyro offset registers, starting from X
Wire.write(0x13); //Set which register to write to, this is start of gyro bias bytes
Wire.write(&toGyro[0],6); //Write all values (each of the 3 has a 16 bit width consisting of 8 bit high and low part, so 6 in total)
Wire.endTransmission(); //End transaction


void loop() {

bool clickState = digitalRead(buttonPin);
if (clickState) {
//MyTim->setOverflow(3000, HERTZ_FORMAT);
else {

if (clickState != lastClickState) {
clickStamp = millis();
lastClickState = clickState;


// calculate the movement distance based on the button states:
int xDistance = -gz / 256;
int yDistance = gy / 256;
int wheel = -gx;

//Do not scroll if vigorously moving mouse
if (abs(xDistance) > scrollInhibitThreshold || abs(yDistance) > scrollInhibitThreshold) {
wheel = 0;

if (millis() – clickStamp < clickInhibitTime) {
xDistance = 0;
yDistance = 0;

if (wheel > 0) {
wheel = max(0, wheel – 16000);
else {
wheel = min(0, wheel + 16000);
wheel /= 8192;

xDistance = constrain(xDistance, -outConst, outConst);
yDistance = constrain(yDistance, -outConst, outConst);
wheel = constrain(wheel, -outConst, outConst);

// if X or Y is non-zero, move:
if ((xDistance != 0) || (yDistance != 0)) {
Mouse.move(xDistance, yDistance, wheel);

// if the mouse button is pressed:
if (clickState == HIGH) {
// if the mouse is not pressed, press it:
if (!Mouse.isPressed(MOUSE_LEFT)) {;
// else the mouse button is not pressed:
else {
// if the mouse is pressed, release it:
if (Mouse.isPressed(MOUSE_LEFT)) {

strip.fill(strip.Color(abs(xDistance) * 2, abs(yDistance) * 2, abs(gx) / 150), 0, 6);;
// a delay so the mouse doesn’t move too fast:

void ReadGyro() {
Wire.requestFrom(0x68, 6);
gx = << 8 |;
gy = << 8 |;
gz = << 8 |;

Get the binary(bin) version from here.


  • STM32Duino (Found in Arduino IDE library manager)
  • Adafruit NeoPixel library (Found in Arduino IDE library manager)

Options to compile (from the Tools menu):

  • Select board as “Generic STM32F0 series”
  • Optimise: “Smallest (-Os default)”
  • Upload method: “STM32CubeProgrammer (DFU)”
  • Board part number as “Generic F042F6Px”
  • USB Support “HID (Keyboard and mouse)”
  • U(S)ART Support: “Disabled (No serial)”

Getting ready to upload the code:

GIMPoletti is immediately ready to receive code after building it, no configuration necessary. By holding the button down while plugging the USB cable in, GIMPoletti will go into the firmware upgrade mode and be recognized by the computer with a STM32 DFU (device firmware upgrade) in the device name. This can be seen in Windows device manager under USB devices, or with the lsusb command in Linux

After this is done, the code can be uploaded using STM32CubeProgrammer which needs to be installed either way. It can work directly or through Arduino IDE:

Uploading the code (.bin file)

  • Make sure GIMPoletti is detected in DFU mode
  • Open STM32CubeProgrammer
  • Select “USB” next to the “Connect” button, then press it
  • Select the “erasing and programming” tab from the left bar
  • Browse to the .bin file in the file path field
  • Check “Verify programming” and “Run after programming”
  • Hit “Start programming”!

Uploading the code (Arduino IDE)

  • Make sure GIMPoletti is detected in DFU mode
  • Make sure the code compiles successfully in Arduino IDE
  • Make sure the upload method is “STM32CubeProgrammer (DFU)”
  • Hit “upload” in Arduino IDE. If it fails, reason is likely that STM32CubeProgrammer is not installed where Arduino expects it to be, the error message will tell if it was not found

More posts


A week has passed since the LogiMAT 2024 ended. We have been busy processing the leads we got from the event. We are a bit overwhelmed by the sheer number and quality of those leads.

Read More


INFRASTRUCTURE FREE LOCALISATION IN DYNAMIC PORT AREAS Optimized navigation needs precise localization. Localization can be based on various sensor modalities. Each of them has its pros and cons. Modern ports are filled with infrastructure to

Read More



Read More


USING SLAM WISELY – BOTH THE TERM AND THE IMPLEMENTATION Mobile robots should know where they are. Majority of the autonomous operation relies on constantly estimating the location and the orientation of the robot, that

Read More

Eurostars everLOC project funded

GIM Robotics and xtonomy receive funding for Eurostars project everLOC with a total budget of over 1.4 M€ GIM Robotics and xtonomy received the prestigious Eurostars grant support to develop a solution for GNSS-free multimodal

Read More