Raspberry Pi Pico W
O Pico W é uma placa baseada no microntolador RP2040. Foi desenvolvida para ter um custo reduzido, flexível e com uma uma interface wireless de 2.4GHz (Wi-Fi 802.11n).
Para além da utilização independente (stand alone) podemos usar o pico w para comunicar com outros servers. Pode-se, assim, controlar e obter dados através de webserver central que pode ser um raspberry pi 3 ou superior, ou outro qualquer webserver.
Neste exemplo, vamos considerar o PI 3B o "main server" que lê os dados dos vários pico w "Sub Server".
Basicamente, cada pico w tem um webserver num dos IPs da rede, gera uma página de web. Por sua vez, o "main server" lê os dados apresentados em determinada "div" produzida no html da página.
Ler temperatura de vários PICO W
Primeiro vamos instalar um webserver em cada pico W, ligar à rede Wi-Fi existente, atribuir um IP ao pico W. Antes o pico W deve ter a lib picozero instalada
import network import socket from time import sleep from picozero import pico_temp_sensor, pico_led import machine ssid = 'Service Name' password = 'password' def connect(): #Connect to WLAN wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) wlan.ifconfig(('192.168.1.50', '255.255.255.0', '192.168.1.254', '8.8.8.8')) while wlan.isconnected() == False: print('Waiting for connection...') sleep(1) ip = wlan.ifconfig()[0] print(f'Connected on {ip}') return ip def open_socket(ip): # Open a socket address = (ip,80) connection = socket.socket() connection.bind(address) connection.listen(1) return connection
Já temos a conetividade com a rede wireless local. Vamos criar a nossa págian de web, neste casos vamos usar o sensor de temperatura interno da board, ligar e desligar o led da board, usar um sensor de temperatura mais preciso o DS18B20 e controlar um LED ligado a uma das saídas (que podemos usar para ligar qualquer outra coisa).
def webpage(temperature, state, tmpds): #Template HTML html = f""" <!DOCTYPE html> <html> <!-- A form permite ligar e desligar
o led da board e o led externo --> <form action="./lighton"> <input type="submit" value="Light on" /> </form> <form action="./lightoff"> <input type="submit" value="Light off" /> </form> <form action="./ledon"> <input type="submit" value="ledon" /> </form> <form action="./ledoff"> <input type="submit" value="ledoff" /> </form> <!-- Estado do Led externo ON ou OFF --> <p>LED is {state}</p> <!-- Sensor de temperatura interno da board --> <p> Internal Temp is <div class="temp" id="temp">{temperature}</div> </p> <!-- Sensor de temperatura externo DS18B20 --> <p> External Temp <div class="tmpds" id="tmpds">{tmpds}</div> </p> </body> </html> """ return str(html)
Ler a temperatura do sensor externo DS18B20 no PIN 28 e gravar numa variável "tmpds";
import machine, onewire, ds18x20, time ds_pin = machine.Pin(28) ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin)) roms = ds_sensor.scan() //se quisermos testar se o sensor é encontrado removert # #print('Found DS devices: ', roms) ds_sensor.convert_temp() tmpds = ds_sensor.read_temp(roms[0])
Ler temperatura do sensor na board, ligar o webserver
def serve(connection): #Start a web server state = 'OFF' pico_led.off() temperature = 0 while True: client = connection.accept()[0] request = client.recv(1024) request = str(request) try: request = request.split()[1] except IndexError: pass if request == '/lighton?': pico_led.on() state = 'ON' elif request =='/lightoff?': pico_led.off() state = 'OFF' elif request =='/ledon?': leda=Pin(13,Pin.OUT) leda.on() state = 'on' elif request =='/ledoff?': leda=Pin(13,Pin.OUT) leda.off() state = 'off' temperature = pico_temp_sensor.temp html = webpage(temperature, state, tmpds) client.send(html) client.close() try: ip = connect() connection = open_socket(ip) serve(connection) except KeyboardInterrupt: machine.reset()
Agora já temos o nosso webserver que podemos aceder através do ip 192.168.1.50
Mostra-nos a temperatura, podemos desligar e ligar o led da board ou o led externo. Podemos inserir o código em várias boards, todas com um ip único, este exemplo será o que termina em 50, por exemplo vamos usar o mesmo código mas com o ip a terminar em 51 (192.168.1.51)
Como obter estes dados no mainserver
Neste exemplo usou-se php, mas podem ser usadas outras linguagens de programação
a base do código é ler cada um das placas assim, vamos criar uma função que nos permitirá ler cada uma delasCriamos um ficheiro php, por exemplo, lerdados.php
<? php function sckd ($ip,$divname){ $s=socket_create(AF_INET,SOCK_STREAM,SOL_TCP); socket_connect($s,$ip,80); socket_send($s,"GET / HTTP/1.1\r\nHost: xx.fakedomain.com\r\n\r\n",1000,0); socket_recv($s, $buf, 1000000,0); socket_close($s); if (!empty ($buf)){ $doc = new DOMDocument; $doc->loadHTML($buf); $xpath = new DOMXPath($doc); $node = $xpath->query("//div[@id='".$divname."']")->item(0); $extemp = trim($node->nodeValue); return $extemp; } else { echo ""; } } ?>
Agora podemos obter os dados de cada uma das board usando ip e a div name, divname é o nome da div onde estão os dados que pretendemos. Criamos um ficheiro rpi.php
<? php include 'lerdados.php'; /* Obter dados na div tmpds na board no ip 50 */ $c=round(sckd('192.168.1.50','tmpds'),2); echo " Temp DS: ".$c." ºC"; /* Obter dados na div temperature na board no ip 50 */ $d=round(sckd('192.168.1.50','temperature'),2); echo " Temp interna da board: ".$d." ºC"; /* Obter dados na div temperature na board no ip 51 */ $e=round(sckd('192.168.1.51','temperature'),2); echo " Temp interna da board: ".$d." ºC"; ?>
Podemos obter qualquer dado que o webserver da board ou várias boards coloquem no interior de uma html div. Se o led está ligado, desligado etc etc
Aqui fica a imagem com o teste do código e hardware necessário neste exemplo
Nota: Neste exemplo foi usada a porta 80, a porta standard para o browser em http1.1, porém, pode ser usada qualquer outra porta o que, por questões de segurança, é conveniente. Neste exemplo não foram usadas nenhumas medidas para limitar o acesso, assim, qualquer browser pode aceder sem limitações ao controlo.