diff --git a/CLAUDE.md b/CLAUDE.md
index 4fe23e2..6f806ab 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -6,6 +6,11 @@ na nuvem. Para setup e o contrato MQTT completo, leia primeiro
`setup-esp32.md`, `setup-pi.md`, `setup-cloud.md`). Este arquivo cobre o que
essa documentação não cobre.
+**Como o repositório funciona, ponta a ponta:**
+[`COMO-FUNCIONA.md`](./COMO-FUNCIONA.md) — o caminho de um comando desde o dedo
+no botão até o motor, o de volta da telemetria, e as decisões que explicam o
+desenho.
+
**Antes de qualquer coisa que atravesse a borda deste repositório**, leia
**[`MAPA-COMUNICACAO.md`](./MAPA-COMUNICACAO.md)** — o mapa das três frentes
(app, cara e corpo), quem fala com quem e por qual transporte. A §0 dele diz o
diff --git a/COMO-FUNCIONA.md b/COMO-FUNCIONA.md
new file mode 100644
index 0000000..6e5d4fd
--- /dev/null
+++ b/COMO-FUNCIONA.md
@@ -0,0 +1,352 @@
+# Como funciona o `orquestrador`
+
+> **Para quem nunca viu este projeto.** Este documento é um passeio guiado pelo
+> código: o que cada peça faz, por onde a informação passa, e por que o desenho
+> é esse. Leva uns quinze minutos e não exige ter o robô na frente.
+>
+> - Quer **instalar**? → [`docs/README.md`](./docs/README.md)
+> - Quer o **contrato MQTT** completo? → [`docs/contrato-mqtt.md`](./docs/contrato-mqtt.md)
+> - Quer ver como os **três repositórios** se encaixam?
+> → [`MAPA-COMUNICACAO.md`](./MAPA-COMUNICACAO.md)
+
+---
+
+## 1. Em uma frase
+
+Este repositório é **o corpo da Atlas**: o que faz o robô se mover, saber onde
+está, e guardar o histórico do que fez.
+
+São três frentes que quase não se conhecem:
+
+| Frente | Onde roda | O que é |
+|---|---|---|
+| **`esp32/`** | No microcontrolador | Firmware que faz a ponte entre o Bluetooth do celular e a serial do Pi |
+| **`pi/services/`** | No Raspberry Pi | Cinco serviços Python independentes, ligados por MQTT |
+| **`cloud/`** | Numa VM (LARCC) | Broker remoto, banco de séries temporais, API de leitura e o túnel |
+| **`site/`** | Cloudflare Pages | A landing page, HTML/CSS/JS puros |
+
+A **cara** do robô — a face animada, a voz, a IA — é do outro repositório,
+[`atlas_ai_v2`](../RobotEye).
+
+---
+
+## 2. O mapa
+
+```mermaid
+flowchart LR
+ APP["App Flutter"]
+
+ subgraph ROBO["NO ROBO"]
+ direction TB
+ PONTE["Ponte BLE
ESP32 ou o proprio Pi"]
+ ING["serial_ingestor
so quando a ponte e o ESP32"]
+ BROKER[("mosquitto
127.0.0.1:1883")]
+ ORQ["orquestrador
o roteador"]
+ MOT["motores"]
+ GPS["gps"]
+ WIFI["wifi"]
+ HW["Drivers TMC2209
GPIO"]
+ end
+
+ subgraph NUVEM["NA NUVEM (VM)"]
+ direction TB
+ BRK2[("mosquitto remoto")]
+ INGC["ingestor"]
+ DB[("TimescaleDB")]
+ API["API FastAPI
so leitura"]
+ TUNEL["cloudflared"]
+ end
+
+ SITE["Landing page"]
+
+ APP -- "BLE, JSON por linha" --> PONTE
+ PONTE -- "serial" --> ING
+ ING --> BROKER
+ PONTE -- "MQTT direto" --> BROKER
+ BROKER --> ORQ
+ ORQ -- "robo/motores/comando" --> MOT
+ ORQ -- "robo/wifi/comando" --> WIFI
+ MOT --> HW
+ GPS -- "robo/gps/posicao" --> BROKER
+ MOT -- "robo/motores/status" --> BROKER
+ ORQ -- "espelha em robo/telemetria/#" --> BRK2
+ BRK2 --> INGC --> DB
+ DB --> API --> TUNEL
+ TUNEL -- "HTTPS, com token" --> APP
+ TUNEL -- "HTTPS, sem token" --> SITE
+```
+
+**A leitura mais curta do diagrama:** há dois caminhos, e eles são de mão única.
+
+- **O de ida (comando):** app → rádio → MQTT → roteador → serviço → motor.
+- **O de volta (telemetria):** serviço → MQTT → espelho → nuvem → banco → API →
+ app.
+
+Nenhum serviço fala com outro diretamente. Todos falam com o **barramento
+MQTT**, e é isso que permite ligar um serviço novo sem tocar em nenhum dos que
+já existem.
+
+---
+
+## 3. O caminho de um comando, passo a passo
+
+Alguém encosta o dedo no botão **FRENTE** do app:
+
+| # | Onde | O que acontece |
+|---|---|---|
+| 1 | App | Escreve `{"cmd":"F"}\n` na característica BLE. E **repete a cada 300 ms** enquanto o dedo estiver no botão (ver [§6](#6-segurança-de-movimento-três-camadas-independentes)). |
+| 2 | Ponte | O ESP32 (`esp32_ble_bridge.ino`) ou o próprio Pi valida que é JSON e repassa. **Não interpreta**: não sabe o que é `"F"`. |
+| 3 | `serial_ingestor` | Só existe quando a ponte é o ESP32. Lê linhas da serial e publica cada uma em `robo/comando/entrada`, sem interpretar. |
+| 4 | `orquestrador/roteador.py` | Traduz. `{"cmd":"F"}` vira `{"acao":"frente","velocidade":60}` em `robo/motores/comando`. É aqui que a entrada não-confiável é validada e saturada. |
+| 5 | `motores/main.py` | Recebe pela thread do MQTT, sob cadeado. |
+| 6 | `motores/cinematica.py` | `"frente"` vira `Velocidades(esquerda=1.0, direita=1.0)`. A `Rampa` acelera até lá sem tranco. |
+| 7 | `motores/acionamento.py` | A velocidade vira frequência de uma onda quadrada no pino STEP. O motor gira sozinho enquanto ninguém mexer. |
+| 8 | `motores/vigia.py` | Em paralelo: se passar **1 segundo** sem o comando ser repetido, para tudo. Silêncio significa “pare”. |
+
+E o caminho de volta, da posição do GPS até o gráfico no celular:
+
+| # | Onde | O que acontece |
+|---|---|---|
+| 1 | `gps/main.py` | Lê sentenças NMEA da serial, extrai posição e publica em `robo/gps/posicao` (retained). |
+| 2 | `orquestrador/main.py` | Espelha `robo/gps/posicao` → `robo/telemetria/gps`. **Só o roteador decide o que vira histórico** — nenhum serviço precisa saber disso. |
+| 3 | Bridge do Mosquitto | Replica `robo/telemetria/#` para o broker da nuvem. |
+| 4 | `cloud/ingestor/main.py` | Assina e grava numa hypertable do TimescaleDB. |
+| 5 | `cloud/api/consultas.py` | Monta o SQL. **Não toca no banco** — devolve `(sql, parâmetros)`. |
+| 6 | `cloud/api/main.py` | Serve por HTTP, atrás do túnel da Cloudflare. |
+| 7 | App | Desenha o mapa e os gráficos. |
+
+---
+
+## 4. As peças, uma a uma
+
+### `pi/services/` — os cinco serviços
+
+Cada um tem o seu `pyproject.toml`, roda como um serviço systemd separado, e
+compartilha só a biblioteca `robo_common`.
+
+| Serviço | Assina | Publica | O que faz |
+|---|---|---|---|
+| **`serial_ingestor`** | — | `robo/comando/entrada` | Lê linhas da serial do ESP32 e repassa. Nada mais. |
+| **`orquestrador`** | `robo/comando/entrada` + os tópicos vivos | `robo/{motores,voz,wifi,rota}/comando` + `robo/telemetria/*` | Roteia comandos e espelha telemetria. |
+| **`motores`** | `robo/motores/comando` | `robo/motores/status` | Executa o movimento. |
+| **`gps`** | — | `robo/gps/posicao` | Lê NMEA e publica posição. |
+| **`wifi`** | `robo/wifi/comando` | `robo/sistema/wifi` | Provisiona rede com o `nmcli`. Roda como root. |
+
+### `robo_common/` — a biblioteca compartilhada
+
+Dois arquivos, e os dois valem a leitura:
+
+- **`topics.py`** — todo nome de tópico MQTT do projeto, num lugar só. É o
+ reflexo em código do `docs/contrato-mqtt.md`. **Nunca escreva o nome de um
+ tópico à mão em outro arquivo.**
+- **`mqtt_client.py`** — o `MqttService`, que embrulha o paho com o que todo
+ serviço precisa: reconexão automática, re-inscrição depois de cair, JSON
+ inválido descartado sem derrubar o serviço, e **Last Will** — se o processo
+ morrer sem avisar, o broker publica “offline” por ele.
+
+### `motores/` — três camadas, e as duas de baixo rodam sem robô
+
+Esta é a parte mais bem separada do repositório, e vale como modelo:
+
+```mermaid
+flowchart TB
+ MQTT["MQTT, vigia e o laco
main.py"]
+ CIN["Cinematica: comando vira velocidade
cinematica.py"]
+ ACI["Acionamento: velocidade vira pulso
acionamento.py (ABC)"]
+ STEP["AcionamentoStepper
TMC2209 por PWM"]
+ SIM["AcionamentoSimulado
so anota o que faria"]
+
+ MQTT --> CIN
+ MQTT --> ACI
+ ACI --> STEP
+ ACI --> SIM
+```
+
+- **`cinematica.py`** é **puro**: sem GPIO, sem MQTT e **sem relógio próprio**.
+ Quem chama informa o `dt`, então uma rampa de meio segundo é testada em zero
+ segundos.
+- **`acionamento.py`** é uma ABC. `MOTORES_BACKEND=simulado` sobe o serviço num
+ notebook e mostra no log o que o robô faria.
+- **`main.py`** não sabe o que é um GPIO.
+
+**O pulso deixou de ser feito em Python.** A versão anterior escrevia cada
+flanco do STEP à mão com `time.sleep(delay)` — e um sleep de meio milissegundo
+não dorme meio milissegundo, dorme o que o escalonador resolver; a variação ia
+para o motor como tremor. Hoje o pino recebe uma onda quadrada do PWM, e mudar a
+velocidade é escrever um número.
+
+### `roteador.py` — Command Pattern, não um dicionário de funções
+
+`ComandoRoteavel` é uma ABC; cada tipo de comando do app é uma subclasse
+registrada em `_ROTAS`. `rotear()` despacha polimorficamente sem saber qual
+subclasse está do outro lado. Adicionar um comando novo é criar a subclasse e
+registrá-la — `rotear()` nunca muda.
+
+Ele também é a **fronteira de confiança**: tudo que vem do app é validado e
+saturado aqui. Velocidade fora de 0–100 é cortada; eixo fora de -1 a 1 é
+cortado; coordenada fora do planeta é descartada; comando malformado vira lista
+vazia e um aviso no log — **nunca uma exceção**.
+
+### `cloud/` — o caminho de volta
+
+```mermaid
+flowchart LR
+ BRK[("mosquitto remoto
com senha")]
+ ING["ingestor"]
+ DB[("TimescaleDB
hypertable telemetria")]
+ API["api
usuario robo_leitura, so SELECT"]
+ CF["cloudflared"]
+
+ BRK --> ING -- "INSERT" --> DB
+ DB -- "SELECT" --> API --> CF
+```
+
+**A API nunca escreve.** Ela roda com um usuário de banco separado, só com
+`SELECT` — é a única peça exposta à internet, e um bug numa rota não pode ser
+capaz de apagar meses de telemetria.
+
+E tem **duas portas**:
+
+| Porta | Exige | Serve |
+|---|---|---|
+| `/v1/...` | `Authorization: Bearer` | Tudo, inclusive as coordenadas exatas |
+| `/v1/publico/...` | Nada | O resumo, e o trajeto com a posição arredondada para ~11 m |
+
+A landing page é estática: qualquer token no JavaScript dela seria legível por
+quem abrisse o inspetor. Então, em vez de fingir que é segredo, **aquela porta
+serve menos**.
+
+### `esp32/` — o firmware
+
+Uma ponte BLE ↔ Serial e nada mais. Valida que a linha é JSON e repassa; se não
+for, responde erro pela característica de notificação. **Não interpreta
+comandos** — não sabe o que é `"F"`.
+
+BLE e não Bluetooth Classic porque o app roda em iOS também, e o iOS nunca
+ofereceu SPP para apps de terceiros.
+
+---
+
+## 5. O barramento MQTT, em uma tabela
+
+Esta é a espinha do repositório. A fonte de verdade é
+[`robo_common/topics.py`](./pi/services/_common/src/robo_common/topics.py).
+
+| Tópico | Quem publica | Quem consome | Conteúdo |
+|---|---|---|---|
+| `robo/comando/entrada` | ponte BLE ou `serial_ingestor` | `orquestrador` | o JSON cru vindo do app |
+| `robo/motores/comando` | `orquestrador` | `motores` | `{"acao":"mover","linear":…,"angular":…}` |
+| `robo/motores/status` | `motores` | telemetria | estado dos motores (retained) |
+| `robo/gps/posicao` | `gps` | telemetria | posição atual (retained) |
+| `robo/wifi/comando` | `orquestrador` | `wifi` | provisionamento de rede |
+| `robo/sistema/wifi` | `wifi` | telemetria | estado da conexão |
+| `robo/voz/falar` | `orquestrador` | *(ninguém ainda)* | texto para a Atlas falar |
+| `robo/rota/comando` | `orquestrador` | *(ninguém ainda)* | a rota segura, fatiada |
+| `robo/sistema/heartbeat/` | cada serviço | telemetria | “online” / “offline” (Last Will) |
+| `robo/telemetria/#` | `orquestrador` (espelho) | bridge → nuvem | tudo que vira histórico |
+
+---
+
+## 6. Segurança de movimento: três camadas independentes
+
+Um comando de movimento **não vale para sempre**. Esta é a regra mais
+importante do repositório, e ela está implementada três vezes, de propósito:
+
+```mermaid
+flowchart TB
+ A["1. O app repete
o mesmo comando a cada 300 ms
enquanto o dedo esta no botao"]
+ B["2. A ponte avisa
ESP32 e ponte do Pi publicam
parada_emergencia ao perder o BLE"]
+ C["3. Os motores vigiam
1 s sem comando repetido = parar
motores/vigia.py"]
+ A --> B --> C
+```
+
+Por que três? Porque cada uma cobre a falha da anterior:
+
+- O app repetir não ajuda se **o app** morrer → a ponte percebe a queda do BLE.
+- A ponte avisar não ajuda se **a ponte** travar → os motores percebem o
+ silêncio.
+- Os motores vigiarem é a última linha, e não depende de mais ninguém estar vivo.
+
+**Ao mexer em qualquer ponto desse caminho, pergunte: o que acontece se isto
+morrer no meio de um movimento?** E prefira sempre a resposta que para o robô.
+
+---
+
+## 7. As decisões que explicam o desenho
+
+**1. Ninguém fala com ninguém — todos falam com o barramento.** Um serviço novo
+entra assinando um tópico, sem tocar em nenhum dos que já existem. É o que
+permite trocar o ESP32 pelo rádio do próprio Pi sem que `motores` saiba.
+
+**2. Quem decide o que vira histórico é um só.** Os serviços publicam o estado
+“vivo”; o `orquestrador` espelha para `robo/telemetria/*` o que deve persistir.
+Acrescentar uma fonte de histórico é acrescentar uma linha em
+`ESPELHO_TELEMETRIA`.
+
+**3. Quem calcula não toca em infraestrutura.** `roteador.py`,
+`motores/cinematica.py` e `cloud/api/consultas.py` seguem todos o mesmo desenho:
+recebem dados, devolvem dados, e não abrem conexão nenhuma. É o que faz 135
+testes rodarem em menos de um segundo, sem broker, sem banco e sem robô.
+
+**4. O app é entrada não-confiável.** Ele atravessa um rádio que não pede senha.
+Tudo que vem dele é validado e saturado antes de virar movimento ou consulta —
+`limitar()`, `_limitar_eixo()`, `campo_valido()`, `INTERVALOS`.
+
+---
+
+## 8. Rodando os testes
+
+Nenhum precisa de Raspberry Pi, motor, broker ou banco.
+
+```bash
+# Tudo de uma vez, num container descartável (não instala nada na sua máquina)
+./scripts/testar.sh
+
+# Ou serviço a serviço:
+cd pi/services/motores && PYTHONPATH="src:../_common/src" python -m unittest discover -s tests # 52
+cd pi/services/orquestrador && PYTHONPATH="src:../_common/src" python -m unittest discover -s tests # 30
+cd pi/services/wifi && PYTHONPATH="src:../_common/src" python -m unittest discover -s tests # 16
+
+cd cloud/api
+python3 -m pip install -r requirements-dev.txt # httpx: o TestClient roda nele
+python3 -m unittest discover -s tests # 37
+```
+
+**Sem dados para testar a nuvem?** `cloud/scripts/semear-demonstracao.py` enche
+o banco com um trajeto plausível em volta do campus, bateria descarregando e
+comandos de motor coerentes com a curva. Tudo marcado com `"demo": true`, que é
+o que faz `--limpar` nunca tocar em telemetria de verdade.
+
+---
+
+## 9. Duas armadilhas que já custaram caro
+
+**⚠️ Um broker só na porta 1883.** O setup do `atlas_ai_v2` instala o Mosquitto
+pelo `apt`; o `pi/docker-compose.yml` daqui sobe outro na mesma porta. O segundo
+a subir falha com *“Address already in use”*, e o sintoma **não parece de
+broker**: o app conecta, os comandos chegam ao Pi e o robô não se mexe.
+
+```bash
+systemctl is-active mosquitto # o do apt
+docker ps --filter name=mosquitto # o do compose
+sudo ss -lntp | grep 1883 # quem realmente está com a porta
+```
+
+**⚠️ Os serviços deste repositório não estão instalados no robô.** Conferido por
+SSH: no Pi rodam a face, a ponte BLE e o Mosquitto — e mais nada. O comando
+chega em `robo/comando/entrada` e para ali. Ver a §0 do
+[`MAPA-COMUNICACAO.md`](./MAPA-COMUNICACAO.md), que traz o teste de dez segundos
+para confirmar.
+
+---
+
+## 10. Onde continuar lendo
+
+| Documento | Para quê |
+|---|---|
+| [`MAPA-COMUNICACAO.md`](./MAPA-COMUNICACAO.md) | As fronteiras entre os três repositórios, e o que está no ar hoje |
+| [`docs/contrato-mqtt.md`](./docs/contrato-mqtt.md) | O formato exato de cada mensagem |
+| [`docs/setup-pi.md`](./docs/setup-pi.md) | Instalar os serviços no Raspberry Pi |
+| [`docs/setup-cloud.md`](./docs/setup-cloud.md) | Subir o broker, o banco, a API e o túnel |
+| [`docs/setup-esp32.md`](./docs/setup-esp32.md) | Gravar o firmware |
+| [`CLAUDE.md`](./CLAUDE.md) | Convenções do repositório |
diff --git a/MAPA-COMUNICACAO.md b/MAPA-COMUNICACAO.md
index 719923f..caf6c2d 100644
--- a/MAPA-COMUNICACAO.md
+++ b/MAPA-COMUNICACAO.md
@@ -108,36 +108,65 @@ Conferido por SSH no mesmo dia:
## 1. O sistema numa tela
+```mermaid
+flowchart TB
+ APP["APP FLUTTER
aplicativo"]
+ SITE["LANDING PAGE
site/"]
+ PC["Maquina da IA
Ollama, outro computador"]
+
+ subgraph PI["RASPBERRY PI"]
+ direction TB
+ PONTE["Ponte BLE
ESP32 ou o proprio Pi"]
+ BROKER[("mosquitto :1883")]
+ ROT["orquestrador
o roteador"]
+ MOT["motores"]
+ GPS["gps"]
+ WIFI["wifi"]
+ CARA["RobotEye
face, voz e IA"]
+ FUTURO["navegacao
ainda nao existe"]
+ end
+
+ subgraph NUVEM["NUVEM - VM do LARCC"]
+ direction TB
+ BRK2[("mosquitto remoto")]
+ INGC["ingestor"]
+ DB[("TimescaleDB")]
+ API["API FastAPI
so leitura"]
+ end
+
+ APP -- "BLE - JSON por linha" --> PONTE
+ PONTE -- "robo/comando/entrada" --> BROKER
+ BROKER --> ROT
+ ROT -- "robo/motores/comando" --> MOT
+ ROT -- "robo/wifi/comando" --> WIFI
+ ROT -. "robo/voz/falar" .-> CARA
+ ROT -. "robo/rota/comando" .-> FUTURO
+ GPS -- "robo/gps/posicao" --> BROKER
+ MOT -- "robo/motores/status" --> BROKER
+ ROT -- "espelha robo/telemetria/#" --> BRK2
+ BRK2 --> INGC --> DB --> API
+ API -- "HTTPS com token" --> APP
+ API -- "HTTPS sem token" --> SITE
+ CARA -- "HTTP" --> PC
```
- ┌───────────────┐ BLE (NUS) ┌──────────────────────────────────┐
- │ App Flutter │ {"cmd":"F"}\n │ Raspberry Pi │
- │ (aplicativo) │ ───────────────────────► │ │
- │ │ {"tipo":"rota",...}\n │ ┌────────────┐ MQTT (:1883) │
- └──────┬────────┘ │ │ │ ponte BLE │──► robo/comando/ │
- │ │ │ │ (ESP32 OU │ entrada │
- │ ▼ │ │ o Pi) │ │ │
- │ ┌────────────┐ │ └────────────┘ ▼ │
- │ │ ESP32 │ Serial │ ┌──────────────────────────────┐│
- │ │ ble_bridge │ ────────► │ │ orquestrador (roteador) ││
- │ └────────────┘ │ │ robo/comando/entrada ││
- │ │ │ ├─► robo/motores/comando ││
- │ │ │ ├─► robo/voz/falar ││
- │ │ │ ├─► robo/wifi/comando ││
- │ │ │ └─► robo/rota/comando 🆕 ││
- │ │ └──────────────────────────────┘│
- │ │ motores │ gps │ wifi │ RobotEye │
- │ └───────┬──────────────────────────┘
- │ HTTP (leitura) │ MQTT → ingestor
- │ api./v1/... ▼
- └─────────────────────────────► ┌────────────────────────┐
- │ Nuvem (Docker/LARCC) │
- ┌───────────────┐ HTTP (público) │ Mosquitto + ingestor │
- │ Landing site │ ────────────────────► │ + TimescaleDB + API │
- │ (site/) │ api./v1/ │ + Cloudflare Tunnel │
- └───────────────┘ publico/... └────────────────────────┘
-
- RobotEye (a cara) também fala com o Ollama (a IA) por HTTP, em OUTRA máquina.
-```
+
+> **Duas ressalvas importantes sobre este diagrama.**
+>
+> 1. Ele mostra o sistema **projetado**. Hoje, no robô real, os serviços do
+> `orquestrador` (o roteador, `motores`, `gps`, `wifi`) **não estão
+> instalados** — ver a §0. As setas que saem do broker para eles são planta,
+> não construção.
+> 2. As setas para `robo/voz/falar` e `robo/rota/comando` mostram para onde o
+> roteador publica. **Ninguém consome esses dois tópicos ainda** — são
+> ganchos para trabalho futuro (§6).
+
+Para entender cada repositório por dentro, há um passeio guiado em cada um:
+
+| Repositório | Passeio guiado |
+|---|---|
+| `atlas_ai_v2` — a cara | [`../RobotEye/COMO-FUNCIONA.md`](../RobotEye/COMO-FUNCIONA.md) |
+| `orquestrador` — o corpo | [`COMO-FUNCIONA.md`](./COMO-FUNCIONA.md) |
+| `aplicativo` — o controle | [`../app/COMO-FUNCIONA.md`](../app/COMO-FUNCIONA.md) |
---
diff --git a/README.md b/README.md
index 1fa224f..f9ad0e9 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
# orquestrador — o corpo da Atlas
+> **Primeira vez aqui?** Comece por **[`COMO-FUNCIONA.md`](./COMO-FUNCIONA.md)**
+> — um passeio guiado de quinze minutos pela arquitetura, com diagramas. Para as
+> fronteiras com os outros dois repositórios, veja
+> [`MAPA-COMUNICACAO.md`](./MAPA-COMUNICACAO.md).
+
Este repositório é a parte da Atlas que **se move, se localiza e se comunica**:
os serviços que rodam no Raspberry Pi, o firmware do ESP32 e a nuvem que guarda
e serve a telemetria.