In this project, we'll embark on an exciting journey into motor control using the powerful combination of Raspberry Pi and Python. Leveraging the Dual H-Bridge Motor Driver (H18R1X) from Hexabitz, we aim to create a seamless interface for DC motor control. Whether you're a robotics enthusiast or an automation aficionado, this project provides a perfect foundation for popular motor control applications.
Objective: To create a Python-based interface for controlling a DC motor using Raspberry Pi and the Dual H-Bridge Motor Driver (H18R1X).
𧩠About the H18R1XThe H18R1X is a dual H-bridge motor driver module based on the L298 and STM32G0 MCU. This module allows driving motors in two directions (forward and backward). With such a module, the motor can be made to rotate, and the polarity of the motorβs power supply can be reversed to change the direction of rotation. If necessary, the motor can also be braked.
HF1R0x is Hexabitz Raspberry Pi interface module. It interfaces seamlessly to Raspberry Pi 3B/4B single-board computers and enables you to connect and control your favorite Hexabitz modules from the Raspberry Pi operating system and build your own Raspberry Pi Hat. This is the worldβs first build-your-own-Pi-Hat system!
You can use C++ Hexabitz Interface library on Raspbian, Ubuntu or other compatible Linux distributions from within your C++ or Python applications.
𧩠Steps to Complete the Project:Setup and Wiring:
- Connect the H18R1 module to HF1R0 module.
- Make sure to connect your Hexabitz module at the wright spot or left spot then put the HF1R0 Jumper JP1 and JP2 at right position.
- Be sure to download the firmware on the module before soldering.
https://hexabitz.com/docs/how-to/update-module-firmware/
- Connect the DC motor to the output terminals of the Dual H-Bridge Motor Driver (H18R1X).
- Ensure the power supply is appropriately connected to the motor driver to power the motor.
Python Code Implementation:
Python pyserial:
This module encapsulates the access for the serial port. It provides backends for Python running on Windows, OSX, Linux, BSD (possibly any POSIX compliant system) and IronPython. The module named βserialβ automatically selects the appropriate backend.
Depending on the version of python, there are several commands to install the package pyserial.
sudo apt-get install python-serial python3-serial
Python code to read the serial port: This section of code primarily instantiates the serial class, setting it up with all the various bits of information that it needs to make the connection with.
port β This defines the serial port that the object should try and do read and writes over.
baudrate β This is the rate at which information is transferred over a communication channel.
parity β Sets whether we should be doing parity checking, this is for ensuring accurate data transmission between nodes during communication.
stopbits β This is the pattern of bits to expect which indicates the end of a character or the data transmission.
bytesize β This is the number of data bits.
timeout β This is the amount of time that serial commands should wait for before timing out.
import serial
ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate = 921600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
Python Tkinter
Tkinter is the standard GUI library for Python. Python when combined with Tkinter provides a fast and easy way to create GUI applications.
Tkinter provides a powerful object-oriented interface to the Tk GUI toolkit.
Creating a GUI application using Tkinter is an easy task.
All you need to do is perform the following steps :
- Import the Tkinter module.
- Create the GUI application main window.
- Add one or more of the above-mentioned widgets to the GUI application.
- Enter the main event loop to take action against each event triggered by the user.
You can start Python3 from the command line (with python3) then
import tkinter
If you get an error message then exit out of Python3 and call
sudo apt-get install python3-tk
to install it.
HexabitzMessaging Protocol
Messaging in the array is carried out via short unacknowledged packets in the following format (each field is a single byte):
|| H | Z | Length | Destination | Source | Options | Code | Par. 1 | Par. 2 | ------- | CRC8 ||
- βHβ=72 and βZβ=90 are message start delimiters. They mark the beginning of a valid Hexabitz message.
- The Length byte is message length not including H & Z delimiters, the length byte itself and the CRC byte.
- Maximum message length is 56, i.e., the maximum number of parameters per message is 47 or 48 bytes.
Source and destination are IDs of source and destination modules.
- If the destination is 255 = 0xFF, the message is a broadcast.
- If destination is 254 = 0xFE, the message is a multi-cast (going to a group).
- If destination is 0, the message is sent to an adjacent neighbor only.
- Source and destination are IDs of source and destination modules.If the destination is 255 = 0xFF, the message is a broadcast.If destination is 254 = 0xFE, the message is a multi-cast (going to a group).If destination is 0, the message is sent to an adjacent neighbor only.
- CODE is a 16-bit variable representing Message Codes. If message code is β€ 255, then only one byte is used. If message code is > 255, then two bytes are used and the Extended Code flag in the Options Byte is set.
Options: is a byte that contains some option bits and flags. It can be extended using the Extended Options Flag:
- 8th bit (MSB): Long messages flag. If set, then message parameters continue in the next message.
6-7th bits: Message response options:
- 00: Send back no response
- 01: Send responses only to Messages.
- 10: Send responses only to CLI Commands.
- 11: Send responses to everything.
- 6-7th bits: Message response options:00: Send back no response01: Send responses only to Messages.10: Send responses only to CLI Commands.11: Send responses to everything.
- 5th bit: reserved.
3rd-4th bits: Message Trace options:
- 00: Show no trace.
- 01: Show Message trace.
- 10: Show Message Response trace.
- 11: Show trace for both messages and their responses.
- 3rd-4th bits: Message Trace options:00: Show no trace.01: Show Message trace.10: Show Message Response trace.11: Show trace for both messages and their responses.
- 2nd bit: Extended Message Code flag. If set, then message codes are 16 bits.
- 1st bit (LSB): Extended Options flag. If set, then the next byte is an Options byte as well.
- Options: is a byte that contains some option bits and flags. It can be extended using the Extended Options Flag:8th bit (MSB): Long messages flag. If set, then message parameters continue in the next message.6-7th bits: Message response options:00: Send back no response01: Send responses only to Messages.10: Send responses only to CLI Commands.11: Send responses to everything.5th bit: reserved.3rd-4th bits: Message Trace options:00: Show no trace.01: Show Message trace.10: Show Message Response trace.11: Show trace for both messages and their responses.2nd bit: Extended Message Code flag. If set, then message codes are 16 bits.1st bit (LSB): Extended Options flag. If set, then the next byte is an Options byte as well.
- Long messages can be broken down into maximum of 20 messages, i.e., ~940-960 bytes of parameters. Any payload larger than 960 bytes will have to set up a DMA stream.
- The CRC byte is a CRC8 of the entire message starting from the delimiters (except the CRC byte itself).
H18R1x Messages:
#H18R1 Messages Codes
CODE_H18R1_Turn_ON = 1200
CODE_H18R1_Turn_OFF = 1201
Turn on the H-Bridge module in either forward or backward direction and specify the motor you want to drive, where:
H_BridgeDirection direction: forward or backward, direction: 1 //forward or 2 //backward
Motor motor: MotorA or MotorB, motor: 1 or 2
Code Explanation π₯οΈ π¨π§
In this project, we've developed a Python-based motor control interface using Tkinter on a Raspberry Pi. The interface is connected to a Hexabitz H-Bridge motor driver module to control a DC motor. The following is a breakdown of the code.
Imports and Setup
import tkinter as tk
import RPi.GPIO as GPIO
import time
import serial
import struct
import math
from ctypes import c_uint32
# Setup serial communication with motor driver
ser = serial.Serial(port='/dev/ttyS0', baudrate=921600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=1)
These imports are essential for setting up the serial communication, GPIO control, and creating the GUI.
CRC Calculation Function
This function calculates the CRC32 checksum for ensuring data integrity during communication
def calculate_crc32mpeg2(msg_buffer, size, reflected_input):
Constants
MAX_MESSAGE_SIZE = 255
MAX_PARAMS_PER_MESSAGE = 10
Raspberrypi_id = 1
# H18R1X Constants
CODE_H18R1_Turn_ON = 1200
CODE_H18R1_Turn_OFF = 1201
CODE_H18R1_Turn_PWM = 1202
Control Functions
def send_control_message_to_module(dst, code, fb, m)
def send_stop_message_to_module(dst, code, m)
These functions handle sending control and stop messages to the motor driver.
Motor Control Commands
def forward():
send_control_message_to_module(1, CODE_H18R1_Turn_ON, 1, 1)
def backward():
send_control_message_to_module(1, CODE_H18R1_Turn_ON, 2, 1)
def stop():
send_stop_message_to_module(1, CODE_H18R1_Turn_OFF, 1)
These messages control the motor's direction and stopping.
GUI Setup
root = tk.Tk()
root.title("Motor Control")
root.geometry("400x300")
root.configure(bg="#282c34")
header_label = tk.Label(root, text="Hexabitz Motor Control Interface", font=("Helvetica", 16, "bold"), bg="#282c34", fg="#61dafb")
header_label.pack(pady=20)
forward_button = tk.Button(root, text="Forward", command=forward, bg="#4CAF50", fg="white", font=("Helvetica", 12, "bold"), padx=20, pady=10, relief="groove")
forward_button.pack(pady=10)
backward_button = tk.Button(root, text="Backward", command=backward, bg="#2196F3", fg="white", font=("Helvetica", 12, "bold"), padx=20, pady=10, relief="groove")
backward_button.pack(pady=10)
stop_button = tk.Button(root, text="Stop", command=stop, bg="#f44336", fg="white", font=("Helvetica", 12, "bold"), padx=20, pady=10, relief="groove")
stop_button.pack(pady=10)
footer_label = tk.Label(root, text="Enjoy controlling your motor!", font=("Helvetica", 14, "italic"), bg="#282c34", fg="#aab0b6")
footer_label.pack(pady=20)
root.mainloop()
This section creates the GUI using Tkinter with buttons to control the motor ( forward, backward, and stop motor operations.
Testing and Calibration:
Test the motor control functions to ensure they work as expected.
𧩠Conclusion:By the end of this project, you will have a functional system for controlling a DC motor using a Raspberry Pi and Python, demonstrating the practical use of the Dual H-Bridge Motor Driver (H18R1X). This project not only highlights the simplicity of interfacing hardware with software but also opens up possibilities for more complex motor control applications in the future.
Comments