Módulo de interface WiFi ESP8266 com Raspberry Pi Pico

Tempo de leitura: 8 minutes

Neste tutorial, você aprenderá como fazer a interface do módulo WiFi ESP8266-01 com o Rasperry Pi Pico para obter conectividade com a Internet. Vamos criar um TCP Web Server com Raspberry Pi Pico usando comandos AT do módulo ESP-01 e usar a porta serial da placa Pico para configurar o módulo WiFi ESP-01 para conectar com WiFi e criar um servidor web. Usaremos o Thonny IDE para programar o Raspberry Pi Pico com o ESP-01 no MircoPython.

 

Raspberry Pi Pico é uma placa de baixo custo e alto desempenho baseada no chip microcontrolador Raspberry Pi RP2040. Mas, ele não suporta recursos WiFi, portanto, temos que usar um módulo WiFi externo para habilitar a conectividade WiFi para Raspberry Pi Pico.

 

Módulo WiFi ESP8266

Em agosto de 2014, a Espressif Systems lançou seu primeiro módulo bruto, fabricado por uma terceira parte do AI-Thinker e módulo conhecido como módulo ESP-01

O ESP8266 oferece uma solução WiFi altamente integrada que atende às necessidades dos setores da Internet das Coisas, como baixo custo, uso eficiente de energia, desempenho confiável e design compacto.

O módulo WIFI ESP8266 é basicamente uma solução WiFi completa, que possui uma pilha de protocolos TCP/IP integrada que pode ser facilmente conectada ao microcontrolador para obter acesso a qualquer rede WiFi.

Usaremos comandos de envio AT para o módulo ESP8266 sobre UART do Raspberry Pi Pico para configurar o servidor Web TCP.

Existem muitos módulos WiFi ESP8266 disponíveis no mercado, desde ESP-01 a ESP-12. Mas neste tutorial, estamos usando o ESP-01. Os comandos AT são os mesmos para todos esses módulos ESP.

 

Pinagem do módulo ESP-01

O módulo WiFi ESP8266-01 consiste em duas fileiras de oito pinos. O diagrama de configuração dos pinos é mostrado na figura abaixo:

Tem um total de 8 pinos dos quais 6 pinos estão ativos.

EtiquetaDescrição
3.3VFornecimento de pino de 3,3 volts
GNDPino terra
RSTPino Reset
CH_PD/ENPotência do chip e pino de ativação
GPIO 0 to 3Interface UART e pinos de entrada/saída
  • Pino_1, que é um pino GND, é conectado diretamente ao terra para alimentar este módulo.
  • Pinos_2 e 3, que são o GPIO 2 e o GPIO 0, esses pinos decidem em qual modo o módulo seria uma partida, ou seja, são os pinos de modo selecionado.
  • Pinos_4 e 5, que são RX e TX, esses pinos são usados para fins de comunicação e programação do módulo.
  • Pino_6 que é CH_PD, é chamado de pino de desligamento do chip.
  • Pino_7 que é o pino RST e este pino é usado para redefinir o módulo.
  • Pino_8 é um pino VCC que é usado para alimentar o módulo. A tensão de operação do ESP-01 é de 3,3 volts.

 

Módulo de interface Wi-Fi ESP-01 com Raspberry Pi Pico

Vamos precisar dos seguintes componentes:

  • Raspberry PI Pico
  • Módulo ESP8266 ESP-01
  • Fios de conexão
  • Protoboard (não necessário)

Como vimos acima o módulo ESP-01 é composto por 8 pinos. No entanto, usaremos 5 pinos para conectá-lo à placa Raspberry Pi Pico. Estes incluem os pinos VCC, EN, GND, RX e TX. Os pinos RX e TX do módulo serão conectados aos pinos UART da placa Pi Pico. Vamos primeiro dar uma olhada nos pinos UART do Raspberry Pi Pi.

Pinos UART Raspberry Pi Pico

Raspberry Pi Pico contém dois periféricos UART idênticos com FIFOs 32×8 Tx e 32×12 Rx separados.

A tabela a seguir lista os pinos GPIO para ambos os periféricos UART que são expostos nas pinagens da placa de desenvolvimento Raspberry Pi Pico.

Pinos UARTPinos GPIO
UART0-TXGP0/GP12/GP16
UART0-RXGP1/GP13/GP17
UART1-TXGP4/GP8
UART1-RXGP5/GP9

Diagrama de ligação

Para este tutorial, usaremos os pinos UART0 TX e RX do Raspberry Pi Pico. Siga o diagrama de conexão abaixo para conectar os dois dispositivos.

Raspberry Pi PicoESP-01
3.3VVCC
3.3VEN
GNDGND
GP1 (UART0 RX)TX
GP0 (UART0 TX)RX

Raspberry Pi Pico Web Server MicroPython Script

O seguinte script MicriPython do Raspberry Pi Pico envia comandos AT para o módulo ESP8266 para configurar o ESP8266 como um servidor Web TCP. Veremos detalhes de todos os comandos AT nas próximas seções.

import uos
import machine
import utime

recv_buf="" # receive buffer global variable

print()
print("Machine: \t" + uos.uname()[4])
print("MicroPython: \t" + uos.uname()[3])

uart0 = machine.UART(0, baudrate=115200)
print(uart0)

def Rx_ESP_Data():
    recv=bytes()
    while uart0.any()>0:
        recv+=uart0.read(1)
    res=recv.decode('utf-8')
    return res

def Connect_WiFi(cmd, uart=uart0, timeout=3000):
    print("CMD: " + cmd)
    uart.write(cmd)
    utime.sleep(7.0)
    Wait_ESP_Rsp(uart, timeout)
    print()

def Send_AT_Cmd(cmd, uart=uart0, timeout=3000):
    print("CMD: " + cmd)
    uart.write(cmd)
    Wait_ESP_Rsp(uart, timeout)
    print()
    
def Wait_ESP_Rsp(uart=uart0, timeout=3000):
    prvMills = utime.ticks_ms()
    resp = b""
    while (utime.ticks_ms()-prvMills)<timeout:
        if uart.any():
            resp = b"".join([resp, uart.read(1)])
    print("resp:")
    try:
        print(resp.decode())
    except UnicodeError:
        print(resp)
    
Send_AT_Cmd('AT\r\n')          #Test AT startup
Send_AT_Cmd('AT+GMR\r\n')      #Check version information
Send_AT_Cmd('AT+CIPSERVER=0\r\n')      #Check version information
Send_AT_Cmd('AT+RST\r\n')      #Check version information
Send_AT_Cmd('AT+RESTORE\r\n')  #Restore Factory Default Settings
Send_AT_Cmd('AT+CWMODE?\r\n')  #Query the WiFi mode
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the WiFi mode = Station mode
Send_AT_Cmd('AT+CWMODE?\r\n')  #Query the WiFi mode again
#Send_AT_Cmd('AT+CWLAP\r\n', timeout=10000) #List available APs
Connect_WiFi('AT+CWJAP="HUAWEI-u67E","4uF77R2n"\r\n', timeout=5000) #Connect to AP
Send_AT_Cmd('AT+CIFSR\r\n')    #Obtain the Local IP Address
utime.sleep(3.0)
Send_AT_Cmd('AT+CIPMUX=1\r\n')    #Obtain the Local IP Address
utime.sleep(1.0)
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n')    #Obtain the Local IP Address
utime.sleep(1.0)
print ('Starting connection to ESP8266...')
while True:
    res =""
    res=Rx_ESP_Data()
    utime.sleep(2.0)
    if '+IPD' in res: # if the buffer contains IPD(a connection), then respond with HTML handshake
        id_index = res.find('+IPD')
        print("resp:")
        print(res)
        connection_id =  res[id_index+5]
        print("connectionId:" + connection_id)
        print ('! Incoming connection - sending webpage')
        uart0.write('AT+CIPSEND='+connection_id+',200'+'\r\n')  #Send a HTTP response then a webpage as bytes the 108 is the amount of bytes you are sending, change this if you change the data sent below
        utime.sleep(1.0)
        uart0.write('HTTP/1.1 200 OK'+'\r\n')
        uart0.write('Content-Type: text/html'+'\r\n')
        uart0.write('Connection: close'+'\r\n')
        uart0.write(''+'\r\n')
        uart0.write('<!DOCTYPE HTML>'+'\r\n')
        uart0.write('<html>'+'\r\n')
        uart0.write('<body><center><h1>Raspberry Pi Pico Web Server</h1></center>'+'\r\n')
        uart0.write('</body></html>'+'\r\n')
        utime.sleep(4.0)
        Send_AT_Cmd('AT+CIPCLOSE='+ connection_id+'\r\n') # once file sent, close connection
        utime.sleep(2.0)
        recv_buf="" #reset buffer
        print ('Waiting For connection...')

 

Como funciona o Código?

Começaremos importando o módulo máquina e o módulo uos. Em seguida, também importaremos o módulo utime para incorporar atrasos.

import uos
import machine
import utime

Em seguida, imprimiremos as informações sobre nosso sistema operacional atual no terminal Thonny shell. Vamos uos.uname() e imprimir a versão e lançamento do sistema operacional.

print()
print("Machine: \t" + uos.uname()[4])
print("MicroPython: \t" + uos.uname()[3])

Em seguida, criaremos um objeto uart usando UART() e especificaremos o canal UART como o primeiro parâmetro e a taxa de transmissão como o segundo parâmetro. Estamos usando UART0 neste caso com baud rate 115200 para a comunicação uart. O ESP8266 tem uma taxa de transmissão padrão de 115200, portanto, usaremos a mesma taxa de transmissão aqui para a comunicação UART do Raspberry Pi Pico para criar a sincronização. Além disso, também imprimiremos os detalhes do UART no terminal do shell.

uart0 = machine.UART(0, baudrate=115200)
print(uart0)

Esta função Connect_WiFi() é usada para conectar o ESP8266 com WiFi.

def Connect_WiFi(cmd, uart=uart0, timeout=3000):
    print("CMD: " + cmd)
    uart.write(cmd)
    utime.sleep(7.0)
    Wait_ESP_Rsp(uart, timeout)
    print()

A seguir, definiremos três funções. O primeiro é Rx_ESP_Data(). Isso lê os dados seriais que estão sendo recebidos. Esses dados são decodificados do formato UTF-8 e retornados.

def Rx_ESP_Data():
    recv=bytes()
    while uart0.any()>0:
        recv+=uart0.read(1)
    res=recv.decode('utf-8')
    return res

A segunda função é Send_AT_Cmd(cmd, uart=uart0, timeout=3000). Leva em três parâmetros, o comando AT, o canal UART e o tempo de resposta. Esta função será utilizada para enviar um comando AT para o ESP8266 via uart0. O tempo de resposta é definido para 3 segundos.

def Send_AT_Cmd(cmd, uart=uart0, timeout=3000):
    print("CMD: " + cmd)
    uart.write(cmd)
    Wait_ESP_Rsp(uart, timeout)
    print()

A função Wait_ESP_Rsp(uart=uart0, timeout=3000) aguarda 3 segundos para obter a resposta do ESP8266. Após receber os dados do ESP8266 ele concatena os bytes recebidos e os imprime no terminal shell.

def Wait_ESP_Rsp(uart=uart0, timeout=3000):
    prvMills = utime.ticks_ms()
    resp = b""
    while (utime.ticks_ms()-prvMills)<timeout:
        if uart.any():
            resp = b"".join([resp, uart.read(1)])
    print("resp:")
    try:
        print(resp.decode())
    except UnicodeError:
        print(resp)

Comandos AT

Agora vamos ver a série de comandos AT que enviaremos através do UART0 para o ESP8266.

Send_AT_Cmd('AT\r\n')          #Test AT startup
Send_AT_Cmd('AT+GMR\r\n')      #Check version information
Send_AT_Cmd('AT+CIPSERVER=0\r\n')   
Send_AT_Cmd('AT+RST\r\n')      #Check version information
Send_AT_Cmd('AT+RESTORE\r\n')  #Restore Factory Default Settings
Send_AT_Cmd('AT+CWMODE?\r\n')  #Query the WiFi mode
Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the WiFi mode = Station mode
Send_AT_Cmd('AT+CWMODE?\r\n')  #Query the WiFi mode again
Send_AT_Cmd('AT+CWJAP="HUAWEI-u67E","4uF77R2n"\r\n', timeout=5000) #Connect to AP
utime.sleep(3.0)
Send_AT_Cmd('AT+CIFSR\r\n')    #Obtain the Local IP Address
utime.sleep(3.0)
Send_AT_Cmd('AT+CIPMUX=1\r\n')    
utime.sleep(1.0)
Send_AT_Cmd('AT+CIPSERVER=1,80\r\n')    #Obtain the Local IP Address
utime.sleep(1.0)

AT: Este tipo de comando é usado para testar a função de inicialização do módulo WiFi. A resposta seria ok, contra este comando se tudo estiver ok.

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

AT+GMR : Este tipo de comando AT é usado para verificar a versão do comando AT e usamos a versão SDK do comando AT neste tipo de módulo WIFI.

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

AT+CIPSERVER=0: Isso configura o ESP8266 como servidor e define o modo como 0, o que significa excluir servidor (precisa seguir por reinicialização)

Send_AT_Cmd('AT+CIPSERVER=0\r\n')

AT+RST: Este tipo de comando é usado para redefinir o módulo WiFi quando estiver em condições de funcionamento. A resposta seria ok, quando resetar o módulo.

Send_AT_Cmd('AT+RST\r\n')

AT+RESTORE: Este tipo de comando é usado para restaurar as configurações de fábrica significa, quando este comando é inserido, todos os parâmetros são redefinidos automaticamente para os padrões.

Send_AT_Cmd('AT+RESTORE\r\n')  #Restore Factory Default Settings

AT+CWMODE? : Este tipo de comando é usado para consultar o modo WiFi do ESP8266.

Send_AT_Cmd('AT+CWMODE?\r\n')  #Query the WiFi mode

AT+CWMODE=1 : Isso define o modo WiFi do ESP8266 neste caso no modo estação.

Send_AT_Cmd('AT+CWMODE=1\r\n') #Set the WiFi mode = Station mode

AT+CWJAP=”SSID”,”PASSWORD”\r\n’, timeout=TIME_ms : Isso conecta o ESP8266 com um AP cujo SSID e senha são fornecidos, O tempo limite aqui é o tempo de reconexão.

Connect_WiFi('AT+CWJAP="A31-x221","1uX73A1n"\r\n', timeout=5000) #Connect to AP

AT+CIFSR: Este comando obtém o endereço IP local.

Send_AT_Cmd('AT+CIFSR\r\n')

AT+CIPMUX=1: Este comando é usado para habilitar múltiplas conexões (máximo 4)

Send_AT_Cmd('AT+CIPMUX=1\r\n')

AT+CIPSERVER=1: Este comando configura o ESP8266 como servidor.

Send_AT_Cmd('AT+CIPSERVER=1,80\r\n')

 

loop while

Dentro do loop while, vamos primeiro chamar Rx_ESP_Data() que retorna os dados que o ESP8266 recebe. Isso é salvo na variável ‘res.’ Agora, após um atraso de 2 segundos, verificaremos se o buffer contém uma conexão IPD ou não. Se isso acontecer, responda com um handshake HTML.

Imprima a resposta no terminal shell.

res =""
res=Rx_ESP_Data()
print("resp:")
print(res)

Obtenha o ID de conexão e imprima-o.

id_index = res.find('+IPD')
connection_id =  res[id_index+5]
print("connectionId:" + connection_id)

Então, usando o objeto uart no método write(), enviaremos os bytes para o UART. Primeiro, estamos escrevendo o comando AT: AT+CIPSEND=’ID’, ‘LENGTH’ Isso definirá o comprimento dos dados que serão enviados. Em seguida, após um atraso de 1 segundo, escreveremos o corpo HTML que construirá a página da web na porta serial. Depois disso, fecharemos as múltiplas conexões enquanto estamos enviando o comando AT: AT+CIPCLOSE=’ID’. Em seguida, vamos redefinir o buffer e aguardar a conexão.

print ('! Incoming connection - sending webpage')
        uart0.write('AT+CIPSEND='+connection_id+',200'+'\r\n')  #Send a HTTP response then a webpage as bytes the 108 is the amount of bytes you are sending, change this if you change the data sent below
        utime.sleep(1.0)
        uart0.write('HTTP/1.1 200 OK'+'\r\n')
        uart0.write('Content-Type: text/html'+'\r\n')
        uart0.write('Connection: close'+'\r\n')
        uart0.write(''+'\r\n')
        uart0.write('<!DOCTYPE HTML>'+'\r\n')
        uart0.write('<html>'+'\r\n')
        uart0.write('<body><center><h1>Raspberry Pi Pico Web Server</h1></center>'+'\r\n')
        uart0.write('</body></html>'+'\r\n')
        utime.sleep(4.0)
        Send_AT_Cmd('AT+CIPCLOSE='+ connection_id+'\r\n') # once file sent, close connection
        utime.sleep(2.0)
        recv_buf="" #reset buffer
        print ('Waiting For connection...')

 

Demonstração

Para testar o script MicroPython, faça o upload do arquivo main.py para sua placa e obtenha um endereço IP para acessar o servidor web:

No terminal shell do seu IDE, você poderá visualizar as seguintes mensagens:

Agora vá para o navegador web do seu sistema e pesquise com o endereço IP que foi exibido no terminal shell. A página da web será aberta.