
Monitoramento de Temperatura e Vibração de Motores com ESP32
Nó de manutenção preditiva com MPU6050 e termopar Tipo K: RMS de vibração, telemetria por MQTT e uma tendência mecânica virando alarme útil no SCADA.
Requisitos de hardware:
- Placa ESP32-WROOM-32 ou ESP32-S3
- Acelerômetro triaxial MPU6050
- Módulo MAX31855 compatível com termopar Tipo K
- Termopar Tipo K instalado por profissional habilitado
- Fonte regulada de 5 V e gabinete protegido para o nó sensor
Baixe o material deste tutorial:
- Projeto completo (ZIP)494 KBplatformio.ini, firmware com leitura I2C e SPI, cálculo RMS, pico, fator de crista, MQTT com Last Will, README e manual em PDF.
- Manual em PDF (6 páginas)606 KBMontagem, ligações, linha de base, qualidade do dado, histerese, integração MQTT/SCADA, testes seguros e solução de problemas.
Quer receber novos manuais e esquemas industriais? Entre no nosso canal do Telegram / WhatsApp
Antes de ligar: este não é um instrumento de segurança
Um ESP32 com MPU6050 e MAX31855 é um excelente nó de aquisição e tendência para laboratório, protótipo e manutenção preditiva. Ele ajuda a descobrir que um motor está aquecendo ou vibrando mais do que a própria linha de base.
Ele não substitui relé térmico, proteção contra sobrecorrente, sensor industrial certificado, monitor de vibração dedicado ou qualquer intertravamento de segurança. Não instale, ajuste ou abra uma caixa próxima a um motor energizado sem qualificação elétrica e sem o procedimento de bloqueio e etiquetagem da planta.
O objetivo deste tutorial é específico: medir de forma repetível, preservar o contexto da leitura e publicar uma tendência que alguém consiga interpretar antes da falha.
O que o nó mede
O MPU6050 mede aceleração em três eixos. Em uma carcaça de motor, a vibração pode aparecer como aumento do valor RMS, mudança na distribuição de energia ou surgimento de componentes periódicos no espectro. O sensor é barato e útil para experimentar, mas sua montagem mecânica, faixa e banda não equivalem às de um acelerômetro industrial.
O MAX31855 converte o sinal de um termopar Tipo K e informa a temperatura da junta quente e possíveis falhas do termopar. Ele usa SPI e não deve ser confundido com um sensor digital de temperatura ambiente: o termopar precisa estar montado em um ponto definido da carcaça, com contato mecânico e isolamento elétrico adequados.
O ESP32 coleta os dois sinais, calcula indicadores simples e envia uma carga MQTT parecida com esta:
| 1 | { |
| 2 | "ts": 1755990000, |
| 3 | "temperature_c": 67.4, |
| 4 | "vibration_rms_g": 0.082, |
| 5 | "vibration_peak_g": 0.31, |
| 6 | "crest_factor": 3.78, |
| 7 | "quality": 192, |
| 8 | "sample_count": 128 |
| 9 | } |
O instante é o da leitura, não o momento em que o broker recebeu a mensagem. A qualidade informa se o valor é confiável. Sem esses dois campos, o gráfico pode parecer preciso e ainda assim induzir uma decisão errada.
A montagem importa mais que o dashboard
Cole o MPU6050 com fita dupla-face e o sensor passa a medir a fita, a caixa e qualquer folga. Para uma comparação de tendência, use uma fixação rígida e repetível, preferencialmente um parafuso ou base metálica projetada para o ponto de medição.
Marque a posição e a orientação dos eixos. Se cada visita de manutenção trocar o lado da carcaça, o valor RMS deixa de ser comparável. Não misture medições feitas no mancal, na tampa do motor e na base como se fossem o mesmo ponto.
O termopar também precisa de uma posição definida. A temperatura da carcaça depende de carga, ventilação, temperatura ambiente e tempo de operação. Registre pelo menos o estado do motor e o tempo desde a partida quando quiser comparar dias diferentes.
Ligações elétricas
O MPU6050 usa I2C. Este exemplo usa SDA no GPIO 21 e SCL no GPIO 22. O endereço mais comum é 0x68; se AD0 estiver em nível alto, ele passa a ser 0x69.
O MAX31855 usa SPI: GPIO 18 para SCK, GPIO 19 para MISO e GPIO 5 para CS. O pino MOSI não é necessário para a leitura deste conversor. Confira a pinagem do seu módulo: placas de fabricantes diferentes podem mudar a serigrafia e o regulador de alimentação.
Todos os módulos precisam compartilhar o GND do ESP32. O barramento de baixa tensão deve ficar fisicamente separado de condutores de potência e de cabos do inversor de frequência. Ruído elétrico não é resolvido apenas trocando a biblioteca.
Fixe o ambiente antes de medir
Crie o projeto no PlatformIO e fixe as bibliotecas. O objetivo é evitar que duas compilações instalem APIs diferentes sem que ninguém perceba.
| 1 | [env:esp32-motor-monitor] |
| 2 | platform = espressif32 |
| 3 | board = esp32dev |
| 4 | framework = arduino |
| 5 | monitor_speed = 115200 |
| 6 | lib_deps = |
| 7 | adafruit/Adafruit MPU6050@^2.2.6 |
| 8 | adafruit/Adafruit BusIO@^1.16.2 |
| 9 | adafruit/Adafruit MAX31855 library@^1.4.2 |
| 10 | knolleary/PubSubClient@^2.8 |
| 11 | bblanchon/ArduinoJson@^7.2.1 |
Comece com o ESP32 na bancada, sem o motor e sem MQTT. Primeiro confirme que o MPU6050 responde no I2C, depois confira a leitura do MAX31855 e só então ligue a aquisição contínua.
Leitura do MPU6050: o número bruto não é o diagnóstico
O acelerômetro entrega aceleração nos eixos X, Y e Z. A gravidade aparece como componente contínua, então uma placa parada sobre a bancada ainda mostra aproximadamente 1 g em um eixo. Para estudar vibração, remova a média de cada janela antes de calcular RMS.
Uma janela de 128 amostras a 1 kHz dura cerca de 128 ms, que é a janela usada no firmware do kit. Isso serve para acompanhar tendência lenta, mas não transforma o MPU6050 em analisador de vibração de alta frequência: janela curta significa resolução grosseira em frequência, e é o primeiro parâmetro a aumentar quando a RAM permitir.
| 1 | // Remove a media da janela antes do RMS: a media carrega a |
| 2 | // gravidade, que e componente continua e nao e vibracao. |
| 3 | float rmsSemGravidade(const float* amostras, size_t n) { |
| 4 | if (n == 0) return 0.0f; |
| 5 | float media = 0.0f; |
| 6 | for (size_t i = 0; i < n; ++i) media += amostras[i]; |
| 7 | media /= static_cast<float>(n); |
| 8 | float somaQuadrados = 0.0f; |
| 9 | for (size_t i = 0; i < n; ++i) { |
| 10 | const float ac = amostras[i] - media; |
| 11 | somaQuadrados += ac * ac; |
| 12 | } |
| 13 | return sqrtf(somaQuadrados / static_cast<float>(n)); |
| 14 | } |
O valor RMS é uma medida de energia média da janela. Ele não diz sozinho qual é a causa. Um desalinhamento, um rolamento danificado, uma base frouxa e uma mudança de carga podem aumentar o mesmo indicador.
Pico e fator de crista
Guarde também o maior valor absoluto da janela. A relação entre pico e RMS é o fator de crista:
| 1 | fator de crista = pico / RMS |
Um RMS crescendo lentamente pode indicar desgaste ou desequilíbrio. Um fator de crista alto com RMS ainda baixo pode revelar impactos curtos, folga ou início de dano em rolamento. Não use um número universal para separar normal e falha: faça a linha de base da sua máquina, na sua fixação, com carga conhecida.
Onde a FFT ajuda
O RMS responde quanto de energia existe na janela. A FFT ajuda a responder onde essa energia está. O resultado pode mostrar uma componente próxima da rotação, harmônicas e bandas que merecem investigação.
Para uma primeira versão, não faça a FFT dentro do mesmo laço que precisa manter a rede e os alarmes responsivos. Colete a janela, sinalize que ela está pronta, processe em uma etapa controlada e publique o resumo. O dashboard deve receber indicadores úteis, não milhares de amostras sem contexto.
A resolução da FFT é aproximadamente taxa de amostragem dividida pelo número de pontos. Com 1 kHz e as 128 amostras do kit, cada bin cobre cerca de 7,8 Hz — grosseiro demais para separar rotação de harmônica em um motor de 1750 rpm, que gira a 29 Hz. Para chegar perto de 1 Hz por bin você precisa de 1024 pontos na mesma taxa. E nenhuma resolução corrige uma montagem ruim nem remove ruído do inversor.
Temperatura: trate falhas como qualidade ruim
O MAX31855 pode informar circuito aberto, curto ou erro de conversão. Em qualquer uma dessas condições, não publique zero como se fosse temperatura válida. Zero é um valor possível; o campo de qualidade existe justamente para distinguir valor de falha.
Uma convenção simples para este projeto:
| 1 | 192 boa termopar válido, relógio sincronizado, leitura normal |
| 2 | 64 incerta relógio ainda sem NTP ou valor fora da faixa esperada |
| 3 | 0 ruim termopar aberto, curto ou sensor sem resposta |
Se a temperatura sair de uma faixa plausível, registre a causa e publique qualidade incerta ou ruim conforme o caso. Não esconda o diagnóstico substituindo a leitura por 0, 999 ou pelo último valor sem marcar que ele está velho.
Alarmes devem ter histerese
Um limite simples comuta o alarme a cada leitura quando o valor fica perto da fronteira. Use dois limites: um para ligar e outro para desligar.
Por exemplo, uma política provisória pode ligar o alerta térmico acima de 80 °C e só desligá-lo quando cair abaixo de 75 °C. Os valores são apenas exemplo; o limite real depende do motor, da classe de isolamento, da carga, do fabricante e do método de medição.
Para vibração, prefira avaliar a tendência e a mudança relativa sobre a linha de base. Um limite absoluto tirado de uma tabela genérica pode gerar alarme falso em uma máquina e deixar outra passar. A ISO 10816/ISO 20816 deve orientar a engenharia da aplicação, não ser usada como selo automático para um MPU6050 montado em uma placa de desenvolvimento.
Publicação MQTT: o contrato do SCADA
Use um tópico estável por grandeza e deixe os valores na carga. Um exemplo de hierarquia:
| 1 | usina1/linha2/motor03/telemetria |
| 2 | usina1/linha2/motor03/status |
| 3 | usina1/linha2/motor03/alarmes |
Retenha o último estado de telemetria e o status do gateway, mas não retenha comando nem alarme momentâneo. Um comando retido pode ser reexecutado quando o SCADA reconectar. O status deve conter uptime, RSSI, versão do firmware e motivo do último reset.
O Last Will do MQTT deve publicar offline se o gateway perder a conexão sem despedida. Ao conectar, publique online com retenção. Assim o SCADA diferencia motor estável de gateway morto.
Código de aquisição e publicação
O trecho abaixo é uma base de integração. Ele mostra a ordem dos cuidados, não um certificado de desempenho industrial. O restante do firmware precisa cuidar de Wi-Fi, NTP, reconexão MQTT sem laço bloqueante, watchdog e armazenamento de configuração.
| 1 | #include <WiFi.h> |
| 2 | #include <PubSubClient.h> |
| 3 | #include <Adafruit_MPU6050.h> |
| 4 | #include <Adafruit_MAX31855.h> |
| 5 | #include <ArduinoJson.h> |
| 6 | #include <time.h> |
| 7 | // --- sensores e transporte -------------------------------------------- |
| 8 | Adafruit_MPU6050 mpu; |
| 9 | Adafruit_MAX31855 termopar(18, 5, 19); |
| 10 | WiFiClient wifiClient; |
| 11 | PubSubClient mqtt(wifiClient); |
| 12 | // --- janela de aquisicao ---------------------------------------------- |
| 13 | constexpr size_t JANELA = 128; |
| 14 | constexpr uint32_t INTERVALO_AMOSTRA_US = 1000; |
| 15 | float magnitude[JANELA]; |
| 16 | // A cadencia sai de um prazo acumulado, nao de um delay depois da leitura. |
| 17 | // Com delay, o tempo da transacao I2C soma a cada volta e a taxa real cai |
| 18 | // abaixo de 1 kHz, invalidando qualquer conta de frequencia feita depois. |
| 19 | void coletarJanela() { |
| 20 | uint32_t proxima = micros(); |
| 21 | for (size_t i = 0; i < JANELA; ++i) { |
| 22 | while ((int32_t)(micros() - proxima) < 0) yield(); |
| 23 | proxima += INTERVALO_AMOSTRA_US; |
| 24 | sensors_event_t aceleracao, giro, temperatura; |
| 25 | mpu.getEvent(&aceleracao, &giro, &temperatura); |
| 26 | const float ax = aceleracao.acceleration.x / 9.80665f; |
| 27 | const float ay = aceleracao.acceleration.y / 9.80665f; |
| 28 | const float az = aceleracao.acceleration.z / 9.80665f; |
| 29 | magnitude[i] = sqrtf(ax * ax + ay * ay + az * az); |
| 30 | } |
| 31 | } |
| 32 | bool relogioSincronizado() { |
| 33 | return time(nullptr) > 1700000000; |
| 34 | } |
| 35 | void publicarResumo(float rms, float pico, float temperaturaC, int qualidade) { |
| 36 | JsonDocument doc; |
| 37 | doc["ts"] = relogioSincronizado() ? (uint32_t)time(nullptr) : 0; |
| 38 | doc["temperature_c"] = temperaturaC; |
| 39 | doc["vibration_rms_g"] = rms; |
| 40 | doc["vibration_peak_g"] = pico; |
| 41 | doc["crest_factor"] = rms > 0.001f ? pico / rms : 0.0f; |
| 42 | doc["quality"] = qualidade; |
| 43 | doc["sample_count"] = JANELA; |
| 44 | char payload[384]; |
| 45 | serializeJson(doc, payload, sizeof(payload)); |
| 46 | mqtt.publish("usina1/linha2/motor03/telemetria", payload, true); |
| 47 | } |
O trecho reduz cada volta a um número só, a magnitude do vetor de aceleração, e é sobre ela que o RMS é calculado — o mesmo que o firmware do kit faz, para que os valores do artigo e do pacote sejam comparáveis. A magnitude é prática para tendência, mas reduz as três direções a um escalar e perde a informação de eixo; quando quiser diagnosticar em vez de só acompanhar, guarde o RMS de cada eixo separadamente. Para análise espectral, aumente a janela conforme a RAM disponível, aplique uma janela matemática antes da FFT e valide a taxa de amostragem real com um sinal conhecido. Não use delay() longo enquanto pretende manter heartbeat, MQTT e watchdog funcionando.
Ordem de validação na bancada
Passo 1: confirmar alimentação e barramentos
Com o motor desligado e o conjunto fora da área de risco, rode um scanner I2C. O MPU6050 precisa aparecer em 0x68 ou 0x69. Depois leia o MAX31855 com o termopar em temperatura ambiente e confirme que não há flag de circuito aberto.
Passo 2: validar a gravidade
Com o sensor parado, gire a placa lentamente em cada eixo. A aceleração resultante deve permanecer próxima de 1 g, descontando tolerância e ruído. Se o valor variar muito parado, revise alimentação, fixação e configuração da faixa do acelerômetro.
Passo 3: criar a linha de base
Registre alguns minutos com o motor em vazio, depois em uma condição de carga conhecida. Guarde RMS, pico, fator de crista, temperatura, rotação e horário. Uma linha de base sem o contexto de carga não é linha de base; é apenas um número.
Passo 4: comparar orientação e posição
Faça uma segunda medição no mesmo motor, no mesmo ponto e com a mesma orientação. Se a repetição variar mais que a tendência que você quer detectar, o problema ainda é mecânico ou de aquisição, não de MQTT.
Passo 5: testar uma falha simulada com segurança
Não afrouxe parafuso, remova proteção ou introduza defeito em uma máquina energizada. Para testar o pipeline, publique valores de teste em um tópico separado ou use um gerador de carga controlado pela engenharia. O alarme deve aparecer, permanecer enquanto a condição existir e desaparecer apenas depois da histerese.
Passo 6: testar a rede caindo
Derrube o broker por alguns minutos com o sensor lendo. O firmware deve continuar coletando ou sinalizar explicitamente que não consegue preservar a janela, sem travar o laço inteiro. Quando a rede voltar, publique o timestamp da leitura e não o horário da reconexão.
Passo 7: testar reinício e qualidade
Desligue o gateway de propósito. O SCADA precisa marcar o status como offline pelo Last Will ou pela ausência do heartbeat. Desconecte o termopar em bancada e confirme que a temperatura não vira zero com qualidade boa.
Erros que parecem problema de sensor
O RMS sobe quando alguém toca no gabinete. A fixação está medindo a própria caixa ou há cabo solto. Reforce a montagem e repita a linha de base.
A temperatura fica em 0 °C depois de uma falha. O firmware está escondendo erro de termopar. Separe valor e qualidade e trate a flag do MAX31855.
O gráfico muda quando o motor troca de carga. Isso pode ser comportamento normal do processo. Publique carga, rotação ou estado operacional junto com a telemetria.
O alarme oscila perto do limite. Falta histerese, tempo mínimo de permanência ou uma janela de avaliação.
O SCADA mostra tudo no mesmo horário. O timestamp está sendo criado no broker ou no consumidor. Carimbe a leitura no ESP32 depois de sincronizar o relógio.
A FFT mostra picos que mudam a cada leitura. A janela é curta demais, o sensor está frouxo, a taxa de amostragem não é estável ou há aliasing. Valide a aquisição antes de interpretar o espectro.
O gateway reinicia quando publica. Verifique fonte, heap, tamanho do JSON e o custo do TLS. Logue o motivo de reset e observe a memória livre antes e depois da conexão.
O projeto diz que atende ISO só porque calculou RMS. RMS é um indicador; conformidade depende de sensor, montagem, banda, calibração, procedimento e avaliação da máquina.
O resultado esperado deste projeto é uma tendência confiável o suficiente para orientar uma inspeção: temperatura, vibração, qualidade e contexto no mesmo histórico. A decisão de parar ou liberar um motor continua sendo da engenharia responsável pela máquina.
