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/