IoT com Python e Raspberry Pi: criando protótipos físicos

1. Fundamentos do Ecossistema IoT com Raspberry Pi

O Raspberry Pi revolucionou a prototipagem IoT ao oferecer um computador completo do tamanho de um cartão de crédito. Modelos como Raspberry Pi 4 e 5 oferecem GPIO de 40 pinos, Wi-Fi, Bluetooth e processamento suficiente para executar Python e bibliotecas de hardware simultaneamente. A plataforma permite conectar sensores, atuadores e módulos de comunicação, formando a base de protótipos físicos funcionais.

No contexto embarcado, Python se destaca pela simplicidade e pelas bibliotecas especializadas:

  • RPi.GPIO: controle direto dos pinos GPIO
  • gpiozero: abstração de alto nível para sensores e atuadores
  • smbus: comunicação I2C com dispositivos externos
  • spidev: interface SPI para conversores ADC e sensores rápidos

A arquitetura típica de um protótipo IoT segue o fluxo: sensores capturam dados do ambiente → processamento local no Raspberry Pi → atuadores executam ações físicas → conectividade envia informações para a nuvem ou rede local.

2. Configuração do Ambiente de Desenvolvimento

Para começar, instale o Raspberry Pi OS Lite (sem ambiente gráfico) para maior desempenho e menor consumo. Após a instalação inicial, habilite as interfaces de hardware:

sudo raspi-config
# Navegue para: Interface Options → I2C, SPI, GPIO → Enable

Crie um ambiente Python virtual isolado para cada projeto:

python -m venv iot_env
source iot_env/bin/activate
pip install RPi.GPIO gpiozero smbus2 paho-mqtt flask

Este ambiente mantém as dependências organizadas e evita conflitos entre projetos.

3. Leitura de Sensores com Python

Sensor de presença PIR (digital)

from gpiozero import MotionSensor
import time

pir = MotionSensor(17)
while True:
    if pir.motion_detected:
        print("Movimento detectado!")
    time.sleep(0.5)

Sensor analógico com MCP3008 (SPI)

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 1350000

def ler_adc(canal):
    r = spi.xfer2([1, (8 + canal) << 4, 0])
    return ((r[1] & 3) << 8) + r[2]

while True:
    valor = ler_adc(0)
    tensao = (valor / 1023.0) * 3.3
    print(f"Tensão no pino 0: {tensao:.2f}V")
    time.sleep(1)

Sensor BME280 (I2C) - temperatura, umidade e pressão

import smbus2
import bme280

bus = smbus2.SMBus(1)
address = 0x76
calib_params = bme280.load_calibration_params(bus, address)

def ler_bme280():
    data = bme280.sample(bus, address, calib_params)
    return data.temperature, data.humidity, data.pressure

temp, hum, press = ler_bme280()
print(f"Temp: {temp:.1f}°C | Umidade: {hum:.1f}% | Pressão: {press:.1f}hPa")

4. Controle de Atuadores e Saídas

Acionamento de LED com proteção

from gpiozero import LED
from time import sleep

led = LED(18)
while True:
    led.on()
    sleep(1)
    led.off()
    sleep(1)

Servomotor com PWM preciso (pigpio)

import pigpio
import time

pi = pigpio.pi()
servo_pin = 12
pi.set_servo_pulsewidth(servo_pin, 1500)  # posição central
time.sleep(1)
pi.set_servo_pulsewidth(servo_pin, 1000)  # 0 graus
time.sleep(1)
pi.set_servo_pulsewidth(servo_pin, 2000)  # 180 graus
pi.stop()

Display LCD I2C 16x2

from RPLCD.i2c import CharLCD
import time

lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=16, rows=2)
lcd.write_string("IoT com Python")
lcd.cursor_pos = (1, 0)
lcd.write_string("Raspberry Pi")
time.sleep(5)
lcd.clear()

5. Comunicação e Conectividade IoT

MQTT com Mosquitto e paho-mqtt

import paho.mqtt.client as mqtt
import json

def on_connect(client, userdata, flags, rc):
    print("Conectado ao broker MQTT")

client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.hivemq.com", 1883, 60)

# Publicar dados de sensores
dados = {"temperatura": 25.3, "umidade": 68.2}
client.publish("casa/sensor/temperatura", json.dumps(dados))
client.loop_forever()

API REST com Flask

from flask import Flask, jsonify
import bme280

app = Flask(__name__)

@app.route('/api/sensores')
def sensores():
    temp, hum, press = ler_bme280()
    return jsonify({
        "temperatura": round(temp, 1),
        "umidade": round(hum, 1),
        "pressao": round(press, 1)
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

6. Tratamento de Eventos e Automação

Interrupção GPIO com callback

from gpiozero import Button
from signal import pause

def botao_pressionado():
    print("Botão pressionado! Executando ação...")

botao = Button(2, pull_up=True)
botao.when_pressed = botao_pressionado
pause()

Agendamento de tarefas com schedule

import schedule
import time

def coletar_dados():
    temp, hum, press = ler_bme280()
    print(f"Coleta automática: {temp}°C, {hum}%")

schedule.every(10).minutes.do(coletar_dados)

while True:
    schedule.run_pending()
    time.sleep(1)

7. Depuração, Logging e Boas Práticas

Use logs estruturados para monitorar o sistema:

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[logging.FileHandler('iot.log'), logging.StreamHandler()]
)
logger = logging.getLogger('IoT_Prototype')

logger.info("Sistema iniciado com sucesso")

Proteção de circuitos: sempre use resistores de pull-up/pull-down em entradas flutuantes, diodos flyback em motores e drivers de potência para cargas indutivas. Organize o código em módulos separados (sensores.py, atuadores.py, comunicacao.py) para reutilização.

8. Estudo de Caso: Estação Meteorológica IoT Completa

import bme280
import smbus2
import paho.mqtt.client as mqtt
from gpiozero import LED
from RPLCD.i2c import CharLCD
import time
import json
import logging

logging.basicConfig(level=logging.INFO)

# Configuração dos componentes
bus = smbus2.SMBus(1)
address = 0x76
calib_params = bme280.load_calibration_params(bus, address)
lcd = CharLCD(i2c_expander='PCF8574', address=0x27, port=1, cols=16, rows=2)
led_indicador = LED(18)

# Configuração MQTT
client = mqtt.Client()
client.connect("broker.hivemq.com", 1883, 60)

def ler_sensor():
    try:
        data = bme280.sample(bus, address, calib_params)
        return data.temperature, data.humidity, data.pressure
    except Exception as e:
        logging.error(f"Erro no sensor: {e}")
        return None, None, None

def atualizar_lcd(temp, hum, press):
    lcd.clear()
    lcd.write_string(f"Temp: {temp:.1f}C")
    lcd.cursor_pos = (1, 0)
    lcd.write_string(f"Umid: {hum:.1f}%")

def enviar_mqtt(temp, hum, press):
    dados = {"temperatura": round(temp, 1), "umidade": round(hum, 1), "pressao": round(press, 1)}
    try:
        client.publish("estacao/dados", json.dumps(dados))
        logging.info("Dados enviados via MQTT")
    except Exception as e:
        logging.error(f"Falha MQTT: {e}")

def main():
    logging.info("Estação meteorológica iniciada")
    while True:
        temp, hum, press = ler_sensor()
        if temp is not None:
            atualizar_lcd(temp, hum, press)
            enviar_mqtt(temp, hum, press)
            led_indicador.blink(on_time=0.5, off_time=0.5, n=3)
        time.sleep(60)

if __name__ == "__main__":
    main()

Expansões possíveis: adicionar bateria LiPo com carregador, implementar modo sleep para economia de energia, armazenar dados localmente em SQLite para análise offline.


Referências