CircuitPython ESP-NOW: Remote control on-board RGB LED via wireless, between ESP32-S3.

With previous CircuitPython  exercises of CircuitPython/ESP-NOW and Touch buttons on ILI9341 SPI LCD with FT6336 Cap. Touch, this exercise implement remote control on-board RGB LED wirelessly, between ESP32-S3-DevKitC-1 (sender) and Waveshare ESP32-S3-Zero (receiver).


cpyS3_ili9341_FT6336_grouped_color_TouchButtons_espnow_sender.py
"""
ESP32-S3/CircuitPython 9.0.5 exercise,
act as ESP-NOW sender,
send msg to receiver to control onboard RGB,
with ILI9341 SPI LCD + FT6336 cap. touch.

---------------------------

Display Module:
3.2 inch IPS SPI Module ILI9341 with cap. touch FT6336U

Test on:
dev. board:     Espressif ESP32-S3-DevKitC-1
CircuitPython:  9.0.5

Libraries needed:
- adafruit_ili9341.mpy
- adafruit_focaltouch.mpy
- adafruit_display_text folder
- adafruit_button folder
- adafruit_cursorcontrol folder

- adafruit_display_shapes folder
  (It's needed by adafruit_button, so you have to load in /lib folder.)
"""
import os, sys
import board
import busio
import terminalio
import displayio
import fourwire
from adafruit_display_text import label
import adafruit_ili9341
import bitmaptools

from digitalio import DigitalInOut, Direction
import adafruit_focaltouch
import adafruit_cursorcontrol.cursorcontrol

from adafruit_button import Button

import time

import wifi
import espnow

ILI9341_INVOFF = 0x20   #Display Inversion OFF
ILI9341_INVON  = 0x21   #Display Inversion ON

# Release any resources currently in use for the displays
displayio.release_displays()

#===init display ======================
#Connection to ILI9341/SD
DISP_CS  = board.IO17
DISP_RES = board.IO16
DISP_DC  = board.IO15
SPI_MOSI = board.IO7
SPI_SCL  = board.IO6
DISP_BL  = board.IO5
SPI_MISO = board.IO4
SD_CS    = board.IO43

#Connection to FT6336U
TOUCH_SCL = board.IO42
TOUCH_SDA = board.IO1
TOUCH_INT = board.IO44
TOUCH_RST = board.IO2

touch_irq = DigitalInOut(TOUCH_INT)
touch_irq.direction = Direction.INPUT

touch_res = DigitalInOut(TOUCH_RST)
touch_res.direction = Direction.OUTPUT
touch_res.value = True
time.sleep(0.1)
touch_res.value = False
time.sleep(0.1)
touch_res.value = True
time.sleep(0.5)

spi = busio.SPI(clock=SPI_SCL,
                MOSI=SPI_MOSI,
                MISO=SPI_MISO)

#On CircuitPython 9  FourWire moved from displayio to fourwire
display_bus = fourwire.FourWire(spi, command=DISP_DC, chip_select=DISP_CS, reset=DISP_RES)

touch_i2c = busio.I2C(TOUCH_SCL, TOUCH_SDA)

#ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False)
#In my test with irq_pin=touch_irq,
#reading ft.touched (in Main Loop) will not return if not touched;
#such that the Main Loop blocked, and the text not scrolled.
ft = adafruit_focaltouch.Adafruit_FocalTouch(touch_i2c, debug=False, irq_pin=touch_irq)

#--- Setup display ---
# for 3.2" 320x240 SPI ILI9341 TFT
disp_width = 320
disp_height = 240
display = adafruit_ili9341.ILI9341(display_bus,
                                   width=disp_width,
                                   height=disp_height,
                                   backlight_pin=DISP_BL,
                                   )

display_bus.send(int(ILI9341_INVON), "") #invert color

sysinfo = sys.implementation[0] + " " + os.uname()[3] + "\nrun on " + os.uname()[4]
drv_info = adafruit_ili9341.__name__ + " " + adafruit_ili9341.__version__ +"\n" \
           + adafruit_focaltouch.__name__ + " " + adafruit_focaltouch.__version__
print("=============================================")
print("coXXect.blogspot.com")
print("---------------------------------------------")
print(sys.implementation[0], os.uname()[3],
      "\nrun on", os.uname()[4])
print("=============================================")
print(drv_info)
time.sleep(1)
# Make the display context
bgGroup = displayio.Group()

display.root_group = bgGroup

bg_bitmap = displayio.Bitmap(display.width, display.height, 1)
bg_palette = displayio.Palette(1)
bg_palette[0] = 0x000000 # Black
bg_sprite = displayio.TileGrid(bg_bitmap, pixel_shader=bg_palette, x=0, y=0)
bgGroup.append(bg_sprite)

# Draw label
text_group = displayio.Group(scale=2, x=10, y=120)
text = "coXXect.blogspot.com"
text_area = label.Label(terminalio.FONT, text=text, color=0xFFFFFF)
text_group.append(text_area)  # Subgroup for text scaling
bgGroup.append(text_group)

info_group = displayio.Group(scale=1, x=10, y=180)
info_label = label.Label(terminalio.FONT,
                         text=sysinfo + "\n" + drv_info,
                         color=0xFFFFFF)
info_group.append(info_label)  # Subgroup for text scaling
bgGroup.append(info_group)

time.sleep(1)

bgGroup.remove(text_group)
bgGroup.remove(info_group)

# Create color buttons panel ---
PANEL_WIDTH = 300
PANEL_HEIGHT = 200
PANEL_OFFSET_X = int((display.width - PANEL_WIDTH)/2)
PANEL_OFFSET_Y = 10

panel_bitmap = displayio.Bitmap(PANEL_WIDTH, PANEL_HEIGHT, 1)
panel_palette = displayio.Palette(1)
panel_palette[0] = 0x808080
panel_sprite = displayio.TileGrid(panel_bitmap, pixel_shader=panel_palette, x=PANEL_OFFSET_X, y=PANEL_OFFSET_Y)
bgGroup.append(panel_sprite)

# max len = num_of_roW * num_of_col
color_set= [ 0x000000, 0xFF0000, 0x00FF00, 0x0000FF, 
             0x808080, 0x800000, 0x008000, 0x000080,
             0xA0A0A0, 0x008080, 0x800080, 0x808000,
             0xFFFFFF, 0x00FFFF, 0xFF00FF, 0xFFFF00,
             ]

num_of_row = 4
num_of_col = 4
row_width = int(PANEL_WIDTH/num_of_row)
col_height = int(PANEL_HEIGHT/num_of_col)
btn_gap_x = 5
btn_gap_y = 3
btn_width = row_width - (2 * btn_gap_x)
btn_height = col_height - (2 * btn_gap_y)

col_btn = []

r = 0
c = 0

for i in range(len(color_set)):
    btn = Button(x= r * row_width + btn_gap_x + PANEL_OFFSET_X,
                 y= c * col_height + btn_gap_y + PANEL_OFFSET_Y,
                 width=btn_width,
                 height=btn_height,
                 fill_color=color_set[i],
                 outline_color=0x000000,
                 )
    col_btn.append(btn)
    bgGroup.append(col_btn[i])
    r = r + 1
    if r == num_of_row:
        r = 0
        c = c + 1

#--- End of Create color buttons panel ---

# Prepare cursor, just to display the touch position for info only.
# initialize the mouse cursor object
# place over all others
mouse_cursor = adafruit_cursorcontrol.cursorcontrol.Cursor(
    display, display_group=bgGroup)
mouse_cursor.x = int(display.width/2)
mouse_cursor.y = int(display.height/2)

running_symbols = ['-', '\\', '|', '/']
running_symbol_idx = 0

# display my MAC address
my_mac = "  "
for m in wifi.radio.mac_address:
    my_mac = my_mac + f"0x{m:02x}"[2:].upper() + "."
my_mac = my_mac[:-1]  # remove last '.'
print("my mac address:", my_mac)

# Prepare ESP-NOW
e = espnow.ESPNow()
peer = espnow.Peer(mac=b'<receiver MAC>') # MAC of receiver
e.peers.append(peer)

# Main Loop
while True:
    # if the screen is being touched print the touches
    if ft.touched:
        touches = ft.touches
        
        #sometimes ft.touches is [], empty!
        #so I check len to prevent IndexError: index out of range
        if len(touches)>0:
            #print(touches)
            x = touches[0]['x']
            y = touches[0]['y']

            #with rotation=0, have to adjust touch x/y to project on screen.
            mouse_cursor.x = y
            mouse_cursor.y = display.height-x

            touch = [mouse_cursor.x, mouse_cursor.y]
            button_pressed = False
            for i, b in enumerate(col_btn):
                if b.contains(touch):
                    color_sellected = b.fill_color
                    bg_palette[0] = color_sellected
                    print("["+str(i)+"]:",  f'{b.fill_color:0>6X}')
                    button_pressed = True
                    
                    color_to_send = str(color_sellected)
                    print(type(color_to_send), color_to_send)
                    e.send(color_to_send)
                    e.send(b'end')
            
            if not button_pressed:
                print("pressed outside buttons")

        else:
            print('no touch')
            
    # print a running symbol on REPL Shell without new-line,
    # to check if it's in:
    # running : no irq_pin parameter passed in creating Adafruit_FocalTouch
    # blocked : with irq_pin=touch_irq in creating Adafruit_FocalTouch
    running_sym = running_symbols[running_symbol_idx]
    print(running_sym, end="\r")
    running_symbol_idx = running_symbol_idx + 1
    if running_symbol_idx == len(running_symbols):
        running_symbol_idx = 0

    time.sleep(0.05)

print("~ bye ~")


cpy_S3Zero-Zero_RGB__espnow_receiver.py
"""
ESP32-S3-Zero/Circuitpython 9.0.5 exercise,
act as ESP-NOW receiver,
to control on-board RGB (NeoPixel) base on received msg.
"""
import os, sys
import time
import neopixel
import board

import wifi
import espnow

def cycleNeopixel(wait):
    for r in range(255):
        pixel[0] = (r, 0, 0)
        time.sleep(wait)
    for r in range(255, 0, -1):
        pixel[0] = (r, 0, 0)
        time.sleep(wait)
        
    for g in range(255):
        pixel[0] = (0, g, 0)
        time.sleep(wait)
    for g in range(255, 0, -1):
        pixel[0] = (0, g, 0)
        time.sleep(wait)
        
    for b in range(255):
        pixel[0] = (0, 0, b)
        time.sleep(wait)
    for b in range(255, 0, -1):
        pixel[0] = (0, 0, b)
        time.sleep(wait)
        
print("=================================================")
info = sys.implementation[0] + ' ' + os.uname()[3] + '\n' + \
       'run on ' + os.uname()[4]
print(info)
print("- Control onboard RGB (NeoPixel) -")
print("=================================================")
print("board.NEOPIXEL:", board.NEOPIXEL)
print()

# Create the NeoPixel object
pixel = neopixel.NeoPixel(board.NEOPIXEL,
                          1,
                          pixel_order=neopixel.RGB)
pixel[0] = (0, 0, 0)
time.sleep(0.5)

#to check if NeoPixel work correct
cycleNeopixel(0.005)

pixel[0] = (0, 0, 0)

mac = ""
for m in wifi.radio.mac_address:
    mac = mac + "\\x" + f'{m:0>2x}'
print(mac)

e = espnow.ESPNow()


while True:
    packets = []
    while True:
        if e:
            packet = e.read()
            packets.append(packet)
            if packet.msg == b'end':
                break

    print("packets:", f"length={len(packets)}")
    for packet in packets:
        if packet.msg != b'end':
            print("received msg:", type(packet.msg), packet.msg)
            msg_to_int = int(packet.msg)
            print("msg_to_int:", type(msg_to_int), msg_to_int, hex(msg_to_int))
            r = int((msg_to_int & 0xFF0000) / 0x010000)
            g = int((msg_to_int & 0x00FF00) / 0x000100)
            b = int(msg_to_int & 0x0000FF)
            print(type(r), r, type(g), g, type(b), b,)
            
            pixel[0] = (r, g, b)
            
print("- bye -\n")



Comments

Popular posts from this blog

480x320 TFT/ILI9488 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

my dev.tools - FNIRSI 2C23T 3-in-1 Dual Channel Oscilloscope/Multimeter/Signal Generator