yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
MicroROS Self-balancing Robot Car📖
01.Introduction
  • 0.Unboxing and Reviewing
  • 1. Must read before use - learning route
  • 2. Introduction to LiDAR
  • 3. Balance car interface description
  • 4. Analysis of common problems
  • 5. Robot charging and battery precautions
02.Assembly tutorial
  • Robot assembly steps
03.Preparation
  • 0.Quick Start (Must Read)
  • 1.Write firmware
  • 2.How to install and use VM
  • 3.ESP32 communication board configuration parameters
  • 4.Connect to microROS agent
04.ROS-WiFi module configuration
  • 0.Serial port configuration WiFi instructions
  • 1.Use ROS-WiFi cam module(must read)
  • 2.Connect to ROS-WiFi cam module agent
  • 3.Camera image correction (optional)
05.Quick start control
  • 1.Keyboard remote control
  • 2.Handle remote control
06.ROS+OpenCV course
  • 1.OpenCV Getting started
  • 2.Geometric transformation
  • 3.Image processing and drawing text line segments
  • 4.Image beautification
07.Mediapipe course
  • 1. Hand detection
  • 2. Posture detection
  • 3. Overall inspection
  • 4. Face detection
  • 5. Face recognition
  • 6. Facial effects
  • 7. 3D object recognition
  • 8. Brush
  • 9. Finger control
  • 10. Gesture recognition
08.Robot basic course
  • 1.Robot information release
  • 2.Robot keyboard control
  • 3.Robot handle control
  • 4.Robot state estimation
  • 5.Line speed calibration
  • 6.Angular velocity calibration
  • 7.Robot URDF model
09.Lidar course
  • 1.Lidar avoid
  • 2.Lidar following
  • 3.Lidar guard
  • 5.Gmapping mapping
  • 6.Cartographer mapping
  • 7.Navigation2 navigation avoid
  • 8.Navigation2 fast relocation navigation
  • 9.ROS Robot APP mapping
  • 10.ROS Robot APP navigation
10.Robot visual interaction
  • 1.Color tracking
  • 2.Object recognition and tracking
  • 3.Face recognition tracking
  • 4.Autonomous driving line patrol
  • 5.QR code motion control
  • 6.Gesture control car movement
  • 7.Palm control car movement
  • 8.Gesture control car action group
  • 9.Palm recognition and tracking
  • 10.Human body posture recognition and tracking
11.Multi-machine course
  • 1.Multi-machine handle control
  • 2.Multi-machine keyboard control
  • 3.Multi-machine navigation
  • 4.Multi-machine rapid relocation navigation
12.STM32 balancing case
01.Environment construction and development
  • 13.Window Watchdog (WWDG)
  • 01.MDK-ARM installation
  • 02.STM32CubeIDE installation
  • 03.Common driver installation
  • 04.Download the program
  • 05.MDK-ARM project usage
  • 06.Program simulation
02.STM32 getting started course
  • 01.Project creation
  • 02.LED Control(GPIO)
  • 03.Buzzer control(GPIO)
  • 04.Button control(EXTI)
  • 05.Serial communication(USART)
  • 06.Voltage detection(ADC)
  • 07.Basic timer(TIM)
  • 08.Universal timer(TIM)
  • 09.Advanced Timer(TIM)
  • 10.I2C Communication(I2C)-OLED
  • 11.SPI communication(SPI)-2.4G handle
  • 12.Independent Watchdog (IWDG)
  • 14.DMA-USART
  • 15.DMA-I2C
03.STM32 expansion course
  • 01.Battery voltage detection (ADC)
  • 02.Ultrasonic module-measuring distance (TIM)
  • 03.Motor drive+encoder (TIM)
  • 04.OLED Data-Display(I2C)
  • 05.MPU6050-Data Read (I2C)
04.Robot car PID control course
  • 01.PID basic concept
  • 02.PID example analysis
  • 03.P, PI, PD controller theory
  • 04.Position PID
  • 05.Incremental PID
  • 06.Cascade PID
  • 07.Balance principle of car
  • 08.Car upright control (PD)
  • 09.Car speed ​​control (PI)
  • 10.Car steering control (PD)
  • 11.Got angle and angular velocity (DMP algorithm)
  • 12.Got angle and angular velocity (Kalman filter algorithm)
  • 13.Got angle and angular velocity(Complementary filter algorithm)
05.Robot car basic course
  • 01.Car parameter adjustment
  • 02.Ultrasonic obstacle avoidance
  • 03.Ultrasonic follow
  • 04.Bluetooth remote control
  • 05.Load balance
  • 06.Radar obstacle avoidance
  • 07.Radar guard
  • 08.Radar follow
  • 09.Radar patrol
  • 10.Radar wall following go in a straight line
  • 11.Radar tracking wall multiple walls
06.Robot car LQR control
  • Balance car LQR high-level control
07.Circuit design
  • 01.Overall circuit design
  • 02.STM32 minimum system
  • 03.Serial port circuit design
  • 04.Power circuit design
  • 05.MPU6050 Circuit Design
  • 06.Motor drive circuit design
08.Mathematical model
  • Balance car mathematical model
13.Linux basic course
  • 1.Introduction to Linux system
  • 2.Ubuntu file system
  • 3.Ubuntu common commands
  • 4.Ubuntu common editors
  • 5.Ubuntu software operation commands
  • 6.Virtual machine installation
  • 7.SSH remote control
  • 8.VNC remote control
  • 9.Transfer files remotely
  • 10.Driver library and communication
  • 11.Static IP and hotspot mode
  • 12.Bind device ID
  • 13.Capacity expansion and resource allocation
  • 14.Update system software sources
  • 15.Set root user password
  • 16.sudo free password
  • 17.Connect to WiFi network
  • 18.View system version
  • 19.Customized service management
  • 20.Back up system image
14.Docker course
  • 1. Overview and installation
  • 2. Common commands
  • 3. Docker images deeply understand and publish images
  • 4. Docker hardware interaction and data processing
  • 5. Enter the bot's docker container
15.ROS2 basic course
  • 1.Introduction to ROS2
  • 2.ROS2 install Humble
  • 3.ROS2 development environment
  • 4.ROS2 workspace
  • 5.ROS2 function package
  • 6.ROS2 node
  • 7.ROS2 topic communication
  • 8.ROS2 service communication
  • 9.ROS2 action communication
  • 10.ROS2 custom interface message
  • 11.ROS2 parameter service case
  • 12.ROS2 meta-function package
  • 13.ROS2 distributed communication
  • 14.ROS2 DDS
  • 15.ROS2 time related API
  • 16.ROS2 common command tools
  • 17.ROS2 rviz2 use
  • 18.ROS2 rqt toolbox
  • 19.ROS2 Launch startup file configuration
  • 20.ROS2 recording and playback tool
  • 21.ROS2 URDF model
  • 22.ROS2 Gazebo simulation platform
  • 23.ROS2 TF2 coordinate transformation
Download
  • RemoteCtrl_APP(Android)
  • Mapping_APP(iOS_Android)
  • Code
  • Hardware Information
  • software tools
  • 3D model file
  • Instruction manual
  • VM image file
  • ROS2_Basic_VM
Download ZIP

Welcome to MicroROS Self-balancing Robot Car repository

11.SPI communication(SPI)-2.4G handle

SPI communication (SPI)

SPI communication (SPI)Hardware connectionControl PrincipleSoftware configurationPin definitionSoftware codeControl functionExperimental phenomenon

The tutorial demonstrates how to use SPI to read the key values of a 2.4G wireless controller and print them through the serial port.

The tutorial only introduces the standard library project code

Hardware connection

image-20240825205618171

Since we have configured a special connection line, we only need to install it to the corresponding interface:

PeripheralsDevelopment Board
PS2: CSPB12
PS2: SCKPB13
PS2: MISOPB14
PS2: MOSIPB15

Control Principle

SPI (Serial Peripheral Interface) is a high-speed, full-duplex, synchronous serial communication interface that is commonly used to transmit data between microcontrollers, sensors, and external devices.

SPI PinFunction
MISOMaster data output line, sends data from the master to the slave
MOSIMaster data input line, transmits data from the slave to the master
SCLKClock signal line, used for timing control of synchronous data transmission
CSSlave select line, used to select a specific slave device to communicate with the master
  • SPI transmission mode

Clock polarity (CPOL): controls the idle and active states of the clock signal (0: idle state low level, 1: idle state high level)

Clock phase (CPHA): controls the sampling and transmission time of data (0: odd transition edge sampling, 1: even transition edge sampling)

Clock polarity (CPOL)Clock phase (CPHA) 
00SCL idle state low level; data is sampled on the rising edge and transmitted on the falling edge
01SCL idle state low level; data is sampled on the falling edge and transmitted on the rising edge
10SCL idle state high level; data is sampled on the falling edge and transmitted on the rising edge
11SCL idle state high level; data is sampled on the rising edge and transmitted on the falling edge

image-20240903163539136

  • 2.4G wireless handle

The 2.4G wireless handle is mainly composed of a handle and a receiver (the receiver adapter board is convenient for pin connection with the development board).

Handle

Send key information to the receiver.

Receiver

Receive the data sent by the handle and pass it to the development board; the development board can also send data through the handle to configure the handle's sending mode.

image-20240807212212404

  • Controller mode description

Single light mode: one controller indicator light is on

Dual light mode: two controller indicator lights are on

  • Controller Button Description

image-20240819100651601

Controller ButtonProgram Function DescriptionProgram Definition (Part)
Direction Key (①): △ForwardPSB_PAD_UP
Direction Key (①): ▽BackwardPSB_PAD_DOWN
Direction Key (①): ◁Turn LeftPSB_PAD_LEFT
Direction Key (①): ▷Turn RightPSB_PAD_RIGHT
Function Key (②): ▲ForwardPSB_TRIANGLE/PSB_GREEN
Function Key (②): ×BackwardPSB_CROSS/PSB_BLUE
Function key (②): ☐Turn leftPSB_SQUARE/PSB_PINK
Function key (②): ◯Turn rightPSB_CIRCLE/PSB_RED
Joystick: ③Control direction (valid in dual-light mode)PSB_L3/PSS_LX/PSS_LY
Joystick: ④Control direction (valid in dual-light mode)PSB_R3/PSS_RX/PSS_RY
Button (⑤): L1/L2AcceleratePSB_L1/PSB_L2
Button (⑥): R1/R2DeceleratePSB_R1/PSB_R2
Button (⑦): STARTTurn off power saving modePSB_START
Button (⑧): MODESwitch mode (indicator light display: single light and dual light mode) 
Key (⑨): SELECTUnusedPSB_SELECT
  • Receiver and adapter board pin description

Receiver pinDescription
DI/DATSignal flow, from handle to host, this signal is an 8-bit serial data, synchronously transmitted on the falling edge of the clock. The signal is read when the clock changes from high to low.
DI/DATSignal flow, from host to handle, this signal is relative to DI, the signal is an 8-bit serial data, synchronously transmitted on the falling edge of the clock.
NCEmpty port.
GNDReceiver working power supply, power supply range 3~5V.
VDDUsed to provide handle trigger signal. During communication, it is at low level.
CS/SELSignal flow, from host to handle, this signal is relative to DI, the signal is an 8-bit serial data, synchronously transmitted on the falling edge of the clock.
CS/SELClock signal, sent by the host, used to keep data synchronized.
NCEmpty port.
ACKAcknowledgement signal from the controller to the host. This signal goes low at the last cycle of each 8-bit data transmission and CS remains low. If the CS signal does not go low, the PS host will try another peripheral in about 60 microseconds. The ACK port is not used during programming. (Can be ignored)

image-20240807214832385

Software configuration

Pin definition

Main control chipPinMain function (after reset)Default multiplexing functionRedefine function
STM32F103RCT6PB12PB12SPI2_NSS/I2C2_SMBAI/USART3_CK/TIM1_BKIN 
STM32F103RCT6PB13PB13SPI2_SCK/USART3_CTS/ TIM1_CH1N 
STM32F103RCT6PB14PB14SPI2_MISO/USART3_RTS/TIM1_CH2N 
STM32F103RCT6PB15PB15SPI2_MOSI/TIM1_CH3N 

Software code

Since the default function of the pin is the ordinary IO pin function, we need to use the multiplexing function.

xxxxxxxxxx
Product supporting materials source code path: Attachment → Source code summary → 1.Base_Course → 11.SPI

Control function

The tutorial only briefly introduces the code, you can open the project source code to read it in detail.

PS2_Init

​x
void PS2_Init(void)
{
     GPIO_InitTypeDef GPIO_InitStructure; //Define GPIO_InitStructure structure
    //DI
    RCC_APB2PeriphClockCmd(PS_RCC_DI,ENABLE);
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU; //Pull-up, pull-down and floating input modes will cause abnormalities when the handle is not connected
    GPIO_InitStructure.GPIO_Pin=PS_PIN_DI;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ
    GPIO_Init(PS_PORT_DI,&GPIO_InitStructure);

    //DO
    RCC_APB2PeriphClockCmd(PS_RCC_DO,ENABLE); //Turn on GPIOB clock
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //Multiplexed push-pull output mode
    GPIO_InitStructure.GPIO_Pin=PS_PIN_DO; //DO port
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ
    GPIO_Init(PS_PORT_DO,&GPIO_InitStructure);

    //CS
    RCC_APB2PeriphClockCmd(PS_RCC_CS,ENABLE); //Turn on GPIOB clock
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //Multiplexed push-pull output mode
    GPIO_InitStructure.GPIO_Pin=PS_PIN_CS; //CS port
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ
    GPIO_Init(PS_PORT_CS,&GPIO_InitStructure);

    //SCK
    RCC_APB2PeriphClockCmd(PS_RCC_CLK,ENABLE); //Turn on GPIOB clock
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //Multiplexed push-pull output mode
    GPIO_InitStructure.GPIO_Pin=PS_PIN_CLK; //CLK port
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; //50MHZ
    GPIO_Init(PS_PORT_CLK,&GPIO_InitStructure);
}

PS2_Cmd

xxxxxxxxxx
void PS2_Cmd(u8 CMD)
{
    
}

PS2_RedLight

xxxxxxxxxx
u8 PS2_RedLight(void)
{
    volatile u16 ref=0x01;
    Data[1] = 0;
    for(ref=0x01;ref<0x0100;ref<<=1)
    {
        if(ref&CMD)
        {
            DO_H; //output a control bit
        }
        else DO_L;
        CLK_H; //clock high
        DELAY_TIME;
        CLK_L;
        DELAY_TIME;
        CLK_H;
        if(DI) //when high
        Data[1] = ref|Data[1];
    }
    delay_us(16);
}

PS2_ReadData

xxxxxxxxxx
void PS2_ReadData(void)
{
    volatile u8 byte=0;
    volatile u16 ref=0x01;
    CS_L;
    PS2_Cmd(Comd[0]);
    PS2_Cmd(Comd[1]);
    for(byte=2;byte<9;byte++)
    {
        for(ref=0x01;ref<0x100;ref<<=1)
        {
            CLK_H;
            DELAY_TIME;
            CLK_L;
            DELAY_TIME; 
            CLK_H;          
              if(DI)
              Data[byte] = ref|Data[byte];
        }
        delay_us(16);
    }
    CS_H;
}

PS2_DataKey

xxxxxxxxxx
u8 PS2_DataKey()
{
    u8 index;
    PS2_ClearData();
    PS2_ReadData();
    Handkey=(Data[4]<<8)|Data[3];
    for(index=0;index<16;index++)
    {       
        if((Handkey&(1<<(MASK[index]-1)))==0)
        return index+1;
    }
    return 0;
}

PS2_AnologData

xxxxxxxxxx
u8 PS2_AnologData(u8 button)
{
    return Data[button];
}

PS2_ClearData

xxxxxxxxxx
void PS2_ClearData()
{
    u8 a;
    for(a=0;a<9;a++)
        Data[a]=0x00;
}

PS2_Vibration

xxxxxxxxxx
void PS2_Vibration(u8 motor1, u8 motor2)
{
    CS_L;
    delay_us(16);
    PS2_Cmd(0x01);
    PS2_Cmd(0x42);
    PS2_Cmd(0X00);
    PS2_Cmd(motor1);
    PS2_Cmd(motor2);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    CS_H;
    delay_us(16);  
}

PS2_ShortPoll

xxxxxxxxxx
void PS2_ShortPoll(void)
{
    CS_L;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x42);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0x00);
    CS_H;
    delay_us(16);   
}

PS2_EnterConfing

xxxxxxxxxx
void PS2_EnterConfing(void)
{
    CS_L;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x43);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x01);
    PS2_Cmd(0x00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    CS_H;
    delay_us(16);
}

PS2_TurnOnAnalogMode

xxxxxxxxxx
void PS2_TurnOnAnalogMode(void)
{
    CS_L;
    PS2_Cmd(0x01);  
    PS2_Cmd(0x44);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x01);
    PS2_Cmd(0xEE);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    PS2_Cmd(0X00);
    CS_H;
    delay_us(16);
}

PS2_VibrationMode

xxxxxxxxxx
void PS2_VibrationMode(void)
{
    CS_L;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x4D);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0X01);
    CS_H;
    delay_us(16);   
}

PS2_ExitConfing

xxxxxxxxxx
void PS2_ExitConfing(void)
{
    CS_L;
    delay_us(16);
    PS2_Cmd(0x01);  
    PS2_Cmd(0x43);  
    PS2_Cmd(0X00);
    PS2_Cmd(0x00);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    PS2_Cmd(0x5A);
    CS_H;
    delay_us(16);
}

PS2_SetInit

xxxxxxxxxx
void PS2_SetInit(void)
{
    PS2_ShortPoll();
    PS2_ShortPoll();
    PS2_ShortPoll();
    PS2_EnterConfing(); //Enter configuration mode
    PS2_TurnOnAnalogMode(); //"Traffic light" configuration mode, and choose whether to save
    //PS2_VibrationMode(); //Turn on vibration mode
    PS2_ExitConfing(); //Complete and save configuration
}

Experimental phenomenon

The SPI.hex file generated by the project compilation is located in the OBJ folder of the SPI project. Find the SPI.hex file corresponding to the project and use the FlyMcu software to download the program to the development board.

After the program is successfully downloaded: the serial port prints the key value pressed by the wireless controller.

xxxxxxxxxx
When using the serial port debugging assistant, you need to pay attention to the serial port settings. If the settings are wrong, the phenomenon may be inconsistent.

image-20240827173648504

I2C Communication(I2C)-OLED
Independent Watchdog (IWDG)

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文