Adsense HTML/JavaScript

Thursday, November 25, 2021

RPi Pico/MicroPython + ESP-C3-12F (as a WiFi co-processor using AT Command)


It's a exercise on Raspberry Pi Pico/MicroPython work with ESP-C3-12F Module. The ESP-C3-12F preloaded with AT Command Firmware (AT version:2.2.0.0 (s-90458f0 - ESP32C3 - Jun 18 2021 10:24:22)), act as a WiFi co-processor. The Raspberry Pi Pico control ESP-C3-12F using AT Command, to connect and send data to TCP and UDP Server running on Raspberry Pi 4B/Python.


Connection:

It's strongly recommended using separate 3V3 Power Supply for ESP-C3-12F.


	Separated
	Power Supply	ESP-C3-12F            Raspberry Pi Pico
	
			+-------------+       +----------------
	3V3 ------------|VCC       RX0|-------| GP0 (UART TX)
			|          TX0|-------| GP1 (UART RX)
			|             |       |
			|          EN |-------| GP2  
			|     GND     |       |
			+------+------+       |
	                       |              |
	GND -------------------+--------------| GND
                                              +----------------
												
												
Exercise Code:

mpyPico_ESP_AT_TCP.py, a simple program to try AT command on ESP.
import usys, uos
import machine
import utime

class color:
    BLACK =   '\033[1;30;48m'
    RED =     '\033[1;31;48m'
    GREEN =   '\033[1;32;48m'
    YELLOW =  '\033[1;33;48m'
    BLUE =    '\033[1;34;48m'
    MAGENTA = '\033[1;35;48m'
    CYAN =    '\033[1;36;48m'
    END =    '\033[1;37;0m'

print("====================================")
print(usys.implementation[0], uos.uname()[3],
      "\nrun on", uos.uname()[4])
print("------------------------------------")


esp_reset = machine.Pin(2, machine.Pin.OUT)

#uart_esp =machine.UART(0, baudrate=115200)
uart_esp =machine.UART(0, timeout=1000)
#print("UART(0) connected to ESP: \n", uart_esp, "\n")

#==================================
"""
esp_sendCMD_waitResp: send comand to ESP, and wait response
if targetResp catched, return True
otherwise return False
"""
def esp_sendCMD_waitResp(cmd, uart=uart_esp, timeout=2000, targetResp="OK"):
    print(color.MAGENTA + cmd + color.END)
    uart.write(cmd)
    return esp_waitResp(uart, timeout, targetResp)

"""
esp_waitResp: wait ESP response
if targetResp catched, return True
otherwise return False
"""
def esp_waitResp(uart=uart_esp, timeout=2000, targetResp="OK"):
    targetCatched = False
    prvMills = utime.ticks_ms()
    print(color.BLUE)
    while (utime.ticks_diff(utime.ticks_ms(), prvMills))<timeout:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                if line_decoded == targetResp:
                    print(color.GREEN + line_decoded)
                    targetCatched = True
                    break
                
                #more checking for Response
                elif line_decoded == "OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "ERROR":
                    print(color.RED + line_decoded)
                    break
                
                elif line_decoded == "SEND OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "SEND FAIL":
                    print(color.RED + line_decoded)
                    break
                
                else:
                    print(line_decoded)
            except UnicodeError:
                print(line)
    
    print(color.END)
    return targetCatched
    
# In my test there are something
# like "################################################"
# follow ready of AT+RST/AT+RESTORE or hardware reset,
# Just dummy wait response to clear it
def esp_waitDummtResp(uart=uart_esp, timeout=2000):
    esp_waitResp(uart=uart_esp, timeout=2000)

#A dummy infinity loop
#to monitor any data sent from ESP via UART
def esp_dummyMonitor(uart=uart_esp):
    while True:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                print(line_decoded)
            except UnicodeError:
                print(line)
#==================================

print()
print("=== Start ===")


#hardware reset ESP
print("Hardware reset")
esp_reset.value(1)
utime.sleep(0.5)
esp_reset.value(0)
utime.sleep(0.5)
esp_reset.value(1)

print("wait 'ready' from Hardware Reset\n")
esp_waitResp(targetResp='ready')
esp_waitDummtResp()

esp_sendCMD_waitResp('AT\r\n')          #Test AT startup

esp_sendCMD_waitResp('AT+GMR\r\n')      #Check version information

esp_sendCMD_waitResp('AT+RESTORE\r\n')
esp_waitResp(targetResp='ready')    #wait ready
esp_waitDummtResp()

esp_sendCMD_waitResp('AT+CIPAPMAC?\r\n')  #Query MAC address of ESP SoftAP
esp_sendCMD_waitResp('AT+CIPSTAMAC?\r\n') #Query MAC address of ESP station

esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode
esp_sendCMD_waitResp('AT+CWMODE=2\r\n') #Set the Wi-Fi mode = SoftAP mode
esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode again

esp_sendCMD_waitResp('AT+CIPMUX=1\r\n') #Enable multiple connections
esp_sendCMD_waitResp('AT+CIPMUX?\r\n')

esp_sendCMD_waitResp('AT+CWSAP="esp","password",5,3\r\n')  #config ESP SoftAP
esp_sendCMD_waitResp('AT+CWSAP?\r\n')

esp_sendCMD_waitResp('AT+CIPAP?\r\n')  #Query the IP address of the ESP SoftAP

esp_dummyMonitor()

print("\n~ bye ~\n");

mpyPico_ESP_AT_ScanAP.py, scan Access Point.
"""
Raspberry Pi Pico/MicroPython + ESP-C3-12F exercise

ESP-C3-12F with AT-command firmware:
AT version:2.2.0.0(s-90458f0 - ESP32C3 - Jun 18 2021 10:24:22)

Scan Access Point
"""

import usys, uos
import machine
import utime

class color:
    BLACK =   '\033[1;30;48m'
    RED =     '\033[1;31;48m'
    GREEN =   '\033[1;32;48m'
    YELLOW =  '\033[1;33;48m'
    BLUE =    '\033[1;34;48m'
    MAGENTA = '\033[1;35;48m'
    CYAN =    '\033[1;36;48m'
    END =     '\033[1;37;0m'

print("====================================")
print(usys.implementation[0], uos.uname()[3],
      "\nrun on", uos.uname()[4])
print("------------------------------------")


esp_reset = machine.Pin(2, machine.Pin.OUT)

uart_esp =machine.UART(0, timeout=1000)
#print("UART(0) connected to ESP: \n", uart_esp, "\n")

#==================================
"""
esp_sendCMD_waitResp: send comand to ESP, and wait response
if targetResp catched, return True
otherwise return False
"""
def esp_sendCMD_waitResp(cmd, uart=uart_esp, timeout=2000, targetResp="OK"):
    print(color.MAGENTA + cmd + color.END)
    uart.write(cmd)
    return esp_waitResp(uart, timeout, targetResp)

"""
esp_waitResp: wait ESP response
if targetResp catched, return True
otherwise return False
"""
def esp_waitResp(uart=uart_esp, timeout=2000, targetResp="OK"):
    targetCatched = False
    prvMills = utime.ticks_ms()
    print(color.BLUE)
    while (utime.ticks_diff(utime.ticks_ms(), prvMills))<timeout:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                if line_decoded == targetResp:
                    print(color.GREEN + line_decoded)
                    targetCatched = True
                    break
                
                #more checking for Response
                elif line_decoded == "OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "ERROR":
                    print(color.RED + line_decoded)
                    break
                
                elif line_decoded == "SEND OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "SEND FAIL":
                    print(color.RED + line_decoded)
                    break
                
                else:
                    print(line_decoded)
            except UnicodeError:
                print(line)
    
    print(color.END)
    return targetCatched

# In my test there are something
# like "################################################"
# follow ready of AT+RST/AT+RESTORE or hardware reset,
# Just dummy wait response to clear it
def esp_waitDummtResp(uart=uart_esp, timeout=2000):
    esp_waitResp(uart=uart_esp, timeout=2000)

#A dummy infinity loop
#to monitor any data sent from ESP via UART
def esp_dummyMonitor(uart=uart_esp):
    while True:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                print(line_decoded)
            except UnicodeError:
                print(line)
#==================================

print()
print("=== Start ===")

#hardware reset ESP
print("Hardware reset")
esp_reset.value(1)
utime.sleep(0.5)
esp_reset.value(0)
utime.sleep(0.5)
esp_reset.value(1)

print("wait 'ready' from Hardware Reset\n")
esp_waitResp(targetResp='ready')
esp_waitDummtResp()

esp_sendCMD_waitResp('AT\r\n')          #Test AT startup

esp_sendCMD_waitResp('AT+GMR\r\n')      #Check version information

esp_sendCMD_waitResp('AT+RESTORE\r\n')
esp_waitResp(targetResp='ready')    #wait ready
esp_waitDummtResp()

esp_sendCMD_waitResp('AT+CIPAPMAC?\r\n')  #Query MAC address of ESP SoftAP
esp_sendCMD_waitResp('AT+CIPSTAMAC?\r\n') #Query MAC address of ESP station

esp_sendCMD_waitResp('AT+CWMODE=1\r\n') #Set the Wi-Fi mode = Station mode
esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode again

preScanTime = utime.ticks_ms()
esp_sendCMD_waitResp('AT+CWLAP\r\n', timeout=10000)  #List Available APs
print("Time used to Scan AP: ",
      utime.ticks_diff(utime.ticks_ms(), preScanTime),
      "(ms)")

print("\n~ bye ~\n");

mpyPico_ESP_AT_TCP_Client.py, TCP Client connect to TCP Server on Raspberry Pi/Python, pyMyTCPServer.py below.
"""
Raspberry Pi Pico/MicroPython + ESP-C3-12F exercise

ESP-C3-12F with AT-command firmware:
AT version:2.2.0.0(s-90458f0 - ESP32C3 - Jun 18 2021 10:24:22)

Pico send AT command to ESP-C3-12F via UART,
- set in station mode
- join AP
- connect to server ip:port 9999
- send text and wait response

Modified from exercise in my another blogspot
https://helloraspberrypi.blogspot.com/2021/02/
picomicropython-esp-01s-at-command-act.html
"""

import usys, uos
import machine
import utime

class color:
    BLACK =   '\033[1;30;48m'
    RED =     '\033[1;31;48m'
    GREEN =   '\033[1;32;48m'
    YELLOW =  '\033[1;33;48m'
    BLUE =    '\033[1;34;48m'
    MAGENTA = '\033[1;35;48m'
    CYAN =    '\033[1;36;48m'
    END =     '\033[1;37;0m'
   
#server port & ip hard-coded,
#have to match with server side setting
server_ip="192.168.120.147"
server_port=9999

print("====================================")
print(usys.implementation[0], uos.uname()[3],
      "\nrun on", uos.uname()[4])
print("------------------------------------")


esp_reset = machine.Pin(2, machine.Pin.OUT)

#uart_esp =machine.UART(0, baudrate=115200)
uart_esp =machine.UART(0, timeout=1000)
#print("UART(0) connected to ESP: \n", uart_esp, "\n")

#==================================
"""
esp_sendCMD_waitResp: send comand to ESP, and wait response
if targetResp catched, return True
otherwise return False
"""
def esp_sendCMD_waitResp(cmd, uart=uart_esp, timeout=2000, targetResp="OK"):
    print(color.MAGENTA + cmd + color.END)
    uart.write(cmd)
    return esp_waitResp(uart, timeout, targetResp)

"""
esp_waitResp: wait ESP response
if targetResp catched, return True
otherwise return False
"""
def esp_waitResp(uart=uart_esp, timeout=2000, targetResp="OK"):
    targetCatched = False
    prvMills = utime.ticks_ms()
    print(color.BLUE)
    while (utime.ticks_diff(utime.ticks_ms(), prvMills))<timeout:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                if line_decoded == targetResp:
                    print(color.GREEN + line_decoded)
                    targetCatched = True
                    break
                
                #more checking for Response
                elif line_decoded == "OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "ERROR":
                    print(color.RED + line_decoded)
                    break
                
                elif line_decoded == "SEND OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "SEND FAIL":
                    print(color.RED + line_decoded)
                    break
                
                else:
                    print(line_decoded)
            except UnicodeError:
                print(line)
    
    print(color.END)
    return targetCatched


def espSend(text="test", uart=uart_esp):
    esp_sendCMD_waitResp('AT+CIPSEND=' + str(len(text)) + '\r\n')
    esp_waitResp(targetResp=">")
    esp_sendCMD_waitResp(text)

# In my test there are something
# like "################################################"
# follow ready of AT+RST/AT+RESTORE or hardware reset,
# Just dummy wait response to clear it
def esp_waitDummtResp(uart=uart_esp, timeout=2000):
    esp_waitResp(uart=uart_esp, timeout=2000)

#==================================

print()
print("=== Start ===")

#hardware reset ESP
print("Hardware reset")
esp_reset.value(1)
utime.sleep(0.5)
esp_reset.value(0)
utime.sleep(0.5)
esp_reset.value(1)

print("wait 'ready' from Hardware Reset\n")
esp_waitResp(targetResp='ready')
esp_waitDummtResp()

esp_sendCMD_waitResp('AT\r\n')          #Test AT startup

esp_sendCMD_waitResp('AT+GMR\r\n')      #Check version information

esp_sendCMD_waitResp('AT+RESTORE\r\n')
esp_waitResp(targetResp='ready')    #wait ready
esp_waitDummtResp()

esp_sendCMD_waitResp('AT+CIPAPMAC?\r\n')  #Query MAC address of ESP SoftAP
esp_sendCMD_waitResp('AT+CIPSTAMAC?\r\n') #Query MAC address of ESP station

esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode
esp_sendCMD_waitResp('AT+CWMODE=1\r\n') #1 = Station mode
                                    #2 = SoftAP mode
esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode again

esp_sendCMD_waitResp('AT+CWJAP="ssid","password"\r\n', timeout=5000) #Connect to AP
esp_sendCMD_waitResp('AT+CIFSR\r\n')    #Obtain the Local IP Address

esp_sendCMD_waitResp('AT+CIPSTART="TCP","' +
                     server_ip + '",' +
                     str(server_port) + '\r\n')

espSend()

while True:
    print('Enter something:')
    msg = input()
    esp_sendCMD_waitResp('AT+CIPSTART="TCP","' +
                         server_ip + '",' +
                         str(server_port) + '\r\n')
    espSend(msg)
    
print("\n~ bye ~\n");

pyMyTCPServer.py, TCP Server run on Raspberry Pi.
"""
Simple Python TCP Server
tested on Raspberry Pi/Python3

ref:
https://docs.python.org/3/library/socketserver.html
"""
import socketserver
import platform

print("sys info:")
for info in platform.uname():
    print(info)

class MyTCPHandler(socketserver.BaseRequestHandler):
    """
    The request handler class for our server.

    It is instantiated once per connection to the server, and must
    override the handle() method to implement communication to the
    client.
    """

    def handle(self):
        # self.request is the TCP socket connected to the client
        self.data = self.request.recv(1024).strip()
        print("{} wrote:".format(self.client_address[0]))
        print(self.data)
        # just send back the same data, but upper-cased
        self.request.sendall(self.client_address[0].encode())
        self.request.sendall(self.data.upper())
        self.request.sendall(b'\r\n')

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999

    # Create the server, binding to localhost on port 9999
    #with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
    with socketserver.TCPServer(('', PORT), MyTCPHandler) as server:
        # Activate the server; this will keep running until you
        # interrupt the program with Ctrl-C

        server.serve_forever()

mpyPico_ESP_AT_UDP.py, UDP connect to pyUDP_server.py (listed below) on Raspberry Pi.
"""
Raspberry Pi Pico/MicroPython + ESP-C3-12F exercise

ESP-C3-12F with AT-command firmware:
AT version:2.2.0.0(s-90458f0 - ESP32C3 - Jun 18 2021 10:24:22)

Pico send AT command to ESP-C3-12F via UART,
- set in station mode
- join AP
- connect to UDP
- send text and wait response

ref:
https://docs.espressif.com/projects/esp-at/en/release-v2.2.0.0_esp32c3/
AT_Command_Examples/TCP-IP_AT_Examples.html
Example 3.2. UDP Transmission with Changeable Remote IP and Port
"""

import usys, uos
import machine
import utime

class color:
    BLACK =   '\033[1;30;48m'
    RED =     '\033[1;31;48m'
    GREEN =   '\033[1;32;48m'
    YELLOW =  '\033[1;33;48m'
    BLUE =    '\033[1;34;48m'
    MAGENTA = '\033[1;35;48m'
    CYAN =    '\033[1;36;48m'
    END =     '\033[1;37;0m'
   
#server port & ip hard-coded,
#have to match with server side setting
server_ip="192.168.120.147"
server_port=8000

print("====================================")
print(usys.implementation[0], uos.uname()[3],
      "\nrun on", uos.uname()[4])
print("------------------------------------")


esp_reset = machine.Pin(2, machine.Pin.OUT)

#uart_esp =machine.UART(0, baudrate=115200)
uart_esp =machine.UART(0, timeout=1000)
#print("UART(0) connected to ESP: \n", uart_esp, "\n")

#==================================
"""
esp_sendCMD_waitResp: send comand to ESP, and wait response
if targetResp catched, return True
otherwise return False
"""
def esp_sendCMD_waitResp(cmd, uart=uart_esp, timeout=2000, targetResp="OK"):
    print(color.MAGENTA + cmd + color.END)
    uart.write(cmd)
    return esp_waitResp(uart, timeout, targetResp)

"""
esp_waitResp: wait ESP response
if targetResp catched, return True
otherwise return False
"""
def esp_waitResp(uart=uart_esp, timeout=2000, targetResp="OK"):
    targetCatched = False
    prvMills = utime.ticks_ms()
    print(color.BLUE)
    while (utime.ticks_diff(utime.ticks_ms(), prvMills))<timeout:
        line=uart.readline()
        if line is not None:
            try:
                line_decoded = line.strip().decode()
                if line_decoded == targetResp:
                    print(color.GREEN + line_decoded)
                    targetCatched = True
                    break
                
                #more checking for Response
                elif line_decoded == "OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "ERROR":
                    print(color.RED + line_decoded)
                    break
                
                elif line_decoded == "SEND OK":
                    print(color.GREEN + line_decoded)
                    break
                elif line_decoded == "SEND FAIL":
                    print(color.RED + line_decoded)
                    break
                
                else:
                    print(line_decoded)
            except UnicodeError:
                print(line)
    
    print(color.END)
    return targetCatched


def espSend(text="test", uart=uart_esp):
    esp_sendCMD_waitResp('AT+CIPSEND=' + str(len(text)) + '\r\n')
    esp_waitResp(targetResp=">")
    esp_sendCMD_waitResp(text)

# In my test there are something
# like "################################################"
# follow ready of AT+RST/AT+RESTORE or hardware reset,
# Just dummy wait response to clear it
def esp_waitDummtResp(uart=uart_esp, timeout=2000):
    esp_waitResp(uart=uart_esp, timeout=2000)

#==================================

print()
print("=== Start ===")

#hardware reset ESP
print("Hardware reset")
esp_reset.value(1)
utime.sleep(0.5)
esp_reset.value(0)
utime.sleep(0.5)
esp_reset.value(1)

print("wait 'ready' from Hardware Reset\n")
esp_waitResp(targetResp='ready')
esp_waitDummtResp()

esp_sendCMD_waitResp('AT\r\n')          #Test AT startup

esp_sendCMD_waitResp('AT+GMR\r\n')      #Check version information

esp_sendCMD_waitResp('AT+RESTORE\r\n')
esp_waitResp(targetResp='ready')    #wait ready
esp_waitDummtResp()

esp_sendCMD_waitResp('AT+CIPAPMAC?\r\n')  #Query MAC address of ESP SoftAP
esp_sendCMD_waitResp('AT+CIPSTAMAC?\r\n') #Query MAC address of ESP station

esp_sendCMD_waitResp('AT+CWMODE=3\r\n') #3 = SoftAP+Station mode
esp_sendCMD_waitResp('AT+CWMODE?\r\n')  #Query the Wi-Fi mode again

esp_sendCMD_waitResp('AT+CWJAP="ssid","password"\r\n', timeout=5000) #Connect to AP
esp_sendCMD_waitResp('AT+CIFSR\r\n')    #Obtain the Local IP Address
            
esp_sendCMD_waitResp('AT+CIPSTART="UDP","' +
                     server_ip +
                     '",' + str(server_port) +
                     ',' + '1112,2\r\n')

espSend()

while True:
    print('Enter something:')
    msg = input()
    espSend(msg)

print("\n~ bye ~\n");

pyUDP_server.py
"""
Simple Python UDP Server
tested on Raspberry Pi/Python3

ref:
https://wiki.python.org/moin/UdpCommunication
"""
import socket

#have to match my ip
UDP_IP = "192.168.120.147"
UDP_PORT = 8000

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

print("UDP IP: %s" % UDP_IP)
print("UDP port: %s" % UDP_PORT)

while True:
    data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes
    print("received message: %s" % data)

Tuesday, November 23, 2021

ESP-C3-12F First power-up

Just received ESP-C3-12F. With "C3FN4" marked on the module shield, that means it have Build-in 4MByte FLASH. ESP-C3-12F is a Wi-Fi module developed by Ai-Thinker. This module core processor ESP32-C3 is a Wi-Fi+ BLE combination of system-level chips (SoC).

In order to use the ESP-C3-12F, I solder it on a special multi-function PCB for ESP-12F (or called "diymore ESP8266 ESP-12E ESP-12F ESP32 Double Side Prototype PCB Board").


I also add buttons of RESET and BOOT connect EN and IO9 (same position of IO0 on ESP-12F), to force it entering BOOTLOADER mode for using with esptool.

It's strongly recommended using separate 3V3 Power Supply for ESP-C3-12F. A USB to Serial Breakout (FT232RL) in 3V3 operation mode is used to connect to ESP-C3-12F.

In my practice, the connection is:

USB-to-Serial (FT232RL)   ESP-C3-12F
(in 3V3 mode)
RX                        TX0
TX                        RX0
GND                       GND

RESET BUTTON              EN/GND
BOOT BUTTON               IO9/GND

Separate Power Supply
+3V3                      VCC
GND                       GND


log of esptool output:
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 chip_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting........_____....._
Detecting chip type... ESP32-C3
Chip is unknown ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: 84:f7:03:a5:10:94
Uploading stub...
Running stub...
Stub running...
Warning: ESP32-C3 has no Chip ID. Reading MAC instead.
MAC: 84:f7:03:a5:10:94
Hard resetting via RTS pin...
pi@raspberrypi:~ $ esptool.py --chip auto --port /dev/ttyUSB0 flash_id
esptool.py v3.1
Serial port /dev/ttyUSB0
Connecting...
Detecting chip type... ESP32-C3
Chip is unknown ESP32-C3 (revision 3)
Features: Wi-Fi
Crystal is 40MHz
MAC: 84:f7:03:a5:10:94
Stub is already running. No upload is necessary.
Manufacturer: 20
Device: 4016
Detected flash size: 4MB
Hard resetting via RTS pin...
pi@raspberrypi:~ $


log of AT Command:
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fcd6100,len:0x147c
load:0x403ce000,len:0x91c
load:0x403d0000,len:0x2838
entry 0x403ce000

################################################
arch:ESP32C3, 3
compile_time:Ai-Thinker|B&T
ble_mac:84F703a51096
wifi_mac:84F703a51094
sdk_version:v4.3-beta3-195-g6be10fab0
firmware_version:2.2.0
compile_time:Jul  5 2021 13:46:35

ready

################################################AT

OK
AT

OK
AT+GMR
AT version:2.2.0.0(s-90458f0 - ESP32C3 - Jun 18 2021 10:24:22)
SDK version:v4.3-beta3-195-g6be10fab0
compile time(5fb0957):Jul  5 2021 13:46:35
Bin version:2.2.0(MINI-1)

OK
AT+RST

OK
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0xc (RTC_SW_CPU_RST),boot:0xc (SPI_FAST_FLASH_BOOT)
Saved PC:0x40383888
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fcd6100,len:0x147c
load:0x403ce000,len:0x91c
load:0x403d0000,len:0x2838
entry 0x403ce000

################################################
arch:ESP32C3, 3
compile_time:Ai-Thinker|B&T
ble_mac:84F703a51096
wifi_mac:84F703a51094
sdk_version:v4.3-beta3-195-g6be10fab0
firmware_version:2.2.0
compile_time:Jul  5 2021 13:46:35

ready

################################################



Remark:

Actually, I'm confussed.

According to ESP-AT v2.2.0.0_esp32c3 User Guide, AT Command should be sent to UART1 (GPIO6/GPIO7). But in my test as shown in the video. Both esptool and AT Command are sent to UART0 (GPIO20/21).

Or, is it AI-Thinker firmware have different port usage?




Next::

Friday, November 5, 2021

ESP32-C3/arduino-esp32 to display on ST7735 and ST7789 SPI LCDs

This exercise run on ESP32-C3-DevKitM-1 with arduino-esp32 2.0.0, to display on ST7735 and ST7789 SPI LCDs using "Adafruit ST7735 and ST7789 Library" and "Adafruit GFX Library".

Make sure both "Adafruit ST7735 and ST7789 Library" and "Adafruit GFX Library" are installed in Arduino IDE.

ST7735 and ST7789 share the common SPI bus and A0(DC), and separated CS and RESET. Connection refer to the exercise code, marked in RED.


ESP32C3_ST77xx_hello.ino
/*
 * arduino-esp32 exercise run on ESP32-C3-DevKitM-1,
 * display on 1.8" 128x160 TFT with SPI ST7735, and
 * 2.0" IPS 240x320 RGB LCD with SPI ST7789,
 * using 'Adafruit ST7735 and ST7789 Library'.
 * 
 * ref:
 * graphicstest example under 'Adafruit ST7735 and ST7789 Library'
 */


#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789

#define TFT_CS_ST7735   10
#define TFT_RST_ST7735  9 // Or set to -1 and connect to Arduino RESET pin
#define TFT_CS_ST7789   2
#define TFT_RST_ST7789  3   
#define TFT_DC        8   

/*
 * Erik:
 * on ESP32-C3-DevKitM-1
 * SS:   7  - not used
 * MOSI: 6
 * MISO: 5  - not used
 * SCK:  4
 * ===================
 * Conection:
 * In my exercise,
 * ST7735 AND ST7789 Share the same pins, 
 * except RESET and CS, marked +
 * 
 * TFT_ST7735 ESP32-C3
 * -------------------
 * VCC        3V3
 * GND        GND
 * CS         10    +
 * RESET      9     +
 * A0(DC)     8
 * SDA        6
 * SCK        4
 * LED        3V3
 *
 * TFT_ST7789 ESP32-C3
 * -------------------
 * BLK        3V3
 * CS         2     +
 * DC         8
 * RES        3     +
 * SDA        6
 * SCL        4
 * VCC        3V3
 * GND        GND
 */

/*
 * for ST7735 displays:
 * Differences between displays (usu. identified by colored tab on
 * plastic overlay) are odd enough that we need to do this 'by hand':
 * https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.h
 */

Adafruit_ST7735 tft_ST7735 = Adafruit_ST7735(TFT_CS_ST7735, TFT_DC, TFT_RST_ST7735);
Adafruit_ST7789 tft_ST7789 = Adafruit_ST7789(TFT_CS_ST7789, TFT_DC, TFT_RST_ST7789);

void setup(void) {
  delay(500);
  Serial.begin(115200);
  delay(500);
  Serial.print(F("Hello! ST77xx TFT Test\n"));

  tft_ST7735.initR(INITR_BLACKTAB);      // Init ST7735S chip, green tab
  tft_ST7789.init(240, 320);

  // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
  // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you
  // may end up with a black screen some times, or all the time.
  //tft.setSPISpeed(40000000);

  Serial.println(F("Initialized"));


  // large block of text
  tft_ST7735.fillScreen(ST77XX_BLACK);
  tft_ST7735.setTextWrap(true);
  tft_ST7735.setTextColor(ST77XX_WHITE);
  tft_ST7789.fillScreen(ST77XX_BLACK);
  tft_ST7789.setTextWrap(true);
  tft_ST7789.setTextColor(ST77XX_WHITE);
  
  tft_ST7735.setCursor(0, 0);
  tft_ST7735.print("Hello ESP32C3");
  tft_ST7789.setCursor(0, 0);
  tft_ST7789.print("Hello ESP32C3");

  tft_ST7735.setCursor(0, 20);
  tft_ST7735.print("Chip Model: " + String(ESP.getChipModel()));
  tft_ST7735.setCursor(0, 30);
  tft_ST7735.print("rotation: " + String(tft_ST7735.getRotation()));
  tft_ST7735.setCursor(0, 40);
  tft_ST7735.print(String(tft_ST7735.width()) + " x " + String(tft_ST7735.height()));

  tft_ST7789.setCursor(0, 20);
  tft_ST7789.print("Chip Model: " + String(ESP.getChipModel()));
  tft_ST7789.setCursor(0, 30);
  tft_ST7789.print("rotation: " + String(tft_ST7789.getRotation()));
  tft_ST7789.setCursor(0, 40);
  tft_ST7789.print(String(tft_ST7789.width()) + " x " + String(tft_ST7789.height()));
  
  delay(2000);

  tft_ST7735.setRotation(3);
  tft_ST7735.setCursor(0, 30);
  tft_ST7735.print("rotation: " + String(tft_ST7735.getRotation()));
  tft_ST7735.setCursor(0, 40);
  tft_ST7735.print(String(tft_ST7735.width()) + " x " + String(tft_ST7735.height()));

  tft_ST7789.setRotation(3);
  tft_ST7789.setCursor(0, 30);
  tft_ST7789.print("rotation: " + String(tft_ST7735.getRotation()));
  tft_ST7789.setCursor(0, 40);
  tft_ST7789.print(String(tft_ST7789.width()) + " x " + String(tft_ST7789.height()));
  
  delay(2000);

  tft_ST7735.fillScreen(ST77XX_RED);
  tft_ST7735.setCursor(50, 50);
  tft_ST7735.print("RED");
  tft_ST7789.fillScreen(ST77XX_RED);
  tft_ST7789.setCursor(50, 50);
  tft_ST7789.print("RED");
  delay(1000);
  tft_ST7735.fillScreen(ST77XX_GREEN);
  tft_ST7735.setCursor(50, 50);
  tft_ST7735.print("GREEN");
  tft_ST7789.fillScreen(ST77XX_GREEN);
  tft_ST7789.setCursor(50, 50);
  tft_ST7789.print("GREEN");
  delay(1000);
  tft_ST7735.fillScreen(ST77XX_BLUE);
  tft_ST7735.setCursor(50, 50);
  tft_ST7735.print("BLUE");
  tft_ST7789.fillScreen(ST77XX_BLUE);
  tft_ST7789.setCursor(50, 50);
  tft_ST7789.print("BLUE");
  delay(1000);

  delay(1000);
  for(int offset=0; offset<tft_ST7735.height()/2; offset++){
    int col;
    if(offset%2 == 0)
      col = ST77XX_WHITE;
    else
      col = ST77XX_BLACK;
      
    tft_ST7735.drawRect(offset, offset, 
                 tft_ST7735.width()-2*offset, tft_ST7735.height()-2*offset,
                 col);
    delay(100);
  }

  int cx_ST7789 = tft_ST7789.width()/2;
  int cy_ST7789 = tft_ST7789.height()/2;
  for(int r=0; r<tft_ST7789.height()/2; r=r+5){

    tft_ST7789.drawCircle(cx_ST7789, cy_ST7789, 
                 r,
                 ST77XX_WHITE);
    delay(100);
  }

  delay(2000);

  Serial.println("- setup() end -");
  delay(1000);
}

void loop() {
  tft_ST7735.invertDisplay(true);
  tft_ST7789.invertDisplay(true);
  delay(500);
  tft_ST7735.invertDisplay(false);
  tft_ST7789.invertDisplay(false);
  delay(500);
}

Next:
ESP32-C3/arduino-esp32 + 0.96" 80x160 IPS, create custom class extends Adafruit ST7735 library.

Related:
128x160 TFT/ST7735 SPI wih EP32C3 (arduino-esp32) using Arduino_GFX Library

Tuesday, November 2, 2021

MicroPython/PyBoard exercise: + 1.8" 128x160 TFT ST7735 SPI

It's a MicroPython/PyBoard exercise run on Modified MicroPython pyboard PYBv1.1, to drive 1.8" 128x160 TFT ST7735 SPI using GuyCarver/MicroPython lib.




Prepare library:

Visit https://github.com/GuyCarver/MicroPython/tree/master/lib copy ST7735.py, seriffont.py, sysfont.py and terminalfont.py to your pyboard.


Connection:

Refer to __init__() of class tft in ST7735.py:

  def __init__( self, aLoc, aDC, aReset ) :
    '''aLoc SPI pin location is either 1 for 'X' or 2 for 'Y'.
       aDC is the DC pin and aReset is the reset pin.'''
	.
	.
	.
    cs = "X5" if aLoc == 1 else "Y5"
	.
	.
    self.spi = pyb.SPI(aLoc, ...)
	.
	.

And refer to pyb SPI class document.


That means 
when aloc = 1:
SPI(1) is on the X position: (CS, SCK, MISO, MOSI) = (X5, X6, X7, X8)
when aloc = 2:
SPI(2) is on the Y position: (CS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8)

In my exercise code below marked RED, display of ST7735.tft is created with aLoc=1.
display = ST7735.tft(aLoc=1, aDC='Y9', aReset='Y10')
So the connection is:
ST7735	Pyboard
	aLoc=1	(if aLoc=2)
----------------------------
LED	3V3		
SCK	X6	Y6
SDA	X8	Y8
A0	Y9
RESET	Y10
CS	X5	Y5
GND	GND
VCC	3V3

Exercise code:

mpyPyb_tft.py
"""
MicroPython/PyBoard exercise run on Pyb v1.1,
+ 1.8" 128x160 TFT ST7735 SPI

using GuyCarver/MicroPython
https://github.com/GuyCarver/MicroPython
"""
import uos
import usys
import time
import random
import ST7735
from seriffont import seriffont
from sysfont import sysfont
from terminalfont import terminalfont

print("====================================")
print(usys.implementation[0], uos.uname()[3],
      "\nrun on", uos.uname()[4])
print("------------------------------------")

print("====================================")

display = ST7735.tft(aLoc=1, aDC='Y9', aReset='Y10')

displaysize = display.size()
print(displaysize)

display.initg() # or initr()/initb() according to your display

display.rotation(1)
display.fill(display._BLACK)
display.text((0,0),
             usys.implementation[0]+' '+uos.uname()[3],
             display._WHITE,
             terminalfont)
time.sleep(1)
display.text((0,30),
             "run on "+uos.uname()[4],
             ST7735.TFTColor(0xFF, 0xFF, 0xFF),
             terminalfont)
time.sleep(3)

#font test
display.fill(display._BLACK)
display.text((0,0),
             "seriffont",
             display._RED,
             seriffont)
display.text((0,10),
             "abcdefghijklmnopqrstuvwxyz",
             display._WHITE,
             seriffont)
display.text((0,30),
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
             display._WHITE,
             seriffont)
display.text((0,50),
             "sysfont",
             display._RED,
             sysfont)
display.text((0,60),
             "abcdefghijklmnopqrstuvwxyz",
             display._WHITE,
             sysfont)
display.text((0,70),
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
             display._WHITE,
             sysfont)
display.text((0,80),
             "terminalfont",
             display._RED,
             terminalfont)
display.text((0,90),
             "abcdefghijklmnopqrstuvwxyz",
             display._WHITE,
             terminalfont)
display.text((0,110),
             "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
             display._WHITE,
             terminalfont)
time.sleep(5)

display.rotation(0)
display.fill(display._RED)
display.text((10,10),
             "RED",
             ST7735.TFTColor(0xFF, 0xFF, 0xFF),
             terminalfont,
             aSize=2)
time.sleep(1)

display.fill(display._GREEN)
display.text((10,10),
             "GREEN",
             ST7735.TFTColor(0xFF, 0xFF, 0xFF),
             terminalfont,
             aSize=2)
time.sleep(1)

display.fill(display._BLUE)
display.text((10,10),
             "BLUE",
             ST7735.TFTColor(0xFF, 0xFF, 0xFF),
             terminalfont,
             aSize=2)
time.sleep(1)

#rotation test
display.rotation(0)
display.fill(display._BLACK)
display.fillrect((1,1),
                 (display.size()[0]-2, display.size()[1]-2),
                 display._WHITE)
display.text((0,0),
             "rotate = "+str(display.rotate)+" : "+str(display.size()),
             display._BLACK,
             terminalfont)
print("rotate = "+str(display.rotate)+" : "+str(display.size()))
time.sleep(2)

display.rotation(1)
display.fillrect((2,2),
                 (display.size()[0]-4, display.size()[1]-4),
                 display._BLACK)
display.text((0,0),
             "rotate = "+str(display.rotate)+" : "+str(display.size()),
             display._WHITE,
             terminalfont)
print("rotate = "+str(display.rotate)+" : "+str(display.size()))
time.sleep(2)

display.rotation(2)
display.fillrect((3,3),
                 (display.size()[0]-6, display.size()[1]-6),
                 display._WHITE)
display.text((0,0),
             "rotate = "+str(display.rotate)+" : "+str(display.size()),
             display._BLACK,
             terminalfont)
print("rotate = "+str(display.rotate)+" : "+str(display.size()))
time.sleep(2)

display.rotation(3)
display.fillrect((4,4),
                 (display.size()[0]-8, display.size()[1]-8),
                 display._BLACK)
display.text((0,0),
             "rotate = "+str(display.rotate)+" : "+str(display.size()),
             display._WHITE,
             terminalfont)
print("rotate = "+str(display.rotate)+" : "+str(display.size()))
time.sleep(2)

#Random pixel
for p in range(1000):
    x = random.randint(5, display.size()[0]-10)
    y = random.randint(5, display.size()[1]-10)
    c = ST7735.TFTColor(random.randint(0, 0xFF),
                        random.randint(0, 0xFF),
                        random.randint(0, 0xFF))
    display.pixel((x, y), c)
    
#Random line
for l in range(100):
    display.line((random.randint(5, display.size()[0]-10),
                  random.randint(5, display.size()[1]-10)),
                 (random.randint(5, display.size()[0]-10),
                  random.randint(5, display.size()[1]-10)),
                 ST7735.TFTColor(random.randint(0, 0xFF),
                        random.randint(0, 0xFF),
                        random.randint(0, 0xFF)))

#Random circle
for l in range(20):
    display.circle((random.randint(5, display.size()[0]-10),
                    random.randint(5, display.size()[1]-10)),
                   random.randint(1, 50),
                   ST7735.TFTColor(random.randint(0, 0xFF),
                                   random.randint(0, 0xFF),
                        random.randint(0, 0xFF)))
    
#Random fillcircle
for l in range(20):
    display.fillcircle((random.randint(5, display.size()[0]-10),
                    random.randint(5, display.size()[1]-10)),
                   random.randint(1, 50),
                   ST7735.TFTColor(random.randint(0, 0xFF),
                                   random.randint(0, 0xFF),
                        random.randint(0, 0xFF)))

print("~ bye ~")
When you run the exercise code, it will fail with:
NameError: name 'BLACK' isn't defined

To fix it, edit ST7735.py in pyboard.
  def fill( self, aColor = BLACK ) :
to
  def fill( self, aColor = _BLACK ) :
Re-run again, it should work as expected.




Related:
MicroPython/ESP32-C3 + 1.8" 128x160 TFT ST7735 SPI, using boochow/MicroPython-ST7735 library. (in my another new blogspot)