Robô Otto Ninja#
Objetivo#
Compreender, montar e programar o robô Otto Ninja, explorando conceitos de eletrônica, mecânica e programação.
Analisaremos também a evolução da plataforma com o uso do ESP32, que incorpora conectividade sem fio (Wi-Fi e Bluetooth), maior capacidade de processamento e novas possibilidades de controle e automação.
Ao longo do notebook, são apresentadas aplicações na Engenharia Civil, como o uso de sensores de distância para monitoramento de estruturas, controle de acesso em obras e automação de inspeções.
1. Introdução ao Otto Ninja#
O Otto Ninja é um robô bípede open-source capaz de andar, dançar e desviar de obstáculos. É amplamente utilizado no ensino de robótica por integrar conceitos de eletrônica, programação e mecânica de forma prática e acessível.

Mais informações: ottodiy.com/ninja
Originalmente baseado em Arduino Nano, versões mais recentes utilizam o ESP32, permitindo comunicação Bluetooth e Wi-Fi, além de maior desempenho e menor custo.
O comportamento do robô é baseado em sequências coordenadas de movimentos dos servomotores, simulando locomoção bípede.
Conceitos envolvidos:#
Área |
Conceito |
|---|---|
Robótica |
Locomoção bípede, cinemática |
Eletrônica |
Controle PWM, sensores, alimentação |
Programação |
C++ / Arduino IDE, lógica de controle |
Comunicação |
Bluetooth, Wi-Fi, IoT |
Mecânica |
Estrutura impressa em 3D, servos |
Modos de operação:#
┌─────────────────────────────────────────┐
│ OTTO NINJA - MODOS │
├─────────────────┬───────────────────────┤
│ Autônomo │ Executa rotinas pré- │
│ │ programadas │
├─────────────────┼───────────────────────┤
│ Manual │ Controle via app / │
│ │ Bluetooth │
├─────────────────┼───────────────────────┤
│ Reativo │ Responde a sensores │
│ │ (desvio de obstáculo) │
└─────────────────┴───────────────────────┘
2. Componentes#
Versão tradicional (Arduino Nano):#
Componente |
Quantidade |
Função |
|---|---|---|
Arduino Nano |
1 |
Microcontrolador principal |
Servo motor SG90 |
4 |
Movimentação das pernas e pés |
Sensor HC-SR04 |
1 |
Detecção de obstáculos |
Buzzer |
1 |
Sons e alertas |
Módulo Bluetooth (HC-05) |
1 (opcional) |
Controle remoto |
Bateria 9V ou LiPo |
1 |
Alimentação |
Estrutura 3D impressa |
1 kit |
Corpo do robô |
Versão atualizada (ESP32) — Recomendada:#

Referência de pinagem: lastminuteengineers.com/esp32-pinout-reference
Componente |
Quantidade |
Vantagem |
|---|---|---|
ESP32 |
1 |
Wi-Fi + Bluetooth integrados, maior CPU |
Servo motor SG90 |
4 |
Mesmos servos — compatível |
Sensor HC-SR04 |
1 |
Mesma funcionalidade |
Buzzer |
1 |
Saída de áudio simples |
Bateria LiPo 3,7V + regulador |
1 |
Mais compacto e eficiente |
Observações:#
Alimentação separada para os servos: Os servos consomem até 1A por unidade em carga. Nunca os alimente diretamente do pino 3.3V do ESP32 — use um regulador externo (ex: AMS1117 5V).
GND compartilhado (Ground comum): O GND do ESP32, dos servos e do sensor deve ser conectado em um ponto comum. Sem isso, os sinais de controle PWM não funcionarão corretamente.
Nível lógico do HC-SR04: O sensor opera em 5V, mas o ESP32 usa 3.3V. O pino ECHO precisa de um divisor de tensão (resistores 1kΩ e 2kΩ) ou de um módulo conversor de nível lógico.
ESP32 (3.3V) Divisor de tensão HC-SR04 (5V)
│ │
ECHO ─┤──── R1(1kΩ) ──┬── R2(2kΩ) ── GND │ ECHO
│ └── GPIO ESP32 │
3. Controle de Servomotores — Conceito de PWM#
O PWM (Pulse Width Modulation) é o sinal usado para controlar a posição de um servomotor.
A largura do pulso determina o ângulo:
~1ms de pulso → 0°
~1,5ms de pulso → 90° (posição central)
~2ms de pulso → 180°
O período total do sinal é de 20ms (frequência de 50Hz).
Analogia com Engenharia Civil:#
Da mesma forma que um atuador hidráulico em uma ponte móvel recebe um sinal proporcional para abrir ou fechar em um ângulo específico, o servomotor responde ao sinal PWM para posicionar sua haste com precisão.
# ============================================================
# SIMULAÇÃO: Controle de Servo via PWM — Otto Ninja
# ============================================================
#
# CONTEXTO
# --------
# O Otto Ninja é um robô bípede de código aberto controlado
# por Arduino. Cada perna é movida por um servomotor, que
# recebe comandos via sinal PWM (Pulse Width Modulation).
#
# COMO FUNCIONA O PWM
# -------------------
# PWM é uma técnica de controle em que o microcontrolador
# envia pulsos elétricos periódicos. O que muda não é a
# tensão, mas a DURAÇÃO de cada pulso (largura):
#
# Pulso curto (1.0 ms) → servo vai para -90°
# Pulso médio (1.5 ms) → servo fica na posição central (0°)
# Pulso longo (2.0 ms) → servo vai para +90°
#
# O servo lê esses pulsos ~50 vezes por segundo e ajusta
# seu eixo para o ângulo correspondente.
#
# O QUE ESTE CÓDIGO FAZ
# ---------------------
# Simula o ângulo de UMA perna do Otto ao longo de 2 segundos,
# usando uma função senoidal para gerar o movimento oscilatório
# suave (vai e volta) que produz o padrão de caminhada.
# Em seguida, converte esse ângulo no pulso PWM equivalente.
#
# APLICAÇÕES NA ENGENHARIA CIVIL
# -------------------------------
# Esse mesmo padrão oscilatório aparece em:
# • Amortecedores ativos de pontes pênseis
# • Atuadores de barragens com comportas automáticas
# • Braços robóticos de inspeção estrutural
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
# ------------------------------------------------------------------
# PARÂMETROS DO MOVIMENTO
# ------------------------------------------------------------------
tempo = np.linspace(0, 2, 300) # Eixo do tempo: 0 a 2s, com 300 amostras
amplitude = 45 # Amplitude da oscilação em graus
# → o servo vai de -45° a +45°
frequencia = 1.5 # Frequência em Hz (ciclos por segundo)
# → 1.5 Hz = uma ida e volta completa a cada 0.67s
# ------------------------------------------------------------------
# ÂNGULO DO SERVO AO LONGO DO TEMPO
# ------------------------------------------------------------------
# A função seno produz valores entre -1 e +1.
# Multiplicar pela amplitude escala esse intervalo para [-45°, +45°].
#
# Fórmula: θ(t) = A · sin(2π · f · t)
# A = amplitude (graus)
# f = frequência (Hz)
# t = tempo (s)
angulo_servo = amplitude * np.sin(2 * np.pi * frequencia * tempo)
# ------------------------------------------------------------------
# CONVERSÃO: ÂNGULO → LARGURA DE PULSO PWM
# ------------------------------------------------------------------
# Relação linear entre ângulo e duração do pulso:
#
# pwm = 1.5 + (ângulo / 90) × 0.5
#
# Exemplos de verificação:
# ângulo = 0° → pwm = 1.5 + 0 = 1.50 ms ✓ (centro)
# ângulo = +45° → pwm = 1.5 + 0.25 = 1.75 ms ✓ (metade do caminho para +90°)
# ângulo = -45° → pwm = 1.5 - 0.25 = 1.25 ms ✓ (metade do caminho para -90°)
# ângulo = +90° → pwm = 1.5 + 0.5 = 2.00 ms ✓ (máximo)
# ângulo = -90° → pwm = 1.5 - 0.5 = 1.00 ms ✓ (mínimo)
pwm_ms = 1.5 + (angulo_servo / 90) * 0.5
# ------------------------------------------------------------------
# VISUALIZAÇÃO
# ------------------------------------------------------------------
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6), sharex=True)
# sharex=True vincula o zoom/pan dos dois gráficos no eixo X
# --- Gráfico 1: Ângulo do servo ---
ax1.plot(tempo, angulo_servo, color='royalblue', linewidth=2)
ax1.axhline(0, color='gray', linestyle='--', linewidth=0.8) # linha de referência: 0°
ax1.fill_between(tempo, angulo_servo, 0, alpha=0.1, color='royalblue') # área sombreada
ax1.set_ylabel('Ângulo do servo (°)', fontsize=11)
ax1.set_title('Simulação de Movimento Oscilatório — Otto Ninja (Perna)', fontsize=13)
ax1.set_ylim(-60, 60) # margem extra acima/abaixo da amplitude de ±45°
ax1.grid(True, alpha=0.3)
ax1.legend(['Ângulo'], loc='upper right')
# --- Gráfico 2: Largura de pulso PWM correspondente ---
ax2.plot(tempo, pwm_ms, color='orangered', linewidth=2)
ax2.axhline(1.5, color='gray', linestyle='--', linewidth=0.8, label='Centro (0° → 1.5 ms)')
ax2.set_ylabel('Largura do pulso PWM (ms)', fontsize=11)
ax2.set_xlabel('Tempo (s)', fontsize=11)
ax2.set_ylim(0.8, 2.2) # margem visual acima de 2.0 ms e abaixo de 1.0 ms
ax2.grid(True, alpha=0.3)
ax2.legend(loc='upper right')
plt.tight_layout()
plt.savefig('pwm_servo.png', dpi=120, bbox_inches='tight')
plt.show()
# ------------------------------------------------------------------
# RESUMO NUMÉRICO DOS RESULTADOS
# ------------------------------------------------------------------
print(f"Amplitude de oscilação : ±{amplitude}°")
print(f"Frequência : {frequencia} Hz → período = {1/frequencia:.2f} s")
print(f"Pulso PWM mínimo : {pwm_ms.min():.2f} ms (posição -{amplitude}°)")
print(f"Pulso PWM máximo : {pwm_ms.max():.2f} ms (posição +{amplitude}°)")
print(f"Pulso PWM central : 1.50 ms (posição 0°)")
Amplitude de oscilação: ±45°
Frequência: 1.5 Hz
Pulso PWM mínimo: 1.25 ms (≈ 45° negativo)
Pulso PWM máximo: 1.75 ms (≈ 45° positivo)
4. Montagem#
A montagem do Otto Ninja influencia diretamente sua estabilidade e a qualidade dos movimentos.
Etapas de montagem:#
Calibração inicial dos servos: Posicione todos os 4 servos em 90° antes de fixá-los na estrutura. Erros nesta etapa resultam em desequilíbrio permanente.
Fixação dos servos na estrutura: Use os parafusos M2 que vêm com os SG90. Garanta alinhamento perfeitamente paralelo.
Montagem das pernas e pés: Encaixe os braços dos servos nos slots da estrutura. Evite folgas.
Instalação do sensor ultrassônico: O HC-SR04 fica na “cabeça” do robô, apontado para frente.
Conexão do microcontrolador: Encaixe o ESP32 na cavidade central.
Organização da fiação: Prenda os fios com abraçadeiras. Fios soltos interferem no movimento.
Problemas comuns e soluções:#
Problema |
Causa provável |
Solução |
|---|---|---|
Robô desequilibrado |
Servo não estava em 90° na montagem |
Desmontar e reposicionar |
Tremores nos servos |
Alimentação insuficiente |
Usar bateria externa para os servos |
Movimento irregular |
Ângulos errados no código |
Ajustar os valores de offset |
Ruído nos movimentos |
Folga mecânica |
Reajustar parafusos da estrutura |
5. Programação — Arduino / ESP32#
A lógica do robô baseia-se no controle dos ângulos dos servos ao longo do tempo. Cada movimento é uma sequência de posições angulares sincronizadas.
No ESP32, o controle PWM é realizado via ledc (LED Control peripheral), que permite frequência e resolução mais precisas que o analogWrite do Arduino.
Estrutura básica de um programa:#
SETUP (executa 1 vez)
└─ Inicializar pinos dos servos
└─ Configurar pinos do sensor HC-SR04
└─ Posicionar servos em 90° (neutro)
LOOP (executa continuamente)
└─ Ler sensor de distância
└─ Decidir: andar, girar ou parar
└─ Executar sequência de movimentos
└─ Aguardar (delay)
Controle de Servo — Otto Ninja#
Arduino / ESP32 — C++
Exemplo básico de movimentação oscilatória de uma perna usando a biblioteca Servo.h no Arduino Nano ou ESP32.
Código-fonte#
// Controle simples de servo — Otto Ninja
#include <Servo.h> // Importa a biblioteca de controle de servo
Servo perna_esquerda; // Cria objeto que representa o servo físico
void setup() {
// Associa o objeto ao pino GPIO 2 do microcontrolador
// O pino envia o sinal PWM que controla o ângulo do servo
perna_esquerda.attach(2);
// Posiciona o servo em 90° (posição neutra / vertical)
perna_esquerda.write(90);
delay(500); // Aguarda 500 ms para estabilizar
}
void loop() {
perna_esquerda.write(70); // Inclina a perna para frente
delay(400); // Mantém a posição por 400 ms
perna_esquerda.write(90); // Retorna ao centro
delay(400);
perna_esquerda.write(110); // Inclina a perna para trás
delay(400);
perna_esquerda.write(90); // Retorna ao centro
delay(400);
}
Funções principais#
Instrução |
O que faz |
|---|---|
|
Importa a biblioteca que traduz |
|
Declara um objeto que representa um servo físico. Cada servo precisa do seu próprio objeto. |
|
Define qual GPIO do microcontrolador enviará os pulsos PWM ao servo. |
|
Move o eixo do servo para o ângulo desejado — aceita valores de 0° a 180°. |
|
Pausa a execução em milissegundos, dando tempo ao servo alcançar a posição antes do próximo comando. |
Mapeamento ângulo → pulso PWM#
O servo interpreta a duração do pulso elétrico recebido (~50 vezes por segundo) e posiciona o eixo no ângulo correspondente:
Ângulo |
Largura do pulso |
Posição |
|---|---|---|
−90° |
1.0 ms |
extremo esquerdo |
0° |
1.5 ms |
centro (neutro) |
+90° |
2.0 ms |
extremo direito |
Fórmula da conversão:
Parâmetros do exemplo#
Parâmetro |
Valor |
|---|---|
Posição central |
90° |
Amplitude de oscilação |
±20° (70° ↔ 110°) |
Tempo por passo |
400 ms |
Pino PWM |
GPIO 2 |
6. Controle de Movimento — Como o Otto anda?#
O Otto Ninja tem 4 servomotores:
[CABEÇA — HC-SR04]
│
┌───┴───┐
│ ESP32 │
└───────┘
│ │
[Servo 1] [Servo 2] ← Pernas (movimento frente/trás)
│ │
[Servo 3] [Servo 4] ← Pés (equilíbrio lateral)
│ │
[PÉ E] [PÉ D]
Como um passo é formado:#
Instante |
Servo Perna E |
Servo Perna D |
Servo Pé E |
Servo Pé D |
|---|---|---|---|---|
T=0ms |
90° |
90° |
90° |
90° |
T=200ms |
70° (frente) |
110° (atrás) |
80° |
100° |
T=400ms |
90° |
90° |
90° |
90° |
T=600ms |
110° (atrás) |
70° (frente) |
100° |
80° |
T=800ms |
90° |
90° |
90° |
90° |
Conceito-chave:
Movimento = sequência de ângulos + tempo (delay)
Analogia com Engenharia Civil:#
Na análise de estruturas, o conceito de deslocamento em função do tempo é fundamental. Uma ponte pênsil oscila em modos de vibração — cada modo tem uma frequência e um padrão de deslocamento específico, assim como os servos do Otto têm frequência de oscilação e amplitudes configuráveis.
# ============================================================
# SIMULAÇÃO: Sequência de movimento de um passo completo
# Visualiza a coordenação entre os 4 servos
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
# Definição dos instantes de tempo (ms)
tempos = [0, 200, 400, 600, 800, 1000]
# Ângulos de cada servo ao longo do tempo
# (um passo completo de caminhada bípede)
servo_perna_E = [90, 70, 90, 110, 90, 70] # Perna Esquerda
servo_perna_D = [90, 110, 90, 70, 90, 110] # Perna Direita
servo_pe_E = [90, 80, 90, 100, 90, 80] # Pé Esquerdo
servo_pe_D = [90, 100, 90, 80, 90, 100] # Pé Direito
fig, ax = plt.subplots(figsize=(11, 5))
cores = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']
nomes = ['Perna E', 'Perna D', 'Pé E', 'Pé D']
dados = [servo_perna_E, servo_perna_D, servo_pe_E, servo_pe_D]
for i, (nome, serie, cor) in enumerate(zip(nomes, dados, cores)):
ax.plot(tempos, serie, marker='o', linewidth=2.5,
color=cor, label=nome, markersize=6)
ax.axhline(90, color='gray', linestyle='--', linewidth=1, alpha=0.6, label='Neutro (90°)')
ax.set_xlabel('Tempo (ms)', fontsize=12)
ax.set_ylabel('Ângulo do servo (°)', fontsize=12)
ax.set_title('Coordenação dos 4 Servos — Um Passo Completo do Otto Ninja', fontsize=13)
ax.set_ylim(60, 120)
ax.legend(loc='upper right')
ax.grid(True, alpha=0.3)
# Destaque nas fases
for t, label in zip([0, 200, 400, 600, 800], ['Neutro', 'Passo 1', 'Neutro', 'Passo 2', 'Neutro']):
ax.axvline(t, color='lightgray', linestyle=':', linewidth=1)
ax.text(t + 10, 62, label, fontsize=7, color='gray')
plt.tight_layout()
plt.savefig('movimento_otto.png', dpi=120, bbox_inches='tight')
plt.show()
print(" Gráfico gerado: coordenação entre os 4 servos durante um passo")
print("\n Observe a OPOSIÇÃO de fase entre Perna E e Perna D — isso gera o deslocamento!")
Gráfico gerado: coordenação entre os 4 servos durante um passo
Observe a OPOSIÇÃO de fase entre Perna E e Perna D — isso gera o deslocamento!
7. Sensor Ultrassônico HC-SR04#
Sensores ultrassônicos como o HC-SR04 medem a distância até um objeto através do tempo de retorno de um pulso sonoro ultrassônico (40 kHz — inaudível ao ser humano).

Tutorial completo: lastminuteengineers.com — HC-SR04
Princípio físico:#
[TRIG]──► pulso 10µs ──► som 40kHz ──► OBJETO ──► eco ──► [ECHO]
↓
tempo eco = HIGH do pino ECHO
Fórmula: $\(d = \frac{t_{eco} \times v_{som}}{2}\)$
\(d\) = distância até o obstáculo (m)
\(t_{eco}\) = tempo do eco (s)
\(v_{som}\) = 343 m/s (a 20°C)
Divide por 2 porque o som vai e volta
Parâmetro |
Valor |
|---|---|
Alcance |
2 cm a 400 cm |
Precisão |
± 3 mm |
Tensão |
5V |
Frequência |
40 kHz |
Aplicação em Engenharia Civil — Monitoramento de Nível:#
O sensor HC-SR04 é utilizado em estações de monitoramento de nível de rios e reservatórios. Instalado sobre a lâmina d’água, calcula a distância à superfície e estima o nível. Pesquisas com Arduino e HC-SR04 mostraram precisão aceitável (erro < 4 cm) em escalas de 0 a 4 metros — aplicação diretamente relacionada ao dimensionamento de obras hidráulicas e planos de contingência para enchentes.
# ============================================================
# SIMULAÇÃO: Leitura do sensor ultrassônico HC-SR04
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
# ---- Função de cálculo de distância ----
def calcular_distancia(tempo_eco_s, temperatura_C=20):
"""
Calcula a distância a partir do tempo do eco ultrassônico.
Parâmetros:
tempo_eco_s : float — duração do pulso ECHO (em segundos)
temperatura_C: float — temperatura ambiente (afeta vel. do som)
Retorna:
distancia_m : float — distância ao obstáculo em metros
distancia_cm : float — distância em centímetros
"""
# A velocidade do som varia com a temperatura:
# v = 331.3 + 0.606 * T (m/s)
velocidade_som = 331.3 + 0.606 * temperatura_C
distancia_m = (tempo_eco_s * velocidade_som) / 2
distancia_cm = distancia_m * 100
return distancia_m, distancia_cm
# ---- Exemplos de leitura ----
print("=" * 55)
print(" LEITURAS DO SENSOR ULTRASSÔNICO HC-SR04")
print("=" * 55)
exemplos = [
(0.00060, 20, "Obstaculo próximo"),
(0.00290, 20, "Distância média"),
(0.01170, 20, "Obstáculo distante"),
(0.00290, 35, "Dia quente (35°C)"), # efeito da temperatura
]
for t, temp, desc in exemplos:
d_m, d_cm = calcular_distancia(t, temp)
print(f" {desc:<25} | t={t*1000:.2f} ms | T={temp}°C | d = {d_cm:.1f} cm")
print()
# ---- Gráfico: distância vs tempo do eco ----
tempos = np.linspace(0.0001, 0.023, 200) # de 0.1ms a 23ms
distancias_20 = [calcular_distancia(t, 20)[1] for t in tempos]
distancias_35 = [calcular_distancia(t, 35)[1] for t in tempos]
fig, ax = plt.subplots(figsize=(9, 4))
ax.plot([t*1000 for t in tempos], distancias_20, label='T = 20°C', color='steelblue', linewidth=2)
ax.plot([t*1000 for t in tempos], distancias_35, label='T = 35°C', color='coral', linewidth=2, linestyle='--')
ax.axhline(400, color='red', linestyle=':', linewidth=1, label='Limite máx. HC-SR04 (400cm)')
ax.axhline(2, color='green', linestyle=':', linewidth=1, label='Limite mín. HC-SR04 (2cm)')
ax.set_xlabel('Tempo do eco (ms)', fontsize=11)
ax.set_ylabel('Distância calculada (cm)', fontsize=11)
ax.set_title('HC-SR04: Relação entre Tempo do Eco e Distância', fontsize=12)
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('sensor_distancia.png', dpi=120, bbox_inches='tight')
plt.show()
print(" Nota: a temperatura afeta a velocidade do som e, portanto, a leitura.")
print(" Em obras externas, é recomendável compensar a temperatura no cálculo.")
=======================================================
LEITURAS DO SENSOR ULTRASSÔNICO HC-SR04
=======================================================
Obstaculo próximo | t=0.60 ms | T=20°C | d = 10.3 cm
Distância média | t=2.90 ms | T=20°C | d = 49.8 cm
Obstáculo distante | t=11.70 ms | T=20°C | d = 200.9 cm
Dia quente (35°C) | t=2.90 ms | T=35°C | d = 51.1 cm
Nota: a temperatura afeta a velocidade do som e, portanto, a leitura.
Em obras externas, é recomendável compensar a temperatura no cálculo.
8. Aplicações na Engenharia Civil#
Os conceitos do Otto Ninja têm paralelos diretos com sistemas utilizados na Engenharia Civil moderna:
8.1 Monitoramento Estrutural com Sensores#
Analogia: O sensor HC-SR04 do Otto detecta obstáculos a sua frente. Na Engenharia Civil, sensores ultrassônicos medem fissuras, recalques e deslocamentos em estruturas de concreto e fundações.
Aplicação Civil |
Sensor |
Parâmetro medido |
|---|---|---|
Nível de reservatório |
Ultrassônico |
Lâmina d’água |
Abertura de fissura |
Extensômetro |
Deslocamento (mm) |
Recalque de fundação |
LVDT / GPS |
Deslocamento vertical |
Vibração em pontes |
Acelerômetro |
Frequência natural |
8.2 Robótica de Inspeção em Obras#
Robôs bípedes como o Otto inspiram robôs de inspeção capazes de caminhar sobre terrenos irregulares de obras, inspecionar dutos, verificar estruturas em altura ou entrar em ambientes confinados sem expor trabalhadores a riscos.
8.3 IoT e Monitoramento Remoto de Canteiro de Obras#
Com o ESP32, é possível replicar as funcionalidades de um sistema IoT real:
Sensor (campo) → ESP32 → Wi-Fi / MQTT → Dashboard Web
─────────────────────────────────────────────────────────────
Nível d'água → ESP32 → Internet → Alerta de cheia
Temperatura → ESP32 → Internet → Cura do concreto
Deslocamento → ESP32 → Internet → Alerta estrutural
# ============================================================
# SIMULAÇÃO: Monitoramento de Nível de Reservatório
# usando o mesmo princípio do sensor HC-SR04 do Otto Ninja
# ============================================================
#
# Cenário: Um ESP32 com sensor HC-SR04 está instalado na borda
# superior de um reservatório de 4 metros de altura.
# Ele mede a distância até a superfície da água a cada 30 min.
#
# Nível da água = Altura do reservatório - Distância medida
# ============================================================
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
# Parâmetros do reservatório
ALTURA_RESERVATORIO = 4.00 # metros
NIVEL_ALERTA = 3.60 # metros (90% cheio)
NIVEL_CRITICO = 3.80 # metros (95% cheio)
# Simulação: leituras ao longo de 24 horas (a cada 30 min)
# O nível sobe com chuva (0-12h) e estabiliza depois
horas = np.linspace(0, 24, 49)
# Curva simulada de variação do nível
nivel_agua = (
2.0
+ 1.5 * (1 - np.exp(-horas / 6)) # Subida exponencial (chuva)
- 0.3 * np.maximum(0, horas - 14) / 10 # Leve queda após a chuva
+ 0.05 * np.random.randn(49) # Ruído de sensor
)
nivel_agua = np.clip(nivel_agua, 0, ALTURA_RESERVATORIO)
# Distância medida pelo sensor (HC-SR04) = Altura - Nível
distancia_sensor = ALTURA_RESERVATORIO - nivel_agua
# Detecção de alertas
em_alerta = nivel_agua >= NIVEL_ALERTA
em_critico = nivel_agua >= NIVEL_CRITICO
# -------- Plot ---------
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(11, 7), sharex=True)
# Gráfico 1: Nível da água
ax1.fill_between(horas, nivel_agua, alpha=0.3, color='steelblue')
ax1.plot(horas, nivel_agua, color='steelblue', linewidth=2, label='Nível da água')
ax1.axhline(NIVEL_ALERTA, color='orange', linestyle='--', linewidth=1.5, label=f'Nível de Alerta ({NIVEL_ALERTA}m)')
ax1.axhline(NIVEL_CRITICO, color='red', linestyle='--', linewidth=1.5, label=f'Nível Crítico ({NIVEL_CRITICO}m)')
ax1.axhline(ALTURA_RESERVATORIO, color='black', linestyle='-', linewidth=1, label=f'Capacidade máxima ({ALTURA_RESERVATORIO}m)')
ax1.scatter(horas[em_critico], nivel_agua[em_critico], color='red', zorder=5, s=40, label='⚠ Alarme crítico')
ax1.set_ylabel('Nível da água (m)', fontsize=11)
ax1.set_title('🏗️ Monitoramento de Reservatório com Sensor Ultrassônico (HC-SR04 + ESP32)', fontsize=12)
ax1.legend(loc='lower right', fontsize=9)
ax1.set_ylim(0, 4.3)
ax1.grid(True, alpha=0.3)
# Gráfico 2: Distância medida pelo sensor
ax2.plot(horas, distancia_sensor * 100, color='darkorange', linewidth=2)
ax2.fill_between(horas, distancia_sensor * 100, alpha=0.2, color='orange')
ax2.set_xlabel('Hora do dia', fontsize=11)
ax2.set_ylabel('Distância medida (cm)', fontsize=11)
ax2.set_title('Leitura bruta do sensor HC-SR04 (distância sensor → superfície da água)', fontsize=11)
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('monitoramento_reservatorio.png', dpi=120, bbox_inches='tight')
plt.show()
# Estatísticas
print("ESTATÍSTICAS DO MONITORAMENTO (24 horas)")
print(f" Nível mínimo: {nivel_agua.min():.2f} m")
print(f" Nível máximo: {nivel_agua.max():.2f} m")
print(f" Leituras em alerta: {em_alerta.sum()} de {len(horas)}")
print(f" Leituras críticas: {em_critico.sum()} de {len(horas)}")
print()
print("💡 Este sistema usa exatamente o mesmo princípio do sensor ultrassônico")
print(" do Otto Ninja — mas aplicado à segurança de obras hidráulicas!")
9. Expansões com ESP32#
Com o ESP32, o projeto vai muito além de um simples robô escolar:
9.1 Controle por Bluetooth (App móvel)#
// Exemplo: receber comando Bluetooth e acionar movimento
#include <BluetoothSerial.h>
BluetoothSerial SerialBT;
void setup() {
SerialBT.begin("OttoNinja"); // Nome que aparece no celular
}
void loop() {
if (SerialBT.available()) {
char cmd = SerialBT.read(); // Lê comando do app
if (cmd == 'F') andar_frente();
if (cmd == 'B') andar_atras();
if (cmd == 'S') parar();
}
}
9.2 Interface Web via Wi-Fi#
O ESP32 cria um servidor HTTP na própria rede Wi-Fi. O usuário acessa pelo navegador (celular ou PC) e controla o robô através de botões numa página HTML — sem instalar nenhum aplicativo.
9.3 Possibilidades avançadas:#
Funcionalidade |
Tecnologia |
Aplicação Civil |
|---|---|---|
Controle de voz |
Google Assistant / Alexa |
Acionamento de sistemas |
Envio de dados |
MQTT / HTTP |
Monitoramento remoto |
OTA (atualização remota) |
Wi-Fi |
Manutenção de sensores em campo |
Machine Learning |
TensorFlow Lite |
Detecção de anomalias estruturais |
Integração com banco de dados |
REST API |
Histórico de medições |
10. Exemplos de Aplicação#
Robótica:#
Novo padrão de movimento: Programe uma “dança” com pelo menos 4 movimentos diferentes encadeados.
Desvio automático: Implemente lógica que faça o robô virar à esquerda quando detectar obstáculo a menos de 20 cm.
Controle Bluetooth: Modifique o código para receber comandos de um app de smartphone.
Suavização: Use um loop
forpara mover o servo gradualmente (ângulo atual → ângulo alvo em 20 passos).
Sugestões de exemplos em Engenharia Civil (integração):#
Nível de água: Programe o ESP32 para enviar alerta (buzzer + Wi-Fi) quando o nível do reservatório ultrapassar 90% da capacidade.
Registrador de dados: Salve as leituras do HC-SR04 em um arquivo CSV com timestamp — simule um relatório de monitoramento estrutural.
Análise de temperatura: Use o sensor DHT22 junto ao HC-SR04 para corrigir a velocidade do som na medição de distância em função da temperatura ambiente.