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.