Neste mês houve um grande evento chamado The Melee – Side by side (muito obrigado a @ojoven e @diversius).
O evento foi um tipo de hackathon onde um grupo de pessoas se reuniu um dia para compartilhar projetos paralelos e para trabalhar juntas (também houve um almoço e cervejas). O formato do evento é apenas uma cópia do evento que nossos colegas de Bilbao chamaram de “El Comité”.
@ibaiimaz falou sobre um projeto para criar um pomodoro colaborativo, no qual as pessoas de uma equipe poderiam compartilhar seu status e verem o status do restante da equipe. Quando ouvi pomodoro e status, imediatamente pensei em um servo movendo uma flag e alguns LEDs ligando e desligando. Nós tivemos um projeto. @penniath e @tatai também se juntaram a nós. Nós também tínhamos uma equipe.
Nós tínhamos um projeto e também um prazo. Tivemos que mostrar um protótipo funcional no final do dia. Isso significa que não tivemos muito tempo. Primeiro, decidimos a maquete do projeto, reduzindo o escopo inicial (mais ambicioso) para encaixá-lo em nosso horário. Discutimos intensamente por 10 minutos e, finalmente, descrevemos um projeto ultradetalhado. Este era o plano completo do projeto:

Era hora de começar a trabalhar.
@penniath e @tatai trabalharam no backend. Ele deve ser o responsável pelos timers pomodoro, ouvir eventos MQTT e criar uma API para o frontend. O backend também deve fornecer uma interface WebSockets para permitir eventos em tempo real dentro do frontend. Eles decidiram usar node e socket.io para os WebSockets. Você pode ver o código-fonte aqui.
@ibaiimaz começou com o frontend. Ele decidiu criar um aplicativo web em Angular para ouvir eventos socket.io para mostrar o status do pomodoro. Você pode ver o código-fonte aqui.
Finalmente trabalhei com o hardware. Eu criei um protótipo com um ESP32, dois LEDs RGB, um botão, um servo e um par de resistores.


Aqui está o código-fonte:
#include <WiFi.h>
#include <PubSubClient.h>
int redPin_g = 19;
int greenPin_g = 17;
int bluePin_g = 18;
int redPin_i = 21;
int greenPin_i = 2;
int bluePin_i = 4;
#define SERVO_PIN 16
const int buttonPin = 15;
int buttonState = 0;
int channel = 1;
int hz = 50;
int depth = 16;
const char* ssid = "SSID";
const char* password = "password";
const char* server = "192.168.1.105";
const char* topic = "/pomodoro/+";
const char* clientName = "com.gonzalo123.esp32";
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void wifiConnect() {
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print("*");
}
Serial.print("WiFi connected: ");
Serial.println(WiFi.localIP());
}
void mqttReConnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
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 callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
String data;
for (int i = 0; i < length; i++) {
data += (char)payload[i];
}
int value = data.toInt();
if (strcmp(topic, "/pomodoro/gonzalo") == 0) {
Serial.print("[gonzalo]");
switch (value) {
case 1:
ledcWrite(1, 3400);
setColor_g(0, 255, 0);
break;
case 2:
setColor_g(255, 0, 0);
break;
case 3:
ledcWrite(1, 6400);
setColor_g(0, 0, 255);
break;
}
} else {
Serial.print("[ibai]");
switch (value) {
case 1:
setColor_i(0, 255, 0);
break;
case 2:
setColor_i(255, 0, 0);
break;
case 3:
setColor_i(0, 0, 255); // green
break;
}
}
Serial.print("] value:");
Serial.println(data);
}
void setup()
{
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(redPin_g, OUTPUT);
pinMode(greenPin_g, OUTPUT);
pinMode(bluePin_g, OUTPUT);
pinMode(redPin_i, OUTPUT);
pinMode(greenPin_i, OUTPUT);
pinMode(bluePin_i, OUTPUT);
ledcSetup(channel, hz, depth);
ledcAttachPin(SERVO_PIN, channel);
wifiConnect();
client.setServer(server, 1883);
client.setCallback(callback);
delay(1500);
}
void mqttEmit(String topic, String value)
{
client.publish((char*) topic.c_str(), (char*) value.c_str());
}
void loop()
{
if (!client.connected()) {
mqttReConnect();
}
client.loop();
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
mqttEmit("/start/gonzalo", (String) "3");
}
delay(200);
}
void setColor_i(int red, int green, int blue)
{
digitalWrite(redPin_i, red);
digitalWrite(greenPin_i, green);
digitalWrite(bluePin_i, blue);
}
void setColor_g(int red, int green, int blue)
{
digitalWrite(redPin_g, red);
digitalWrite(greenPin_g, green);
digitalWrite(bluePin_g, blue);
}
O servidor MQTT (um servidor mosquitto) estava rodando inicialmente no meu laptop, mas como eu também tinha um Raspberry Pi Zero na minha bolsa, decidimos usar o Pi Zero como um servidor e rodar o servidor mosquitto MQTT com o Raspbian. Tudo é melhor com um Raspberry Pi. @tatai me ajudou a configurar o servidor.
Aqui você pode ver o protótipo em ação:
Esse é o tipo de projeto paralelo que eu normalmente crio sozinho, mas definitivamente é mais divertido fazer isso com outros colegas, mesmo que eu precise acordar cedo em uma manhã de sábado.
- Código-fonte do ESP32 aqui.
***
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/2018/03/26/pomodoro-with-esp32-one-the-melee-side-by-side-project/




