Aula Jazmati
Published © MIT

Power Up: DC Motor Control with Raspberry Pi & H18R1X

Take control of your DC motor projects with ease using Raspberry Pi, Python, and the Hexabitz Dual H-Bridge Motor Driver (H18R1X). πŸš€πŸ”§

IntermediateWork in progress2 hours73

Things used in this project

Story

Read more

Schematics

H18R1x_Factsheet

Code

Hexabitz Motor Control Interface Code

Python
Hexabitz Motor Control Interface Final Code ^_^
#By Aula Jazmati
import tkinter as tk
import RPi.GPIO as GPIO
import time
import serial
import struct
import serial
import math
from ctypes import c_uint32
ser = serial.Serial(
    port='/dev/ttyS0',
    baudrate=921600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout=1
)

def calculate_crc32mpeg2(msg_buffer, size, reflected_input):
    crc32_initial = 0xFFFFFFFF
    crc32_polynomial = 0x04C11DB7
    crc32 = crc32_initial
    crc32_bytes_count = size
    
    while(size % 4 != 0):
        size += 1
        msg_buffer.append(0x0)
        
    # check whether the reflected data is enabled
    if 1 == reflected_input:
        # calculate the words count in the provided message
        words_count = math.ceil(size / 4)
        # if words_count < 2:
        #    words_count = 2

        # initialize a temporary list array
        temp_array = [0] * words_count * 4

        # reverse the bytes order of each word of the input message
        words_shift = 0
        for _ in range(words_count):
            bytes_shift = 4
            if bytes_shift > (size - words_shift):
                bytes_shift = size - words_shift

            # rotate inside the current word
            for bytes_counter in range(bytes_shift):
                temp_array[words_shift + bytes_counter] = msg_buffer[words_shift + bytes_shift - 1]
                bytes_shift -= 1
            # increase the word shift by 4
            words_shift += 4
        crc32_bytes_count = words_shift

    for i in range(crc32_bytes_count):
        # XOR next byte to upper bits of CRC
        if 1 == reflected_input:
            crc32 ^= (temp_array[i] << 24)
        else:
            crc32 ^= (msg_buffer[i] << 24)

        for _ in range(8):              # Do it eight times (number of bits in one byte).
            # the next variables are converted to c_uint32 so as not to exceed the value of 32-bit (0xFFFFFFFF).
            msb = c_uint32(crc32 >> 31)         
            crc32_c = c_uint32(crc32 << 1)
            # the previous variables are converted back to python type int to be consistent.
            crc32 = int(crc32_c.value)
            crc32 ^= ((0 - msb.value) & crc32_polynomial)
    return crc32
MAX_MESSAGE_SIZE = 255
MAX_PARAMS_PER_MESSAGE = 10
BOS_RESPONSE = 0  # Replace with actual value
BOS_TRACE = 0  # Replace with actual value
BOS_BROADCAST = 0xFF  # Replace with actual value
Raspberrypi_id = 1  # Replace with actual Raspberry Pi ID
#H18R1 Messages Codes
CODE_H18R1_Turn_ON = 1200
CODE_H18R1_Turn_OFF = 1201
# Functions to control the motor
def send_control_message_to_module(dst, code, fb,m):
    message = [0] * 13
    extend_options = False
    extend_code = False
    # Try to open serial port
    # HZ Delimiter
    message[0] = ord('H')
    message[1] = ord('Z')

    # Header
    message[3] = dst
    message[4] = Raspberrypi_id
    message[5]= 0x2
    ptmsb = (code>> 8) & 0xff
    ptlsb = code & 0xff 
    message[6] = (ptlsb)
    message[7] = (ptmsb) 
    #message[6] = 0xb0   
    #message[7] = 0x4
    message[8] = fb
    message[9] = m
    length = 10        
    message[2]= 7    
    s = len(message[:length])
    CRC32 = calculate_crc32mpeg2(message[:length], s, 1)
    CRC8 = CRC32 & 0xFF
    crc = format(CRC8 , 'X')
    message[10] = CRC8 
# Transmit the message from this port
    ser.write(message)
    ser.flushOutput()


def send_stop_message_to_module(dst, code, m):
    message = [0] * 12
    extend_options = False
    extend_code = False
    # Try to open serial port
    # HZ Delimiter
    message[0] = ord('H')
    message[1] = ord('Z')

    # Header
    message[3] = dst
    message[4] = Raspberrypi_id
    message[5]= 0x2
    ptmsb = (code>> 8) & 0xff
    ptlsb = code & 0xff 
    message[6] = (ptlsb)
    message[7] = (ptmsb) 
    #message[6] = 0xb1   
    #message[7] = 0x4
    message[8] = m
    length = 9 
    message[2]= 6    
    s = len(message[:length])
    CRC32 = calculate_crc32mpeg2(message[:length], s, 1)
    CRC8 = CRC32 & 0xFF
    crc = format(CRC8 , 'X')
    message[9] = CRC8
# Transmit the message from this port
    ser.write(message)
    ser.flushOutput()
def forward():
    print('F')
    send_control_message_to_module(1, CODE_H18R1_Turn_ON, 1,1)

def backward():
    print('B')
    send_control_message_to_module(1, CODE_H18R1_Turn_ON, 2,1)

def stop():
    print('S')
    send_stop_message_to_module(1, CODE_H18R1_Turn_OFF, 1)

# Create the interface using Tkinter
root = tk.Tk()
root.title("Motor Control")
root.geometry("400x300")
root.configure(bg="#282c34")

# Header Label
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
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
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
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
footer_label = tk.Label(root, text="Enjoy controlling your motor!", font=("Helvetica", 14, "italic"), bg="#282c34", fg="#aab0b6")
footer_label.pack(pady=20)

# Start the interface
root.mainloop()

Hexabitz Motor Control Interface GUI TEST

Python
GUI TEST
import tkinter as tk
# Functions to control the motor
def forward():
    print('F')

def backward():
    print('B')

def stop():
    print('S')

# Create the interface using Tkinter
root = tk.Tk()
root.title("Motor Control")
root.geometry("400x300")
root.configure(bg="#282c34")

# Header Label
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
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
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
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
footer_label = tk.Label(root, text="Enjoy controlling your motor!", font=("Helvetica", 14, "italic"), bg="#282c34", fg="#aab0b6")
footer_label.pack(pady=20)

# Start the interface
root.mainloop()

H18R1x_Firmware

Credits

Aula Jazmati

Aula Jazmati

52 projects β€’ 215 followers
πŸ’‘πŸ•ŠοΈ

Comments