Projeto DIY IoT : construa uma plantadeira inteligente de baixo custo

Há algumas semanas resolvi comprar uma suculenta para minha mesa de escritório apenas pelos benefícios que ela pode trazer ao meio ambiente. Caso você não saiba, o cultivo de suculentas ou cactos pode beneficiá-lo de várias maneiras, pois ajudam a purificar o ar, melhorar a umidade dos espaços e adicionar oxigênio fresco ao ambiente

Depois de alguns dias com a Lana (sim, chamei de Lana 💕) na minha mesa, comecei a sentir que faltava alguma coisa. Como um criador apaixonado e IoT na Ubidots , decidi criar um " Smart Planter " para Lana usando nossas ferramentas. Depois de alguns dias de muito trabalho e muitos problemas de impressão, finalmente consegui esse resultado bacana, e estava ansiosa para compartilhar com vocês meu processo 🙆‍♀️💚:

Este projeto foi inspirado em um anterior criado por Paul a Maker 👨‍💻 (Impressão 3D, Eletrônica, Software) que venho acompanhando há meses e posso dizer que aprendi muitas dicas e truques com ele. Se você está procurando inspiração para seus projetos eletrônicos, você deve segui-lo , confie em mim.

Pessoalmente, gosto muito de encontrar minha própria inspiração acompanhando projetos de outras pessoas, de qualquer forma, sempre darei um jeito de adicionar meu próprio estilo, dar créditos e claro, compartilhar o resultado final para outras pessoas como eu obterem inspirado também. 🤓 🤓

Este post contém um passo a passo do meu projeto, bem como todos os recursos necessários para replicar a “ Plantadeira Inteligente ”.

Requisitos

Passo a passo

  1. Impressão 3D
  2. Fiação
  3. Invólucro
  4. Programando NodeMCU ESP8266
  5. Dashboard - Controle e Monitoramento
  6. Resumo

1. Impressão 3D

Minhas habilidades para modelar peças 3D são meio limitadas (estou trabalhando nisso para criar mais projetos usando a impressora 3D), mas existe uma comunidade aberta chamada Thingiverse que facilita nossa vida. É uma comunidade de design próspera para descobrir, criar e compartilhar coisas imprimíveis em 3D. Depois de ver muitos designs de plantadores, decidi imprimir o seguinte:

Clique aqui para fazer o downlink do design - coisa:2857938

Gostei muito desse design porque já era uma plantadeira IoT , e a luminária era um acessório lindo e bacana. Basicamente, este modelo se encaixou perfeitamente no que eu tinha em mente desde o início:

  • Lâmpada para controle remoto.
  • Espaço para colocar componentes eletrônicos para adicionar alguns sensores.

Porém, sabia que o espaço para a eletrónica não era suficiente para todas as funcionalidades que pretendia incluir. Para resolver isso, imprimi 2 vezes a parte de baixo:

  • Peça branca : Para colocar o NodeMCU ESP8266, sensores e fios.
  • Peça transparente : Para colocar o anel NeoPixel.

Tendo como resultado a obra-prima abaixo:

NOTA: O anel NeoPixel não é obrigatório para este projeto, foi apenas um acessório que o deixou mais bonito. Você também pode usar apenas uma peça.

2. Fiação

De acordo com o firmware fornecido neste guia, consulte o diagrama e a tabela abaixo para estabelecer uma conexão adequada entre os componentes utilizados.

3. Invólucro

Com as conexões de fios adequadas já estabelecidas, coloque todos os componentes dentro da plantadeira conforme mostrado abaixo:

Como você pode notar, coloquei o NodeMCU em uma placa de ensaio PCB com 10 cabeçalhos em ângulo reto. A ideia era estabelecer a conexão com os sensores e economizar espaço para a eletrônica. Para ser sincero, eu poderia ter feito um trabalho melhor organizando os cabos. Porém, a ideia era criar uma PCB customizada para a plantadeira, a certa altura tudo ficaria embutido. Além disso, perfurei a peça branca para cruzar os cabos do anel NeoPixel por ela. Para finalizar colei o anel NeoPixel apontando para baixo na parte inferior, depois colei a peça transparente na branca para desfocar a luz. No final tive este resultado incrível:

4. Programação NodeMCU ESP8266

1. Para poder trabalhar com a ESP8266 no Arduino IDE, você precisará instalar a plataforma ESP8266 usando o Arduino Board Manager . Se você não estiver familiarizado com a adição de uma placa com o Arduino IDE, consulte este artigo para obter orientações adicionais .

2. Com a plataforma ESP8266 instalada, selecione o dispositivo ESP8266 com o qual você está trabalhando. No caso, estamos trabalhando com um “ NodeMCU 1.0 ”. Para selecionar sua placa no Arduino IDE, selecione Ferramentas > Placa “Módulo ESP8266 Genérico” .

3. Baixe e instale a Ubidots MQTTESP8266 . Para obter uma explicação detalhada de como instalar bibliotecas usando o Arduino IDE, consulte este guia .

4. Cole o código abaixo no IDE do Arduino. Em seguida, atribua seu Ubidots TOKEN , SSID (nome WiFi ) e senha exclusivos da rede disponível.

NOTA: Lembre-se de atribuir os pinos corretos para os componentes usados ​​caso você use uma conexão diferente daquela fornecida acima

Repositório GitHub

/* RGB Smart Planter integrado ao Ubidots para monitoramento e controle. Este código funciona para: 1) Leia dois sensores: DHT11 e Umidade do Solo. 2) Publicar leituras de sensores no Ubidots . 3) Assine múltiplas variáveis ​​para controle remoto. Bibliotecas necessárias: - Ubidots ESP8266 MQTT - (https://github.com/ ubidots / ubidots -mqtt-esp) - Adafruit NeoPixel - (https://github.com/adafruit/Adafruit_NeoPixel) - DHT - (https:// github.com/adafruit/DHT-sensor-library) Feito por: Maria Hernández - IoT Developer Advocate @ Ubidots Revisão: José García - Gerente de Desenvolvimento e Suporte @ Ubidots /*************** ************************* * Incluir Bibliotecas ********************** ******************/ #incluir<Adafruit_NeoPixel.h> #incluir<stdio.h> #incluir<map> #incluir "DHT.h" #incluir " Ubidots ESPMQTT.h" /********************************** ****** * Definir Pinos ****************************************/ #define LIGHTPIN D1 // Pino digital para lâmpada Led. #define DHTPIN D5 // Pino digital para sensor DHT. #define NEOPIXELSPIN D6 // Pino digital para NeoPixel Ring. #define MOISTUREPIN A0 // Pino analógico para sensor de umidade. /**************************************** * Definir constantes ****** **********************************/ #define TOKEN "BBFF-xxxxxxxxxx" // Atribua seu TOKEN Ubidots . #define WIFINAME "xxxxxxxxxx" // Atribua seu SSID. #define WIFIPASS "xxxxxxxxxx" // Atribua sua senha WiFi. #define DEVICE "plantador" // Etiqueta do dispositivo Ubidots . #define VAR_PUB_1 "temperature" // Rótulo das variáveis Ubidots para publicação de dados. #define VAR_PUB_2 "umidade" #define VAR_PUB_3 "umidade do solo" #define VAR_PUB_4 "índice de calor" #define VAR_SUB_1 "light-1" // Rótulo das variáveis Ubidots para assinatura de dados; \ // Estas variáveis ​​devem ser criadas no Ubidots . #define VAR_SUB_2 "light-2" #define NUMPIXELS 12 // NeoPixel Ring de 12 bits // Remova o comentário do tipo que você está usando #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) typedef enum { vermelho, verde, azul, amarelo, branco, preto } NeoPixelColor; // R, G, B uint8_t myColors[][6] = {{250, 0, 0}, // Vermelho. {0, 255, 0}, // Verde. {0, 0, 255}, // Azul. {255, 255, 0}, // Amarelo. {255, 255, 255}, // Branco. {0, 0, 0}}; // Preto. const uint8_t numberOfVariables = 2; // Número de variáveis ​​para assinatura. char *variableLabels[numberOfVariables] = {VAR_SUB_1, VAR_SUB_2}; // Rótulo das variáveis ​​para assinatura. valor flutuante; // Armazena o valor recebido. int últimoValor; bool bottomLight; // sinalizador para controlar as condições da luz inferior. initTime longo não assinado; // Armazena o tempo de inicialização. const longo SECONDS_TO_RECONNECT = 180000; // Período para reconectar a conexão MQTT. // Funtor de comparação com funções de mapa. struct cmp_str { bool operador()(char const *a, char const *b) const { return strcmp(a, b) < 0; } }; //Declaração da função do mapa. typedef std::função<void()> FunctionType; typedef std::mapa<const char *, FunctionType, cmp_str> mapTopicSubscription; /**************************************** * Definir instâncias ****** **********************************/ Cliente Ubidots (TOKEN); Pixels Adafruit_NeoPixel (NUMPIXELS, NEOPIXELSPIN, NEO_GRB + NEO_KHZ800); DHT dht(DHTPIN, DHTTYPE); mapTopicSubscription ubiSubTopic; /************************************** * Funções principais ****** **********************************/ void setup() { initTime = milis(); // Salva o tempo de inicialização Serial.begin(115200); pinMode(LIGHTPIN, SAÍDA); // Declara o modo pin // Define as funções mapeadas para lidar com o evento de assinatura. ubiSubTopic[VAR_SUB_1] = &subscriptionHandler1; ubiSubTopic[VAR_SUB_2] = &subscriptionHandler2; cliente. ubidots SetBroker("industrial.api. ubidots .com"); // Define o corretor corretamente para a // conta comercial. cliente.setDebug(true); // Passa um valor bool verdadeiro ou falso para ativar mensagens de depuração. cliente.wifiConnection(WIFINAME, WIFIPASS); //Estabelece conexão WiFi. cliente.begin(retorno de chamada); dht.begin(); // Inicializa o sensor DHT. pixels.begin(); // Inicializa o Anel NeoPixel. pixels.clear(); // Defina todas as cores dos pixels como 'desligadas'. // Estabelece assinatura com variáveis ​​definidas. cliente. ubidots Assinar(DEVICE, VAR_SUB_1); cliente. ubidots Assinar(DEVICE, VAR_SUB_2); } void loop() { // Restabelece a assinatura com variáveis ​​definidas quando a conexão é perdida ou a cada 3 minutos. if (!client.connected() || abs(millis() - initTime) > SECONDS_TO_RECONNECT) { initTime = milis(); cliente.reconectar(); cliente. ubidots Assinar(DEVICE, VAR_SUB_1); cliente. ubidots Assinar(DEVICE, VAR_SUB_2); } cliente.reconectar(); // Leitura dos valores de temperatura, umidade e umidade do solo.a float humidity = dht.readHumidity(); temperatura flutuante = dht.readTemperature(); int soloMoisture = analogRead(MOISTUREPIN); // Calcula o índice de calor em Celsius (isFahreheit = false). float heatIndexC = dht.computeHeatIndex (temperatura, umidade, falso); // Verifique se alguma leitura falhou e saia mais cedo (para tentar novamente). if (isnan(umidade) || isnan(temperatura)) { Serial.println(F("Falha ao ler o sensor DHT!")); } //Controla as cores do NeoPixel com base nos valores de temperatura. if (bottomLight) { if (inRange(temperatura, 0, 16)) colorWipe(azul, 50); if (inRange(temperatura, 16, 21)) colorWipe(verde, 50); if (inRange(temperatura, 21, 26)) colorWipe(amarelo, 50); if (inRange(temperatura, 26, 40)) colorWipe(vermelho, 50); } // Adiciona variáveis ​​a serem publicadas no Ubidots . cliente.add(VAR_PUB_1, temperatura); cliente.add(VAR_PUB_2, umidade); cliente.add(VAR_PUB_3, umidade do solo); cliente.add(VAR_PUB_4,heatIndexC); //Publica todas as variáveis ​​adicionadas no dispositivo definido. cliente. Publicação ubidots (DEVICE); cliente.loop(); atraso(1000); } /************************************** * Funções de assinatura ***** ***********************************/ // Função a ser executada quando var_sub_1 alterar seu status. void subscriptionHandler1() { if (value == 1) { Serial.println("Lâmpada da plantadeira ligada."); digitalWrite(LIGHTPIN, HIGH); } else { Serial.println("Lâmpada da plantadeira desligada."); digitalWrite(LIGHTPIN,LOW); } }; // Função a ser executada quando var_sub_2 alterar seu status. void subscriptionHandler2() { if (value != lastValue) { if (value == 1) { Serial.println("Luz inferior da plantadeira acesa."); for (int i = 0; i < 3; i++) { colorWipe(vermelho, 50); colorWipe(verde, 50); colorWipe(azul, 50); }; colorWipe(branco, 200); bottomLight = verdadeiro; } else { Serial.println("Luz inferior da plantadeira desligada."); colorWipe(branco, 50); colorWipe(preto, 200); luz inferior = falso; } } últimoValor = valor; }; /************************************** *Funções Auxiliares****** **********************************/ // Retorna um int com o comprimento de um char int strLen(char *s) { int l = 0; enquanto (*s != '\0') { s++; l++; } retornar (eu); } // Retorno de chamada para lidar com assinatura void callback(char *topic, byte *payload, unsigned int length) { char *variableLabel = (char *)malloc(sizeof(char) * 30); getVariableLabelTopic(tópico, variávelLabel); // Salva o rótulo da variável. valor = btof(carga útil, comprimento); // Salva o valor da variável subscrita. executeCases(variableLabel); // Executa o manipulador de função para a // variável inscrita. grátis(variávelLabel); //Libere memória. } // Analisar o tópico recebido para extrair o rótulo da variável. void getVariableLabelTopic(char *topic, char *variableLabel) { sprintf(variableLabel, ""); for (int i = 0; i < numberOfVariables; i++) { char *resultLv = strstr(tópico, variávelLabels[i]); if (resultadoLv! = NULO) {uint8_t len ​​= strlen(resultadoLv); resultado de caractere[100]; uint8_t i = 0; for (i = 0; i < len - 3; i++) { resultado[i] = resultadoLv[i]; } resultado[i] = '\0'; snprintf(variableLabel, strLen(resultado) + 1, "%s", resultado); quebrar; } } } // Converte de um array de caracteres para um valor flutuante. float btof(byte *carga útil, comprimento int não assinado) { char *demo_ = (char *)malloc(sizeof(char) * 10); for (int i = 0; i < comprimento; i++) { demo_[i] = carga útil[i]; } retornar atof(demo_); } // Executa a respectiva "Função de Assinatura" com base no valor recebido. void executeCases(char *variableLabel) { if (ubiSubTopic.find(variableLabel) != ubiSubTopic.end()) { mapTopicSubscription::iterator i = ubiSubTopic.find(variableLabel); (i->segundo)(); } } // Preenche os pixels do anel NeoPixel um após o outro com cor. void colorWipe(NeoPixelColor color, int wait) { int r, g, b; r = minhasCores[cor][0]; g = minhasCores[cor][1]; b = minhasCores[cor][2]; for (int i = 0; i < pixels.numPixels(); i++) { pixels.setPixelColor(i, r, g, b); pixels.show(); atraso(espera); } } // Verifica se o valor recebido está no intervalo esperado bool inRange(float x, int low, int high) { return ((x - low) > 0 && (high - x) >= 0); }

5. Verifique seu código no IDE do Arduino. Para fazer isso, no canto superior esquerdo do nosso Arduino IDE você verá o ícone Check Mark selecione-o para verificar seu código.

6. Carregue o código em seu “NodeMCU 1.0” . Para fazer isso, escolha o ícone seta para a direita” marca de seleção ”.

7. Para verificar a conectividade do dispositivo e os dados enviados, abra o monitor serial selecionando o ícone " lupa " no canto superior direito do IDE do Arduino para ver os logs , bem como as respostas do Ubidots .

8. Após alguns segundos de inicialização, o código fornecido criará um novo dispositivo automaticamente em sua Ubidots . Vá para a seção de dispositivos da sua conta Ubidots ; você deverá ver novos dispositivos criados automaticamente:

Entre no dispositivo “ Plantadeira ” e veja as variáveis ​​configuradas transmitindo os dados:

9. Em seguida, crie duas novas variáveis ​​brutas para estabelecer a assinatura e controlar as luzes remotamente. Para fazer isso, clique em "Adicionar variável > Variável bruta " e atribua o rótulo da variável definido no código. Para o código de amostra fornecido, os rótulos de variáveis ​​a serem criados são "light-1" e "light-2" .

Com as variáveis ​​criadas com sucesso, você deverá ter o seguinte resultado:

5. Dashboard - Controle e Monitoramento

Com tudo já integrado, é hora de apresentar os dados dos dispositivos em um Dashboard . Além disso, o dashboard também servirá para controlar o status de ambas as lâmpadas.

1. Para criar seu primeiro dashboard , acesse o Dashboard guia (Dados → Dashboards ) . Em seguida, selecione o ícone de adição (+) no canto superior direito e selecione o tipo de widget desejado. Você deve ser capaz de criar dashboards como este abaixo:

Mais sobre Dashboards Ubidots : Branding do aplicativo: estilos personalizados para seus dashboards e widgets

Ubidots é muito intuitivo para qualquer usuário administrar seus dados, permitindo que qualquer pessoa os personalize o quanto quiser; caso você queira saber mais, recomendo conferir os seguintes guias:

2. Ubidots suporta eventos já integrados para permitir que você envie eventos, alertas e notificações com base nos dados de seus sensores e atuadores.

Confira os tipos de eventos suportados e saiba como configurar cada um deles:

  1. Notificações por e-mail
  2. Notificações por SMS
  3. Eventos de webhook – saiba mais
  4. Notificações de telegrama
  5. Notificações do Slack – saiba mais
  6. Notificações de chamadas de voz – saiba mais
  7. Notificação de volta ao normal - saiba mais
  8. Notificações de cerca geográfica - saiba mais

6. Resumo

Depois de algumas horas fazendo e codificando (e muitos cafés), dei vida a esta Smart Planter:

Como mencionei no início, fiz isso porque não queria apenas uma nova decoração de mesa, mas também porque sentia que faltava alguma coisa para a Lana, queria inventar minha própria forma de me comunicar com ela através de IoT e dados. Caso queira outras formas de se comunicar com suas plantas você pode ouvi-las usando o MIDI Sprout . Isso é legal, certo? 🤩

Este é apenas o V0 do Smart Planter e há algumas coisas que quero melhorar, como o design, organização da eletrônica com PCB customizada e integração com outros serviços como Google Assistance, Alexa e Twitter.

Espero que você tenha gostado disso assim como eu. Caso você tenha algum comentário ou dúvida sobre o projeto, fique à vontade para entrar em contato! Estou totalmente aberto a feedbacks construtivos para aprimorar este tipo de projetos e compartilhá-los com vocês. 😁💚

Projetos IoT mais úteis: