Wednesday, February 3, 2021

Raspberry Pi/Python remote control LED on Raspberry Pi Pico/MicroPython with HC-08 + ILI9341 SPI Display via Bluetooth

Raspberry Pi Pico/MicroPython exercise to work with HC-08 BLE 4.0 module, to communication with Raspberry Pi/Python. The ILI9341 SPI screen is used to display related information only. HC-08 connect to Pico via UART(0), as a BLE server. Once connected, Pico monitor the incoming data, if matched pattern of "#LEDON\r\n"/"#LEDOFF\r\n" received, it turn ON/OFF its onboard LED accordingly.

In the Raspberry Pi/Python, using bluepy library, act as client connect to Pico/HC-08 BLE server, setup a simple tkinter GUI, send "#LEDON\r\n"/"#LEDOFF\r\n" command if user click on the toggle button.

It's a group result of my previouse exercises:
Python on Raspberry Pi to read ESP32 BLE_server, using bluepy
Raspberry Pi Pico/MicroPython + 320x240 ILI9341 SPI Display, using jeffmer/micropython-ili9341 library
Raspberry Pi Pico/MicroPython + HC-08 BLE 4.0 UART Module

Connection between Raspberry Pi Pico and HC-08/ILI9341:

MicroPython/Python Code:

MicrcoPython code run on Raspberry Pi Pico, mpyPico_ili9341_HC08.py:

"""
Exercise on Raspberry Pi Pico/MicroPython
with 320x240 ILI9341 SPI Display
+ HC-08 Bluetooth UART Module(ver:HC-08 V3.1,2017-07-07)
"""
from ili934xnew import ILI9341, color565
from machine import Pin, SPI
from micropython import const
import os
import glcdfont
import tt14
import tt24
import tt32
import time

#2 sec timeout is arbitrarily chosen
def sendCMD_waitResp(cmd, timeout=2000):
    print("CMD: " + cmd)
    uart.write(cmd)
    waitResp(timeout)
    print()
    
def waitResp(timeout=2000):
    prvMills = time.ticks_ms()
    resp = b""
    while (time.ticks_ms()-prvMills)<timeout:
        if uart.any():
            resp = b"".join([resp, uart.read(1)])
    print(resp)
    display.print(resp.decode('utf_8'))

def sendCMD_waitRespLine(cmd, timeout=2000):
    print("CMD: " + cmd)
    uart.write(cmd)
    waitRespLine(timeout)
    print()
    
def waitRespLine(timeout=2000):
    prvMills = time.ticks_ms()
    line = b""
    while (time.ticks_ms()-prvMills)<timeout:
        if uart.any():
            line = line+uart.readline()
    print(line)
    display.print(line.decode('utf_8'))

SCR_WIDTH = const(320)
SCR_HEIGHT = const(240)
SCR_ROT = const(2)
CENTER_Y = int(SCR_WIDTH/2)
CENTER_X = int(SCR_HEIGHT/2)

print(os.uname())
TFT_CLK_PIN = const(6)
TFT_MOSI_PIN = const(7)
TFT_MISO_PIN = const(4)

TFT_CS_PIN = const(13)
TFT_RST_PIN = const(14)
TFT_DC_PIN = const(15)

fonts = [glcdfont,tt14,tt24,tt32]
text = 'RPi Pico+ili9341+HC-08'

print(text)

#print uart info
#using UART(0)
#UART_TX = GP0
#UART_RX = GP1
uart = machine.UART(0, baudrate=9600,
                    bits=8, parity=None, stop=1)
print(uart)

led_onboard = machine.Pin(25, machine.Pin.OUT)
led_onboard.value(0)

spi = SPI(
    0,
    baudrate=40000000,
    miso=Pin(TFT_MISO_PIN),
    mosi=Pin(TFT_MOSI_PIN),
    sck=Pin(TFT_CLK_PIN))
print(spi)

display = ILI9341(
    spi,
    cs=Pin(TFT_CS_PIN),
    dc=Pin(TFT_DC_PIN),
    rst=Pin(TFT_RST_PIN),
    w=SCR_WIDTH,
    h=SCR_HEIGHT,
    r=SCR_ROT)

display.erase()
display.set_pos(0,0)

#indicate program started visually
display.set_font(tt24)
display.print(text)

time.sleep(1)
"""
for i in range(20):
    display.scroll(1)
    time.sleep(0.01)
"""
led_onboard.value(1)
time.sleep(0.5)
led_onboard.value(0)
"""
for i in range(20):
    display.scroll(-1)
    time.sleep(0.01)
"""
#-----------------------------------
#clear bufer in UART
display.set_font(tt14)
waitResp()
sendCMD_waitResp("AT")
sendCMD_waitRespLine("AT+RX")

display.set_font(tt24)
while True:
    char = uart.read(1)
    print(char)
    
    if char == b'#':
        print("match")
        bleCmd = uart.readline()
        if bleCmd == b'LEDON\r\n':
            led_onboard.value(1)
            display.fill_rectangle(0, 280, 200, 20, color565(0, 0, 0))
            display.set_pos(0, 280)
            display.print("- LED ON -")
            print("- LED ON -")
        if bleCmd == b'LEDOFF\r\n':
            led_onboard.value(0)
            display.fill_rectangle(0, 280, 200, 20, color565(0, 0, 0))
            display.set_pos(0, 280)
            display.print("- LED OFF -")
            print("- LED OFF -")
            
        else:
            print(bleCmd)
            #display.print(char.decode('utf_8'))

print("- bye-")

Python code run on Raspberry Pi 4, pyBLE_Pico_HC08.py:

from bluepy import btle
import time
import tkinter as tk

HC08_Char = None

def toggle():
    if toggle_btn.config('relief')[-1] == 'sunken':
        toggle_btn.config(relief="raised")
        HC08_Char.write(b'#LEDOFF\r\n')
        toggle_btn['text'] = 'Turn LED ON'
    else:
        toggle_btn.config(relief="sunken")
        HC08_Char.write(b'#LEDON\r\n')
        toggle_btn['text'] = 'Turn LED OFF'

MAC = "F8:33:31:E2:A0:42"
SERVICE_UUID = "FFE0"
CHARACTERISTIC_UUID = "FFE1"

print("Connect to:" + MAC)
dev = btle.Peripheral(MAC)

print("\n--- dev ----------------------------")
print(type(dev))
print(dev)

print("\n--- dev.services -------------------")
for svc in dev.services:
    print(str(svc))

print("\n------------------------------------")
print("Get Serice By UUID: " + SERVICE_UUID)
service_uuid = btle.UUID(SERVICE_UUID)
service = dev.getServiceByUUID(service_uuid)

print(service)
print("\n--- service.getCharacteristics() ---")
print(type(service.getCharacteristics()))
print(service.getCharacteristics())

#----------------------------------------------
characteristics = dev.getCharacteristics()
print("\n--- dev.getCharacteristics() -------")
print(type(characteristics))
print(characteristics)

for char in characteristics:
    print("----------")
    print(type(char))
    print(char)
    print(char.uuid)
    if(char.uuid == CHARACTERISTIC_UUID ):
        print("=== !CHARACTERISTIC_UUID matched! ==")
        HC08_Char = char
        print(char)
        print(dir(char))
        print(char.getDescriptors)
        print(char.propNames)
        print(char.properties)
        print(type(char.read()))
        print(char.read())


if HC08_Char != None:
    for i in range(3):
        HC08_Char.write(b'#LEDON\r\n')
        time.sleep(0.5)
        HC08_Char.write(b'#LEDOFF\r\n')
        time.sleep(0.5)


    root = tk.Tk()
    label = tk.Label( root, text="Toggle button to Turn ON/OFF the Pico LED via HC-08/BLE")
    label.pack(pady=10)
    toggle_btn = tk.Button(text="Turn LED ON", width=12, relief="raised", command=toggle)

    toggle_btn.pack(pady=10)
    root.geometry("500x200")

    #Place tkinter window center
    root.eval('tk::PlaceWindow %s center' % root.winfo_pathname(root.winfo_id()))
    root.title("helloraspberrypi.blogspot.com")
    root.mainloop()
else:
    print("Target HC-08 Not found!!!")

dev.disconnect()
print("--- bye ---")

Next:
ESP32 BLE Client remote control Raspberry Pi Pico/HC-08 via Bluetooth, almost same function to this exercise have ESP32 BLE client to replace Raspberry Pi/Python. 

~ More exercise for Raspberry Pi Pico


No comments: