Desenvolvimento

7 jul, 2017

Brincando com Raspberry Pi, Arduino, NodeMcu e MQTT

Publicidade

 

Eu tenho me divertido bastante fazendo coisas para Internet of Things (IoT). Hoje, eu quero usar o protocolo MQTT para fazer a comunicação entre diferentes dispositivos. Primeiro, eu criei um broker mqtt no meu laptop. Para testar, eu vou usar o servidor mosquitto. Na produção, podemos usar RabbitMQ ou mesmo um servidor de terceiros, como iot.eclipse.org ou mesmo o serviço de IoT da Amazon.

A ideia é emitir um valor com um dispositivo e ouvir esse valor com o resto dos dispositivos, e executar uma ação dependendo desse valor. Por exemplo, vou usar um potenciômetro conectado ao microcontrolador NodeMcu.

Esse controlador se conectará ao broker mqtt e emitirá o valor do potenciômetro (lendo a entrada analógica) em um tópico (chamado “potenciômetro”). Podemos programar nosso NodeMcu com Lua, mas fico mais confortável com C++ e Arduino IDE. Primeiro, eu preciso me conectar à minha rede Wi-fi, depois me conectar ao broker e começar a emitir os valores do potenciômetro.

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
 
// Wifi configuration
const char* ssid = "MY_WIFI_SSID";
const char* password = "my_wifi_password";
 
// mqtt configuration
const char* server = "192.168.1.104";
const char* topic = "potentiometer";
const char* clientName = "com.gonzalo123.nodemcu";
 
int value;
int percent;
String payload;
 
WiFiClient wifiClient;
PubSubClient client(wifiClient);
 
void wifiConnect() {
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
 
  if (client.connect(clientName)) {
    Serial.print("Connected to MQTT broker at ");
    Serial.print(server);
    Serial.print(" as ");
    Serial.println(clientName);
    Serial.print("Topic is: ");
    Serial.println(topic);
  }
  else {
    Serial.println("MQTT connect failed");
    Serial.println("Will reset and try again...");
    abort();
  }
}
 
void mqttReConnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      client.subscribe(topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
 
void setup() {
  Serial.begin(9600);
  client.setServer(server, 1883);
  wifiConnect();
  delay(10);
}
 
void loop() {
  value = analogRead(A0);
  percent = (int) ((value * 100) / 1010);
  payload = (String) percent;
  if (client.connected()) {
    if (client.publish(topic, (char*) payload.c_str())) {
      Serial.print("Publish ok (");
      Serial.print(payload);
      Serial.println(")");
    } else {
      Serial.println("Publish failed");
    }
  } else {
    mqttReConnect();
  }
 
  delay(200);
}

 

Agora, vamos usar outro Arduíno (com um escudo ethernet).

Vamos mover um servomotor de acordo com o valor do potenciômetro NodeMcu. Esse Arduino só precisa fazer um listen do tópico do MQTT e mover o servo.

#include <SPI.h>
#include <Servo.h>
#include <Ethernet.h>
#include <PubSubClient.h>
 
#define SERVO_CONTROL 9
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 
Servo servo;
EthernetClient ethClient;
 
// mqtt configuration
const char* server = "192.168.1.104";
const char* topic = "potentiometer";
const char* clientName = "com.gonzalo123.arduino";
 
PubSubClient client(ethClient);
 
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] angle:");
 
  String data;
  for (int i = 0; i < length; i++) {
    data += (char)payload[i];
  }
 
  double angle = ((data.toInt() * 180) / 100);
  constrain(angle, 0, 180);
  servo.write((int) angle);
  Serial.println((int) angle);
}
 
void mqttReConnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect(clientName)) {
      Serial.println("connected");
      client.subscribe(topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}
 
void setup()
{
  Serial.begin(9600);
  client.setServer(server, 1883);
  client.setCallback(callback);
  servo.attach(SERVO_CONTROL);
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
  }
 
  delay(1500); // Allow the hardware to sort itself out
}
 
void loop()
{
  if (!client.connected()) {
    mqttReConnect();
  }
  client.loop();
}

Finalmente, usaremos um Raspberry Pi com um Sense Hat e exibiremos com sua matriz de led diferentes cores e pontos, dependendo do valor do NodeMcu. Da mesma forma que o script Arduino, aqui só precisamos fazer um listen do tópico do broker e executar as ações com o Sense Hat. Agora com Python:

import paho.mqtt.client as mqtt
from sense_hat import SenseHat
 
sense = SenseHat()
sense.clear()
mqttServer = "192.168.1.104"
 
red = [255, 0, 0]
green = [0, 255, 0]
yellow = [255, 255, 0]
black = [0, 0, 0]
 
def on_connect(client, userdata, rc):
    print("Connected!")
    client.subscribe("potentiometer")
 
def on_message(client, userdata, msg):
    value = (64 * int(msg.payload)) / 100
    O = black
    if value < 21:
        X = red
    elif value < 42:
        X = yellow
    else:
        X = green
 
    sense.set_pixels(([X] * value) + ([O] * (64 - value)))
 
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
 
client.connect(mqttServer, 1883, 60)
client.loop_forever()

O hardware:

  • 1 Arduino Uno
  • 1 NodeMCU (V3)
  • 1 potenciômetro
  • 1 Servo (SG90)
  • 1 Raspberry Pi 3 (com um Sense Hat)

O código-fonte está disponível no meu GitHub.

***

Gonzalo Ayuso faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://gonzalo123.com/2017/06/26/playing-with-raspberry-pi-arduino-nodemcu-and-mqtt/