Como usar acelerômetro com ESP8266 NodeMCU 63

O assunto IoT (Internet das Coisas) está em alta e por isso vem surgindo inúmeras plataformas de desenvolvimento para esse tipo de solução. Uma delas, provavelmente a mais interessante e utilizada pelos makers, é o módulo Wifi ESP8266 NodeMCU. Além desse pequeno módulo conter I/O’s, regulador de tensão e conectividade USB que facilita programação via IDE do Arduino, contém um módulo WiFi que possibilita conexão à nuvem. E é essa conexão que vamos utilizar para ligar um acelerômetro com ESP8266 NodeMCU, enviando os dados para uma página web.

Acelerômetro com ESP8266 NodeMCU

Antes de mostrarmos o funcionamento do acelerômetro com ESP8266 NodeMCU, recomendamos a leitura do post Tutorial: Acelerômetro MPU6050 com Arduino.

Um Pouco de Teoria Sobre o MPU6050 e sua Comunicação I2C

O MPU6050 é uma IMU (Inertial Measurement Unit), que mede valores de aceleração em 3 eixos, X, Y e Z e velocidade angular também em X, Y e Z. Por isso esse sensor tem 6 graus de liberdade (6DOF). Além dessas medições o sensor também pode medir temperaturas de -40 a 80°C. O sensor ainda conta com um DMP(Digital Motion Processor) que pode realizar inúmeros cálculos e algoritmos complexos dentro do próprio MPU6050. Entre esses algoritmos temos detecção de passos, tap-detection, cálculos de ângulo e muito mais. Mais informações sobre o sensor podem ser encontradas no datasheet e no site da InveSense.

O protocolo I2C, que é um protocolo estilo mestre/escravo, consiste basicamente em leitura e escrita de valores em determinados registros. Isso é feito através do envio e recebimento de bits 0 e 1 de uma forma ordenada e em sequência. Para saber mais leia este pequeno resumo.

No caso deste projeto, temos o NodeMCU como mestre e o MPU6050 como escravo. De acordo com mapa de registro do MPU6050, o endereço I2C padrão do MPU6050 é 0x68 podendo ser alterado para 0x69 conectando o pino AD0 para 3,3V, ou seja, podemos utilizar até dois desses sensores em conjunto. Os valores enviados pelo MPU6050 são valores puros (raw data) que, se desejado, podem ser convertidos para ângulos utilizando-se de cálculos ou algoritmos.

Circuito acelerômetro com ESP8266 NodeMCU

Para montagem do circuito do acelerômetro com ESP8266 NodeMCU foram utilizados os seguintes materiais:

A ligação do circuito foi feita da seguinte maneira:

Pinos NodeMCU            Pinos MPU6050
     D5          ->          SDA
     D6          ->          SCL
     Vin         ->          VCC
     GND         ->          GND

Circuito acelerômetro com ESP8266 NodeMCU

O pino Vin do NodeMCU possui 5V, que é a mesma tensão ligada ao conector USB. Com este pino podemos alimentar o MPU6050. O acelerômetro em si opera a 3,3V mas como placa GY-251 possui um regulador de tensão, podemos utilizar 5V sem problemas para alimentação. As linhas de SDA e SCL de comunicação I2C possuem na placa resistores de pull-up para 3,3V de acordo com seu esquemático. Sendo assim, a comunicação I2C pode ser realizada diretamente no NodeMCU que também opera a 3,3V. Ou seja, tudo é energizado via USB 5V e ambas as placas regulam para suas tensões de operação 3,3V.

Configuração da IDE Arduino para o NodeMCU

O NodeMCU pode ser facilmente programado usando a IDE do Arduino como visto no post Como programar o NodeMCU com IDE Arduino. 

Entre na IDE do Arduino e clique em Arquivo -> Preferências:

Menu Preferências IDE Arduino

Na tela seguinte, digite o link abaixo no campo URLs adicionais de Gerenciadores de Placas:

http://arduino.esp8266.com/stable/package_esp8266com_index.json

A sua tela ficará assim:

Tela Preferências IDE Arduino

Clique em OK para retornar à tela principal da IDE

Agora clique em Ferramentas -> Placa -> Gerenciador de Placas:

Menu Gerenciador de Placas IDE Arduino

Utilize a barra de rolagem para encontrar o esp8266 by ESP8266 Community e clique em Instalar.

Tela Gerenciador de Placas IDE Arduino

Assim teremos disponíveis as placas da linha ESP8266, suas bibliotecas e exemplos incluídos.

No menu Ferramentas -> Placas, selecione a placa NodeMCU 1.0 (ESP 12-E module)

Menu Placas IDE Arduino

Instalação da biblioteca ArduinoJSON

Este projeto usará a biblioteca ArduinoJson.h que fará a conversão dos dados do MPU6050 em formato JSON.

Para instalá-la clique em Sketch -> Incluir Biblioteca -> Gerenciar de Bibliotecas…

Menu Gerenciador de Bibliotecas IDE Arduino

No campo Refine sua busca… procure por json, selecione a biblioteca ArduinoJson by Benoit Blanchon e clique em instalar.

Tela Gerenciador de Bibliotecas IDE Arduino

Programação do NodeMCU

Para comunicação com o sensor temos basicamente duas funções usando Wire, uma de escrita e outra de leitura de registros do sensor. A partir dessas duas funções podemos realizar diversas tarefas com o sensor, como por exemplo, inicializá-lo, verificar a comunicação, escolher as escalas, ler os valores entre outras.

As funções de escrita e leitura de registros são writeRegMPU() e readRegMPU()  que encotram-se nas linhas de código 68 e 79 respectivamente.

Para que as leituras do sensor sejam enviadas ao servidor o programa formata esses dados em JSON usando a bibliotexa ArduinoJSON resultando no seguinte formato:

{
  "data" : {
    "accel" : {
      "accelX" : xxxx,
      "accelY" : xxxx,
      "accelZ" : xxxx
    },
    "gyro" : {
      "gyroX" : xxxx,
      "gyroY" : xxxx,
      "gyroZ" : xxxx
    },
    "temp" : xxxx
  },
  "nodeID" : "mcu1"
}

Com os dados convertidos para JSON eles estão prontos para serem enviados à internet.

Exibição dos Dados na Página Web

Para melhor visualização dos dados do acelerômetro com ESP8266 NodeMCU, foi desenvolvido um Web Server em NodeJS instalado em uma Rasberry Pi 3 que responde a requisições HTTP como GET e POST.

O NodeMCU envia uma requisição POST no link /accel com as leituras do sensor em formato JSON. A requisição segue o seguinte formato:

POST /accel HTTP/1.1 
Host: 192.168.0.24:3000
Content-Type: application/json
Content-Length: tamanho do JSON
conteúdo JSON

O servidor então recebe esses dados e exibe em tempo real para os clientes que acessam o servidor via browser.

Para que o NodeMCU saiba sua geolocalização, foi utilizada a API do site ip-api.com. O NodeMCU realiza um HTTP GET request no link /json e recebe de volta o seguinte JSON:

{ 
	"city":"Florianópolis",
	"country":"Brazil",
	"lat":-27.5833,
	"lon":-48.5667,
	"query":"186.xxx.xx.xx",
	"region":"SC"
}

Assim que o NodeMCU recebe sua geolocalização ele repassa para o servidor que exibe então, em um Google Maps.

O servidor exibe a seguinte página para os clientes que o acessam via browser:

Tela Página Web de Monitoramento Remoto

O código completo do servidor escrito em Node.js pode ser encontrado no GitHub.

Código acelerômetro com ESP8266 NodeMCU

Update 24/09/2019: A versão do ArduinoJSON foi atualizada para a versão 6, portanto alguns ajustes devem ser feitos. Confira o link!

//Programa: Acelerometro com ESP8266 NodeMCU
#include <ESP8266WiFi.h> // biblioteca para usar as funções de Wifi do módulo ESP8266
#include <Wire.h>         // biblioteca de comunicação I2C
#include <ArduinoJson.h>  // biblioteca JSON para sistemas embarcados

/*
 * Definições de alguns endereços mais comuns do MPU6050
 * os registros podem ser facilmente encontrados no mapa de registros do MPU6050
 */
const int MPU_ADDR =      0x68; // definição do endereço do sensor MPU6050 (0x68)
const int WHO_AM_I =      0x75; // registro de identificação do dispositivo
const int PWR_MGMT_1 =    0x6B; // registro de configuração do gerenciamento de energia
const int GYRO_CONFIG =   0x1B; // registro de configuração do giroscópio
const int ACCEL_CONFIG =  0x1C; // registro de configuração do acelerômetro
const int ACCEL_XOUT =    0x3B; // registro de leitura do eixo X do acelerômetro

const int sda_pin = D5; // definição do pino I2C SDA
const int scl_pin = D6; // definição do pino I2C SCL

bool led_state = false;

// variáveis para armazenar os dados "crus" do acelerômetro
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ; 

// Definições da rede Wifi
const char* SSID = "Nome da Rede WiFi";
const char* PASSWORD = "Senha da Rede Wifi";

// endereço IP local do Servidor Web instalado na Raspberry Pi 3
// onde será exibida a página web
const char* rpiHost = "192.168.0.24";  

// servidor que disponibiliza serviço de geolocalização via IP    
const char* IpApiHost = "ip-api.com";   

WiFiClient client;

// construindo o objeto JSON que irá armazenar os dados do acelerômetro na função populateJSON()
StaticJsonBuffer<300> jsonBuffer;
JsonObject& object = jsonBuffer.createObject();
JsonObject& data = object.createNestedObject("data");
  
JsonObject& accel = data.createNestedObject("accel");
JsonObject& temp = data.createNestedObject("temp");
JsonObject& gyro = data.createNestedObject("gyro");
  
JsonObject& accelX = accel.createNestedObject("accelX");
JsonObject& accelY = accel.createNestedObject("accelY");
JsonObject& accelZ = accel.createNestedObject("accelZ");

JsonObject& gyroX = gyro.createNestedObject("gyroX");
JsonObject& gyroY = gyro.createNestedObject("gyroY");
JsonObject& gyroZ = gyro.createNestedObject("gyroZ");

/*
 * função que configura a I2C com os pinos desejados 
 * sda_pin -> D5
 * scl_pin -> D6
 */
void initI2C() 
{
  //Serial.println("---inside initI2C");
  Wire.begin(sda_pin, scl_pin);
}

/*
 * função que escreve um dado valor em um dado registro
 */
void writeRegMPU(int reg, int val)      //aceita um registro e um valor como parâmetro
{
  Wire.beginTransmission(MPU_ADDR);     // inicia comunicação com endereço do MPU6050
  Wire.write(reg);                      // envia o registro com o qual se deseja trabalhar
  Wire.write(val);                      // escreve o valor no registro
  Wire.endTransmission(true);           // termina a transmissão
}

/*
 * função que lê de um dado registro
 */
uint8_t readRegMPU(uint8_t reg)        // aceita um registro como parâmetro
{
  uint8_t data;
  Wire.beginTransmission(MPU_ADDR);     // inicia comunicação com endereço do MPU6050
  Wire.write(reg);                      // envia o registro com o qual se deseja trabalhar
  Wire.endTransmission(false);          // termina transmissão mas continua com I2C aberto (envia STOP e START)
  Wire.requestFrom(MPU_ADDR, 1);        // configura para receber 1 byte do registro escolhido acima
  data = Wire.read();                   // lê o byte e guarda em 'data'
  return data;                          //retorna 'data'
}

/*
 * função que procura pelo sensor no endereço 0x68
 */
void findMPU(int mpu_addr)
{
  Wire.beginTransmission(MPU_ADDR);
  int data = Wire.endTransmission(true);

  if(data == 0)
  {
    Serial.print("Dispositivo encontrado no endereço: 0x");
    Serial.println(MPU_ADDR, HEX);
  }
  else 
  {
    Serial.println("Dispositivo não encontrado!");
  }
}

/*
 * função que verifica se o sensor responde e se está ativo
 */
void checkMPU(int mpu_addr)
{
  findMPU(MPU_ADDR);
    
  int data = readRegMPU(WHO_AM_I); // Register 117 – Who Am I - 0x75
  
  if(data == 104) 
  {
    Serial.println("MPU6050 Dispositivo respondeu OK! (104)");

    data = readRegMPU(PWR_MGMT_1); // Register 107 – Power Management 1-0x6B

    if(data == 64) Serial.println("MPU6050 em modo SLEEP! (64)");
    else Serial.println("MPU6050 em modo ACTIVE!"); 
  }
  else Serial.println("Verifique dispositivo - MPU6050 NÃO disponível!");
}

/*
 * função de inicialização do sensor
 */
void initMPU()
{
  setSleepOff();
  setGyroScale();
  setAccelScale();
}

/* 
 *  função para configurar o sleep bit  
 */
void setSleepOff()
{
  writeRegMPU(PWR_MGMT_1, 0); // escreve 0 no registro de gerenciamento de energia(0x68), colocando o sensor em o modo ACTIVE
}

/* função para configurar as escalas do giroscópio
   registro da escala do giroscópio: 0x1B[4:3]
   0 é 250°/s

    FS_SEL  Full Scale Range
      0        ± 250 °/s      0b00000000
      1        ± 500 °/s      0b00001000
      2        ± 1000 °/s     0b00010000
      3        ± 2000 °/s     0b00011000
*/
void setGyroScale()
{
  writeRegMPU(GYRO_CONFIG, 0);
}

/* função para configurar as escalas do acelerômetro
   registro da escala do acelerômetro: 0x1C[4:3]
   0 é 250°/s

    AFS_SEL   Full Scale Range
      0           ± 2g            0b00000000
      1           ± 4g            0b00001000
      2           ± 8g            0b00010000
      3           ± 16g           0b00011000
*/
void setAccelScale()
{
  writeRegMPU(ACCEL_CONFIG, 0);
}

/* função que lê os dados 'crus'(raw data) do sensor
   são 14 bytes no total sendo eles 2 bytes para cada eixo e 2 bytes para temperatura:

  0x3B 59 ACCEL_XOUT[15:8]
  0x3C 60 ACCEL_XOUT[7:0]
  0x3D 61 ACCEL_YOUT[15:8]
  0x3E 62 ACCEL_YOUT[7:0]
  0x3F 63 ACCEL_ZOUT[15:8]
  0x40 64 ACCEL_ZOUT[7:0]

  0x41 65 TEMP_OUT[15:8]
  0x42 66 TEMP_OUT[7:0]

  0x43 67 GYRO_XOUT[15:8]
  0x44 68 GYRO_XOUT[7:0]
  0x45 69 GYRO_YOUT[15:8]
  0x46 70 GYRO_YOUT[7:0]
  0x47 71 GYRO_ZOUT[15:8]
  0x48 72 GYRO_ZOUT[7:0]
   
*/
void readRawMPU()
{  
  Wire.beginTransmission(MPU_ADDR);       // inicia comunicação com endereço do MPU6050
  Wire.write(ACCEL_XOUT);                       // envia o registro com o qual se deseja trabalhar, começando com registro 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);            // termina transmissão mas continua com I2C aberto (envia STOP e START)
  Wire.requestFrom(MPU_ADDR, 14);         // configura para receber 14 bytes começando do registro escolhido acima (0x3B)

  AcX = Wire.read() << 8;                 // lê primeiro o byte mais significativo
  AcX |= Wire.read();                     // depois lê o bit menos significativo
  AcY = Wire.read() << 8;
  AcY |= Wire.read();
  AcZ = Wire.read() << 8;
  AcZ |= Wire.read();

  Tmp = Wire.read() << 8;
  Tmp |= Wire.read();

  GyX = Wire.read() << 8;
  GyX |= Wire.read();
  GyY = Wire.read() << 8;
  GyY |= Wire.read();
  GyZ = Wire.read() << 8;
  GyZ |= Wire.read(); 

  Serial.print("AcX = "); Serial.print(AcX);
  Serial.print(" | AcY = "); Serial.print(AcY);
  Serial.print(" | AcZ = "); Serial.print(AcZ);
  Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);
  Serial.print(" | GyX = "); Serial.print(GyX);
  Serial.print(" | GyY = "); Serial.print(GyY);
  Serial.print(" | GyZ = "); Serial.println(GyZ);

  led_state = !led_state;
  digitalWrite(LED_BUILTIN, led_state);         // pisca LED do NodeMCU a cada leitura do sensor
  delay(50);                                        
}

/*
 * função que conecta o NodeMCU na rede Wifi
 * SSID e PASSWORD devem ser indicados nas variáveis
 */
void reconnectWiFi() 
{
  if(WiFi.status() == WL_CONNECTED)
    return;

  WiFi.begin(SSID, PASSWORD);

  while(WiFi.status() != WL_CONNECTED) {
    delay(100);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("Conectado com sucesso na rede: ");
  Serial.println(SSID);
  Serial.print("IP obtido: ");
  Serial.println(WiFi.localIP());  
}

void initWiFi()
{
  delay(10);
  Serial.print("Conectando-se na rede: ");
  Serial.println(SSID);
  Serial.println("Aguarde");

  reconnectWiFi();
}

/*
 * função que armazena cada dado do sensor em um objeto JSON
 * utiliza a biblioteca ArduinoJson
 */
void populateJSON()
{
  object["nodeID"] = "mcu1";

  accel["accelX"] = AcX;
  accel["accelY"] = AcY;
  accel["accelZ"] = AcZ;

  data["temp"] = Tmp/340.00+36.53;

  gyro["gyroX"] = GyX;
  gyro["gyroY"] = GyY;
  gyro["gyroZ"] = GyZ;
}

/*
 * função que envia os dados do sensor para o servidor em formato JSON
 * faz um POST request ao servidor 
 */
void makePOST()
{
  if(!client.connect(rpiHost, 3000))     // aqui conectamos ao servidor
  {
    Serial.println("Não foi possível conectar ao servidor!n");
  }
  else
  {    
    Serial.println("Conectado ao servidor");
    // Make HTTP POST request    
    client.println("POST /accel HTTP/1.1");
    client.println("Host: 192.168.0.24");
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.println(object.measureLength());
    client.println();
    object.printTo(client);    // enviamos os dados em JSON    
  }
}

/*
 * Função que realiza GET request no site ip-api.com
 * Esse site disponibiliza uma API de geolocalização via IP
 * A função retorna um JSON com dados de geolocalização
 * Os dados de geolocalização são exibidos na página web em um Google Maps
 */
String makeGETlocation()
{
  if ( !client.connect(IpApiHost, 80) ) {
    Serial.println("connection ao ip-api.com falhou");
    return "connection failed";
  }
  
  // Realiza HTTP GET request
  client.println("GET /json/?fields=8405 HTTP/1.1");
  client.print("Host: ");
  client.println(IpApiHost);
  client.println("Connection: close");
  client.println();

  // recebe o Header de resposta
  while (client.connected()) {
    String data = client.readStringUntil('n');
    if (data == "r") {
      break;
    }
  }
  // recebe os dados de geolocalização em formato JSON e guarda na variável data
  String data = client.readStringUntil('n');
  Serial.println("Dados de geolocalização recebidosn");
  Serial.println(data);  
  return data; 
}

/*
 * Função que envia ao servidor a localização do NodeMCU
 * função realiza um POST request ao servidor no link /location
 * o servidor por sua vez exibe a localização do NodeMCU no Google Maps
 */
void makePOSTlocation()
{
  String location = makeGETlocation(); // guarda o JSON de geolocalização na variável location
  if(!client.connect(rpiHost, 3000))     // aqui conectamos ao servidor
  {
    Serial.print("Could not connect to host: n");
    Serial.print(rpiHost);
  }
  else
  {
    // realiza HTTP POST request    
    client.println("POST /location HTTP/1.1");
    client.println("Host: 192.168.0.24");
    client.println("Content-Type: application/json");
    client.print("Content-Length: ");
    client.println(location.length());
    client.println();
    client.println(location);    // enviamos o JSON ao servidor
  }
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);

  Serial.println("nIniciando configuração WiFin");
  initWiFi();

  Serial.println("nIniciando configuração do MPU6050n");
  initI2C();
  initMPU();
  checkMPU(MPU_ADDR);

  Serial.println("Enviando localização ao servidorn");
  makePOSTlocation();

  Serial.println("nConfiguração finalizada, iniciando loopn");  
}

void loop() {
  readRawMPU();    // lê os dados do sensor
  populateJSON();  // transforma os dados em formato JSON
  makePOST();      // envia os dados ao servidor  
  delay(100);  
}

 

Conclusão

Neste artigo foi apresentado um sistema de monitoramento remoto de um acelerômetro com ESP8266 NodeMCU usando um sensor MPU6050, cobrindo temas teóricos como comunicação I2C e o modo de comunicação do MPU6050. Fizemos com que a placa Wifi NodeMCU se portasse como um Web Client, enviando as leituras do MPU6050 a um servidor através de HTTP requests como também seus dados de geolocalização.

Gostou do post do acelerômetro com ESP8266 NodeMCU? Deixe seu comentário logo abaixo.

Faça seu comentário

Acesse sua conta e participe

63 Comentários

  1. Fantástica tratativa desse modulo. A melhor que já li. Parabéns. Esse site é sempre excelente.

  2. Olá, uma duvida conceitual, neste exemplo é usado os pinos D5 e D6 para configurar o I2C.
    Então para que serve os pinos SDD1,SDD2,SDD3,SDCMD ?
    Para I2C tem que ser sempre esses pinos D5 e D6, ou pode ser qualquer outro?

    1. Olá Fábio!

      Para I2C no NodeMCU ESP8266 serão sempre os pinos D5 e D6, pois é a interface que o micro controlador disponibiliza.

      Os pinos SDD1, SDD2, SDD3 e SDCMD são referentes à interface SDIO(Secure Digital Input/Output Interface), que é outra interface disponibilizada pelo ESP8266, conforme você pode conferir aqui: https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf logo na página 1.

      Abraços!
      Vinícius – Equipe MakerHero

  3. Alguém tem esse código com as correçoes para JSON6 ?

  4. Olá, Giovanni!
    Seria possível utilizar o protocolo MQTT no lugar do HTTP nesse caso?

  5. Pelos comentários escritos, alguns encontraram problemas com as leituras e valores…
    Existe um erro básico na montagem: foi usado o pino de entrada de alimentação (Vin) do ESP8266 para alimentar a placa do acelerômetro, isso pode causar instabilidades funcionais no circuito.
    O correto seria usar o pino 3v3 do ESP8266 para alimentar a outra placa.
    O pino Vin é a entrada de um regulador de tensão na placa do ESP8266 que pode sofrer flutuações na baixa corrente fornecida pela saída USB de um notebook ou PC, afetando a correta funcionalidade da placa do acelerômetro.

  6. Olá! Obrigado pelo material! “readRegMPU” retornando zero, o que pode ser?

      1. Olá, Vitalli,

        Consegue detalhar melhor o problema?

        Abraços!
        Diogo – Equipe MakerHero

        1. Obrigado pelo retorno! O que acontece é que as leituras ficam todas em 0, tanto do acelerômetro quanto do giroscópio. Aparece: “Dispositivo encontrado no endereço: 0x68”, mas depois também aparece: “Verifique dispositivo – MPU6050 NÃO disponível!”. Percebi que na função “checkMPU” “data” vale 0, sendo que deveria valer 104. Isso acontece porque “readRegMPU” está retornando 0.

          1. Também estou com o mesmo problema. Conseguem ajudar?

          2. Agora funcionou! As leituras do sensor estavam todas resultando em zero. Pelo que pesquisei é algo bem comum com ESP32 e MPU6050. O que fiz foi utilizar outra biblioteca do ESP32. Parece que há uma biblioteca que é “incompatível” com o acelerômetro, ou algo assim.

          3. Vitalli,

            É possível disponibilizar a biblioteca para o pessoal aqui nos comentários?

            Abraços!
            Diogo – Equipe MakerHero

            Diogo Zimmermann
          4. Oi, Diogo! O que fiz foi apenas atualizar a própria biblioteca no Arduino IDE mesmo.

  7. Gostei muito do projeto, só que ao aplicá-lo descobri que ele utiliza a versão 5 do arduinojson, você tem o acerto para utilizar a versão 6 do arduinojson?

    1. Olá, Sidnei

      O link para download da placa você se refere?

      Abraços!
      Diogo – Equipe MakerHero

      1. Parece que uma das partes do código do Arduíno a ser modificada (o que não entendi como fazer, por causa da minha inexperiência) devido a nova versão 6 do arduinojson é:

        // construindo o objeto JSON que irá armazenar os dados do acelerômetro na função populateJSON()
        StaticJsonBuffer jsonBuffer;
        JsonObject& object = jsonBuffer.createObject();
        JsonObject& data = object.createNestedObject(“data”);

        JsonObject& accel = data.createNestedObject(“accel”);
        JsonObject& temp = data.createNestedObject(“temp”);
        JsonObject& gyro = data.createNestedObject(“gyro”);

        JsonObject& accelX = accel.createNestedObject(“accelX”);
        JsonObject& accelY = accel.createNestedObject(“accelY”);
        JsonObject& accelZ = accel.createNestedObject(“accelZ”);

        JsonObject& gyroX = gyro.createNestedObject(“gyroX”);
        JsonObject& gyroY = gyro.createNestedObject(“gyroY”);
        JsonObject& gyroZ = gyro.createNestedObject(“gyroZ”);

        Como é para a nova versão?

        1. Olá, Sidnei

          Para a versão 6 do JSON, basta remover o “&” depois de JsonObject. No link abaixo tem a documentação mais detalhada:
          https://arduinojson.org/v6/doc/upgrade/

          Abraços!
          Diogo – Equipe MakerHero

          1. Acertei o código assim:
            StaticJsonDocument doc;

            JsonObject object = doc.createNestedObject(“object”);
            JsonObject data = object.createNestedObject(“data”);
            JsonObject accel = data.createNestedObject(“accel”);
            JsonObject temp = data.createNestedObject(“temp”);
            JsonObject gyro = data.createNestedObject(“gyro”);
            JsonObject accelX = accel.createNestedObject(“accelX”);
            JsonObject accelY = accel.createNestedObject(“accelY”);
            JsonObject accelZ = accel.createNestedObject(“accelZ”);
            JsonObject gyroX = gyro.createNestedObject(“gyroX”);
            JsonObject gyroY = gyro.createNestedObject(“gyroY”);
            JsonObject gyroZ = gyro.createNestedObject(“gyroZ”);

            e mais adiante:
            // da versão 5
            //object.printTo(client); // enviamos os dados em JSON
            // da versão 6
            serializeJson(doc, client);

            Assim consegui compilar e executar, só que ainda não tenho certeza de que os dados são passados corretamente para a página pois o gráficos não se alteram.

          2. Sidnei,

            A página não se altera?

            Abraços!
            Diogo – Equipe MakerHero

            Diogo Zimmermann
  8. solo falta conectarme a internet 192.168.0.17:3000 la pagina no responde la información en monitor serial si es visible y en serial plotter se gráfica con precisión gracias ya conseguire conectarme a internet saludos desde queretaro mexico

    1. Olá Felipe,

      Com o endereço 192.168.0.24 funcionou?

      Abraço!
      Rosana – Equipe MakerHero

  9. Boa noite!

    Depois de arrancar os cabelos que não tenho, gostaria de saber se alguém tem o cod utilizando dois servos motores mais o giroscópio? Um abs!

    1. Olá Luiz!

      Já deu uma olhada em nosso outro projeto?
      https://www.makerhero.com/blog/labirinto-com-arduino-e-mpu6050/

      Lá mostramos como utilizar um acelerômetro para controlar dois servo motores. Espero que ajude.

  10. Bom dia Giovanni,

    Excelente projeto, muito bem explicado!
    Uma pergunta, sempre que eu começo o código, ele funciona por cerca de 30 segundos e depois para de mandar informação, apaga o led azul de transmissão, como se entrasse em algum loop no código. Aí só resetando para voltar a mandar, e sempre nessa faixa de tempo. Alguma ideia do que possa estar causando?

    Obrigado por compartilhar

    1. Olá Victor! Obrigado pela leitura!

      Difícil dizer exatamente o que pode estar acontecendo.
      Uma opção para tentarmos descobrir é colocar mais mensagens de debug Serial.print.
      Analise essas mensagens e veja onde o programa está travando.

      1. Olá Giovanni,

        Eu coloquei alguns Serial debug no código e vi que o programa estava travando na função makePOST().

        void makePOST()
        {
        if(!client.connect(rpiHost, 3000)) // aqui conectamos ao servidor
        {
        Serial.println(“Não foi possível conectar ao servidor!\n”);
        }
        else
        {
        Serial.println(“Conectado ao servidor”);
        // Make HTTP POST request
        client.println(“POST /accel HTTP/1.1”);
        Serial.println(“1”);
        client.println(“Host: 192.168.0.24”);
        Serial.println(“2”);
        client.println(“Content-Type: application/json”);
        Serial.println(“3”);
        client.print(“Content-Length: “);
        Serial.println(“4”);
        client.println(object.measureLength());
        Serial.println(“5”);
        client.println();
        Serial.println(“6”);
        object.printTo(client); // enviamos os dados em JSON
        Serial.println(“7”);
        }
        }

        O que estava acontecendo era que, depois de algum tempo, cada uma dessas funções client demorava mais para finalizar, de 5-15 segundos para as funções de 1 a 6 e próximo de dois minutos para a função 7. Porém, depois de passar isso o programa volta a funcionar por mais ou menos o mesmo tempo de antes, e isso se repete. As vezes ele trava mais vezes também. Alguma ideia do que possa ser? Pensei que fosse alguma falha de conexão com a internet, mas aqui costuma funcionar bem.

        Obrigado pela ajuda!

        1. Qual servidor você está usando? É uma Raspberry Pi também? Se for uma Rasp, o servidor Nodejs está executando normalmente? O IP do seu servidor é o mesmo que está no código 192.168.0.24?

  11. Sou novo aqui e nao entendo muito de arduino. Comprei este modulo ESP8266 de voces e segui todos os passos do post mas nao consigo fazer meu notebook reconhecer a placa. Ja tentei de tudo e nao consigo.
    Tem como me ajudar? Precisa de alguma outra informacao?
    Te agradeco

    1. Olá Thiago!

      Está usando Windows? aparece algum erro no gerenciador de dispositivos? O Windows reconhece alguma porta COM no gerenciador de dispositivos? A IDE Arduino reconhece alguma porta COM no menu portas?

      Por favor teste também em outros computadores, outros cabos, outras portas USB.
      Faça também a reinstalação da IDE Arduino e do suporte a ESP8266 para IDE Arduino.

      Caso ainda não funcione por favor envie um e-mail para [email protected] explicando sua situação.

      Abraço!

  12. Acho que tem um pequeno erro no Post. É dito que a placa é a “GY-251” em algumas seções, Quando na verdade, se trata da “GY-521”. Abs.

  13. Cumprimentos Engº Giovanni; Eu tenho uma pergunta fora do assunto:

    Gostaria de saber se é possível usar o ESP8266 NodeMCU em lugar do Arduino Uno, pelo fato de eu ter uma sketch que está ocupando a memória flash do Arduino quase no seu total, a ponto de mostrar a seguinte mensagem: “Pouca memória disponível, problemas de estabilidade podem ocorrer.”

    Experimentei mudar a placa para NodeMCU 1.0 (ESP-12E Module), na IDE do Arduino, então, mostra a seguinte mensagem: “fatal error: avr/pgmspace.h: No such file or directory”

    Obrigado

    1. Olá Daniel!
      Dependendo do seu sketch, ele não vai ser compatível com diferentes placas. Por exemplo um sketch de NodeMCU que contenha funções de WiFi não vai ser compatível com Arduino UNO, pois não tem WiFi. Aí vai dar erro ao tentar compilar.

      Caso seu sketch esteja ficando muito grande, você pode tentar fazer um upgrade para uma placa com mais memória, como Arduino Mega por exemplo. Ela tem 128Kb de flash. O Uno tem apenas 32Kb.

  14. Tenho um problema ao colocar o código. O programa me devolve:

    Conectando-se na rede: wireless
    Aguarde
    ………….
    Conectado com sucesso na rede: wireless
    IP obtido: 192.168.1.10
    nIniciando configuração do MPU6050n
    Dispositivo não encontrado!
    Verifique dispositivo – MPU6050 NÃO disponível!
    Enviando localização ao servidorn
    Dados de geolocalização recebidosn

    Could not connect to host: n192.168.1.10nConfiguração finalizada, iniciando loopn
    AcX = -1 | AcY = -1 | AcZ = -1 | Tmp = 36.53 | GyX = -1 | GyY = -1 | GyZ = -1
    Não foi possível conectar ao servidor!n
    AcX = -1 | AcY = -1 | AcZ = -1 | Tmp = 36.53 | GyX = -1 | GyY = -1 | GyZ = -1

    Você poderia me ajudar por favor?

    1. Olá Jean!

      Verifique as conexões com o sensor na seção “Circuito acelerômetro com ESP8266 NodeMCU”

      Se tiver algum mal contato o programa irá gerar o erro “Dispositivo não encontrado!”

  15. Bom dia,
    estou com um problema. não consigo, de nenhuma maneira, colocar para funcionar isso.
    A minha saída está sendo:

    €nIniciando configuração WiFin
    Conectando-se na rede: GVT-73F0
    Aguarde
    …………..
    Conectado com sucesso na rede: GVT-73F0
    IP obtido: 192.168.1.7
    nIniciando configuração do MPU6050n
    Dispositivo não encontrado!
    Verifique dispositivo – MPU6050 NÃO disponível!
    Enviando localização ao servidorn
    Dados de geolocalização recebidosn

    Could not connect to host: n192.168.1.6nConfiguração finalizada, iniciando loopn
    AcX = -1 | AcY = -1 | AcZ = -1 | Tmp = 36.53 | GyX = -1 | GyY = -1 | GyZ = -1
    Não foi possível conectar ao servidor!n
    (OBS, o ESP-01 não estão conectados até o momento no acelerometro porque so estou programando, mas o erro não está ai .(estou usando o ESP-01))

    Creio que o erro seja no IP.
    O que eu fiz?
    1;instalei o node.js
    2. Escolhi a pasta, conforme esse código: cd /d “c:\Users\rafae\Desktop\projeto-mpu6050-nodeMCU-master\nodejs-server
    3. Executei o server. conforme: node server.js a saída foi:
    Server listening on :::3000…

    Então eu consigo acessar a página vide link: “http://127.0.0.1:3000/” ou “http://localhost:3000/”
    mas fiquei com dúvida na parte do código que é definido o ip:
    const char* rpiHost = “192.168.0.24”;
    qual ip devo colocar ai? já deixei todos os possíveis (o localhost, o 12.0.0.1, o IPv4 e deixei o mesmo… em nenhum dos casos funcionou).
    Qual passo estou fazendo errado?
    agradeço desde já pela ajuda.

    1. Olá Rangel!

      Você está usando Windows para hospedar o servidor?
      Eu desenvolvi o código do servidor pra rodar em sistemas Linux, como Raspberry Pi, Ubuntu, etc…
      Não sei se o código funcionaria out of the box no Windows.
      Creio que teria que otimizar o código do servidor para rodar no windows.
      Tem que dar uma pesquisada como se desenvolve nodejs+express no windows.

      Por exemplo nessa parte eu verifico as interfaces de rede ativas do sistema e pego o IP de alguma delas que não seja local(127.0.0.1):
      var interfaces = os.networkInterfaces();
      var addresses = [];
      for (var k in interfaces) {
      for (var k2 in interfaces[k]) {
      var address = interfaces[k][k2];
      if (address.family === 'IPv4' && !address.internal) {
      addresses.push(address.address);
      }
      }
      }

      No caso esse trecho de código acima me retornou o IP 192.168.0.24 por isso no código do NodeMCU temos:
      const char* rpiHost = “192.168.0.24”;

      IP local 127.0.0.1 não vai funcionar pois não é um IP de LAN.
      Ambos Raspberry Pi e NodeMCU precisam estar na mesma LAN com IPs 192.168.0.xx

  16. É possível armazenas esses dados em um banco de dados para que depois possa exportar para o Excel? grato

  17. muito bom!!! Parabéns!!

  18. Oi! Eu executei tudo mas não aparece nenhum dado na página index.html
    Não mexi nenhum arquivo do lugar. No esp ele diz que está conectado no servidor e está enviando os dados.
    Quando eu do ‘node server.js’ ele fica aberto e executando…e as vezes até joga na tela do Rpi a cidade onde estou devido a busca da localização pelo esp, mas não mostra mas nenhum outro dado nem envia nada para a index.html.

    De vez em quando ele me joga este erro no Rpi:
    events.js:141
    throw er; // Unhandled ‘error’ event
    ^

    Error: listen EADDRINUSE :::3000
    at Object.exports._errnoException (util.js:874:11)
    at exports._exceptionWithHostPort (util.js:897:20)
    at Server._listen2 (net.js:1234:14)
    at listen (net.js:1270:10)
    at Server.listen (net.js:1366:5)
    at Object. (/var/www/html/server.js:35:8)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)

    1. Olá Alexsandro!

      Obrigado pela leitura e que legal que você chegou até o ponto de executar o servidor.

      Primeiramente esse erro que aparece as vezes:
      Error: listen EADDRINUSE :::3000
      pode ser por causa que o endereço IP e a porta estão ocupados e o servidor não consegue “servir” nesse endereço.
      Verifique sempre que você não executou o servidor duas vezes.
      Você também pode tentar trocar o endereço IP e porta. Lembre-se de trocar também no código do NodeMCU.

      Sobre não estar exibindo os dados na Web, você pode tentar colocar mensagens de log em ambos server.js e index.html

      Você disse que vê a localização no terminal da Raspberry certo? Deve ser essa parte do código do server.js:
      app.post('/location', function(req, res) {
      location = req.body
      io.emit('location', location);
      console.log(req.body.city) <<<<------- mensagem de log aqui exibe a cidade });

      Na seguinte parte tem várias mensagens de log comentadas(linhas 53 a 60 do server.js).
      Descomente para ver se o NodeMCU realmente está mandando os valores do sensor

      app.post('/accel', function(req, res) {
      //console.log(req.body.nodeID) <<<---descomente aqui //console.log(req.body.data.accel.accelX) <<<---descomente aqui

      Isso deve exibir os dados no terminal da Raspberry Pi.

      O próximo passo é verificar se as mensagens estão chegando ao cliente(página Web, index.html)
      Na linha 147 do index.html tem a função
      socket.on('accelData', function(accelData) {
      dentro dessa função coloque mensagens de log exibindo dados do sensor. Exemplo:
      var accelX = accelData.data.accel.accelX
      console.log(accelX) <<<--- mensagem de log com valor accelX

      Todas as mensagens de log no arquivo index.html irão aparecer no navegador web.
      Aperte F12 e clique na aba console para ter acesso ao terminal do navegador.

  19. Olá, fiz tudo conforme mas achou q meu mpu6050 está com algum defeito. veja as leituras:

    AcX = -8284 | AcY = -144 | AcZ = 14244 | Tmp = 28.39 | GyX = -221 | GyY = 42 | GyZ = -18
    AcX = -8388 | AcY = -128 | AcZ = 14072 | Tmp = 28.39 | GyX = -203 | GyY = -40 | GyZ = 4
    AcX = -8412 | AcY = -268 | AcZ = 14060 | Tmp = 28.39 | GyX = -229 | GyY = -12 | GyZ = -24
    AcX = -8672 | AcY = -116 | AcZ = 13704 | Tmp = 28.34 | GyX = -146 | GyY = -52 | GyZ = -53

    é normal isso mesmo parado em cima de uma mesa?

  20. Tem como fazer um esuqema pra usa o gseture sensor da sarkfun no nodemcu??

  21. Giovanni funcionou beleza, só que que eu fiz com Esp8266 Wemos D1 pro e com Raspberry PI 2, mas funcionou tudo perfeito. Eu vi que parte da pagina fica em um site da amazon (nuvem) , tem como modificar isso?

    Muito obrigado.

    1. Eu já descobri e editei o arquivo index.html e troque a figura…rsrs

      Abraços

  22. Entendi todo o projeto, só travei na parte de botar o site pra rodar e configurar o IP no código do nodeMCU. To usando só o nodeMCU e um notbook com Windows.

    1. Olá Artur,

      O site desenvolvido é um Web Server feito em NodeJS.
      Pra colocar o site pra rodar você precisa ter NodeJS instalado em seu sistema.

      Veja no seguinte link como instalar NodeJS no Windows:
      http://blog.teamtreehouse.com/install-node-js-npm-windows

      O código do servidor e também a pagina Web HTML podem ser encontrados no meu GitHub
      https://github.com/giobauermeister/projeto-mpu6050-nodeMCU/tree/master/nodejs-server

      1. GIOVANNI aproveitando a pergunta, considerando que eu já instalei o Node.js no Raspberry em que diretório eu coloco os seus arquivos?

        1. Olá Armando,

          Em qualquer diretório de sua preferência.
          Aí dentro da pasta onde estão os arquivos do servidor bastaria executar “nodejs server.js”
          Se der algum erro sobre pacotes não instalados veja no início do código todos os “require”. Como
          var express = require(‘express’);
          Ai tem q ir instalando os pacotes pelo npm (node package manager).

          Dê uma olhada nesse tutorial: https://www.element14.com/community/community/raspberry-pi/raspberrypi2/blog/2015/03/25/rpi2-nodejs-expressjs-sockjs-angularjs

          Abraço!

    2. Então Artur no código do NodeMCU voce tem que colocar o IP do seu notebook (tipo: 192.168.0.132) para que o NodeMCU possa enviar as informações para ele. Voce descobre o IP Wireless do seu notebook usando o comando ipconfig na linda de comando do Windows.

      Ate mais.

  23. Giovanni a parte do Raspberry não esta incluída neste seu artigo ? Teria como enviar pelo email? Eu achei muito bom este seu artigo parabéns.

    Abraços.

    1. Olá Armando,

      Eu inclui o link para o Github.
      https://github.com/giobauermeister/projeto-mpu6050-nodeMCU

      Lá você encontra tanto o código do NodeMCU como do servidor escrito em Nodejs.
      O servidor pode ser executado em qualquer computador ou placa tipo Raspberry que suporte Nodejs.

  24. Bom dia.
    Gostaria de uma dica de como criar um código entre dois ESP8266, sendo assim:
    ESP8266_(número-1), com dois botôes envia comando para o ESP8266_9número-2) ligar dois leds ou relay.
    Os dois se conectando e responde automaticamente, quando estiverem no raio de alcance.
    Esta uma ideia para fazer um controle remoto com dois ESP8266.

    Desde já obrigado

    1. Olá Roberto,

      Você tem que configurar um ESP8266 como Access Point e outro como cliente, ou seja, um deles vai criar uma rede wifi e o outro vai se conectar nessa rede.
      Mais informações aqui:
      http://randomnerdtutorials.com/how-to-make-two-esp8266-talk/

      Abraço

    2. OK, muito obrigado, vou estudar o código.
      Quando vcs vão falar a respeito do ESP32?, e como instalar para o IDE Arduino?

  25. TUNIOT é um gerador de código de bloco para NODEMCU.
    http://easycoding.tn/

    1. Roberto, muito boa sua dica. Já criei um código para usar no ESP e funciona muito bem. Obrigado por compartilhar.

  26. Caro Bauermeister, Muito bom o seu tutorial! Enfim todas as informações para configurar a IDE do arduino reunidas num só artigo bem claro.
    Tenho uma dúvida que gostaria que esclarecesse: Pelo que entendi, o servidor deverá ser instalado em um Raspberry Pi-3. Se assim for, me parece que isto é um complicador, pois a grande maioria dos usuários de arduino, assim como eu, não tem esta plataforma por ser de alto custo. Não seria melhor optar por instalar o Web Server em um PC ou em Note book?
    Fica a sugestão para próximo tutorial!

    1. Olá JAGoris, obrigado pela leitura e sugestões!
      Foi usada uma Raspberry Pi 3 apenas por conveniência e por se tratar de uma solução embarcada onde poderia colocar a Raspberry Pi em uma caixinha ao invés de um computador ligado 24/7 apenas para tarefa de servidor. Mas o servidor pode ser executado em computadores com Linux ou Windows bastando apenas instalar o Node.js e os módulos corretamente para cada plataforma. Existem outros métodos de comunicação com servidores como MQTT que também poderia ser usado em uma solução como essa.

    2. Gostei de sua sugestão sobre o WebServer.

  27. Muito bom!!!
    A biblioteca de Kalman pra arduino(https://github.com/TKJElectronics/KalmanFilter), que eh usada para achar o angulo com o mpu6050, ja esta funcionando com o esp8266 e outros arduinos de 32bits.
    Seria bacana se vc pudesse fazer um post usando-a para mostrar o angulo via web.