Vaso inteligente e automático.
Irriga sozinho, enxerga se há planta na frente e se controla pelo celular — sem
internet, sem computador, só com o roteador do próprio celular.
Ensaio de campo de 21/09/2026, só com o celular — nenhum PC na conta:
| Situação | |
|---|---|
✅ App no celular pela rede própria do vaso (farmio-01 → 192.168.4.1) |
funcionou |
| ✅ App no celular pelo roteador do celular | funcionou |
| ✅ Foto pedida no app, da câmera até a tela, pelo fio | funcionou; 58 de 58 em bancada, com retransmissão |
| ✅ Sensores de ar e solo na página | leitura viva; terra seca lida como seca |
| ✅ Alerta de solo seco e tanque vazio | na faixa vermelha do topo |
| ⏳ Umidade do solo | calibração parcial: ponto seco medido, molhado ainda é chute (calibração) |
| ⏳ Bomba girando | não ensaiada: o tanque ainda está vazio |
| não calibrada — já deu falso positivo com foto real, e a página avisa (docs/05) |
Este é um projeto do laboratório Jaspy, que guarda o método, as ferramentas e a documentação comum. Cada projeto tem repositório próprio; este é o do FarmIO.
- lê temperatura e umidade do ar (DHT22), umidade do solo e nível do tanque;
- irriga em pulsos quando o solo fica extremamente seco, e para na hora se o tanque esvaziar ou o solo encharcar;
- classifica o solo em cinco faixas em vez de um limiar único — limiar único faz a bomba oscilar em torno do ponto de corte;
- reconhece se há uma planta na frente da câmera, por textura e não por cor — é o que impede um balde verde de passar por planta;
- conhece o próprio orçamento de corrente e ajusta o brilho do anel ao que a porta USB aguenta, em vez de descobrir o limite reiniciando;
- alerta em três canais: tela, anel de LED e página web;
- tira uma foto quando o app pede — pelo fio, sem a câmera precisar de rede;
- liga e desliga a bomba por um botão no app, sem mexer na lógica automática e sem passar por cima da proteção contra bomba a seco;
- funciona em campo aberto só com um celular: tem rede própria sempre no ar, e entra no roteador do celular quando ele estiver ligado.
| Papel | Placa | O que roda nela |
|---|---|---|
| O vaso | ESP32-C3 (4 MB, USB nativo) | sensores, bomba, tela, anel, página |
| O olho | XIAO ESP32-S3 Sense (OV3660, 8 MB PSRAM) | captura, classificação, foto |
Elas conversam por UART, não por Wi-Fi — as razões estão em 04-enlace-c3-cam.md. Pelo fio passam o veredito, a cada 10 s, e a foto, quando o app pede. A câmera não tem rádio ligado: o celular só conversa com o vaso.
| Item | Componente |
|---|---|
| Ar | DHT22 |
| Solo | sensor capacitivo de umidade |
| Tanque | sensor de nível tipo pente (Funduino) |
| Tela | OLED SSD1306 128×64, I²C |
| Luz | anel de 16 LEDs WS2812 (5050) |
| Bomba | RS-385 em 7–9 V, fonte própria, via ponte H dupla mini — um pino |
Pinagem completa, alimentação e as armadilhas de ADC e strapping estão em
docs/02-hardware-e-pinagem.md.
pio run # compila o vaso e a câmera
pio run -e c3 -t upload # grava o vaso (USB nativo)
pio run -e cam -t upload # grava a câmera XIAO (USB-C dela)
pio run -e autoteste -t upload # treina e mede, sem nada ligado na placa
pio run -e ensaio -t upload # le so o DHT22 e o nivel, sem mais nada
pio run -e bancada -t upload # o vaso com log detalhado, para calibrar
pio device monitor -e c3| Ambiente | Placa | Para que serve |
|---|---|---|
c3 |
ESP32-C3 | o vaso |
cam |
XIAO ESP32-S3 Sense | a câmera |
cam-aithinker |
ESP32-CAM | a câmera da v0.2, mantida compilando |
autoteste |
ESP32-C3 | exercita o enlace e treina o classificador na placa |
ensaio |
ESP32-C3 | bring-up de sensor, um subsistema por vez |
bancada |
ESP32-C3 | o vaso com log detalhado |
esp32dev |
DevKit V1 | a placa da v0.1, mantida compilando |
Credencial de Wi-Fi é opcional para compilar:
Copy-Item include\secrets.example.h include\secrets.h # e preencherSem secrets.h o firmware compila e roda — só com a rede própria. É isso que
permite o CI compilar sem nenhuma senha. A detecção de planta e a foto não
dependem de rede nenhuma: elas vivem no fio.
| Caminho | Como | Endereço |
|---|---|---|
| rede do vaso — sempre funciona | desligar o roteador do celular e entrar no Wi-Fi farmio-01 |
http://192.168.4.1 |
| roteador do celular | ligar o roteador do celular; o vaso entra sozinho em até ~1 min | http://farmio-01.local, ou o IP de farmio-01 na lista de aparelhos conectados do roteador |
O roteador do celular precisa estar em 2,4 GHz e WPA2 — as placas não enxergam 5 GHz, e o erro que aparece é "rede não encontrada", não "senha errada".
O IP muda. Cada vez que o roteador do celular é religado, o vaso pode ganhar outro
endereço. Não adianta anotar o da última vez. Se farmio-01.local não abrir no
celular — nem todo Android resolve .local —, o caminho que nunca falha é a rede
própria: desligar o roteador, entrar em farmio-01 e abrir 192.168.4.1. O Android
avisa que a rede "não tem internet"; é para continuar conectado assim mesmo.
Os dois caminhos foram ensaiados no celular em 21/09/2026, com o vaso ligado fora do PC. Antes disso, com o roteador emulado, a página respondeu em ~50 ms, a foto chegou em ~1,7 s e o vaso reentrou no roteador 17 s depois de ele voltar — ver o diário.
Compilação de 21/09/2026:
| Ambiente | RAM | Flash |
|---|---|---|
c3 (vaso) |
17,4% — 57,0 kB de 320 kB | 68,2% — 894 kB de 1,31 MB |
cam (câmera) |
13,4% — 43,9 kB de 320 kB | 11,5% — 360 kB de 3,15 MB |
A câmera encolheu 114 kB em 21/09: é a pilha de Wi-Fi que saiu junto com o vídeo.
FarmIO/
├── platformio.ini sete ambientes, bibliotecas fixadas, build flags
├── include/
│ ├── config.h pinagem, limiares, orçamento ← só isso muda ao trocar de placa
│ ├── sensores.h DHT22, solo, tanque, filtro de mediana
│ ├── bomba.h acionamento e intertravamentos
│ ├── camera.h o lado vaso do enlace, e a escada de recuperação
│ ├── energia.h orçamento de corrente e teto de brilho
│ ├── anel.h anel WS2812, animações não bloqueantes
│ ├── tela.h OLED, tela inicial e tela de risco
│ ├── web.h o app: página, JSON, foto e botão da bomba
│ ├── telemetria.h o painel legível da serial, e os comandos de bancada
│ └── cenas.h gerador de cenas sintéticas (só no autoteste)
├── lib/
│ ├── farmio_enlace/ protocolo de quadros — C++11 puro, os dois lados do fio
│ └── farmio_visao/ dez características + regressão logística em ponto fixo
│ └── pesos.cpp o modelo: onze números, gerados pelo autoteste
├── src/
│ ├── main.cpp o vaso
│ ├── main_cam.cpp a câmera
│ ├── main_autoteste.cpp treino e medição na placa
│ └── cenas.cpp desenho das cenas sintéticas
├── scripts/
│ └── calibra_solo.py só aceita a leitura do solo depois de ela estabilizar
├── docs/ herança, hardware, lógica, enlace, visão, energia
│ └── img/ fotos do vaso e do app
└── diario.md previsto × medido, a cada iteração
- Herança do SmartFarm — de onde o projeto veio, a especificação original preservada e o que mudou
- Hardware e pinagem — ligação, ADC, strapping, os treze pinos do C3 e o roteiro de calibração
- Lógica de operação — faixas, intertravamentos, riscos, telas e anel
- Enlace vaso ↔ câmera — por que fio e não Wi-Fi, formato do quadro, retransmissão da foto, diagnóstico do fio
- Visão: tem planta na frente? — as dez características, o treino na placa e as quatro iterações até o modelo atual
- O projeto inteiro numa porta USB — o orçamento de corrente, o que cabe e o que não cabe
- Diário — cada iteração com previsto ao lado de medido
- Pôr água no tanque e ensaiar a bomba na fonte de 7–9 V — primeiro pelo botão do app, depois pelo automático.
- Calibrar a visão com fotos reais. A primeira foto real já deu falso
positivo. Com planta na bancada: fotos com e sem planta pelo comando
Fda câmera, e o retreino em cima delas. - Completar a calibração do solo: molhar a terra até encharcar e medir com
scripts/calibra_solo.py(espera a leitura estabilizar). O ponto seco já está medido, mas ainda assentando (a leitura seca desceu 50 pontos em 20 min): refazer depois de algumas horas. O molhado, e portanto as faixas do meio, ainda são chute. O tanque também espera água. - Medir a corrente com amperímetro e comparar com o
energia_mapublicado no JSON. - Acoplamento entre vasos, que dá nome ao projeto. Nenhum protocolo definido ainda — mas o quadro do enlace já é o candidato natural.
Commits seguem tipo(subsistema): descrição, validados pelo commitizen
(cz.toml). Branches: main guarda o estado coerente e publicado,
develop integra o trabalho em curso, feat/<assunto> para tarefa curta.
Tag de versão só nasce de coisa medida. A v0.2 está na main porque compila,
roda nas duas placas e passou no ensaio de campo com o celular — mas ainda não
recebeu tag: a bomba não girou e a calibração do solo está pela metade.
python -m pip install --user pre-commit commitizen
pre-commit install --install-hooks
pre-commit install --hook-type commit-msg
