ESP-Now JSON: A Beginner's Guide

ESP-Now JSON Transmission: A Beginner's Guide

Hey guys! Ever tried getting two ESP32 devices to talk to each other? It's a super cool project, and ESP-Now is a fantastic way to do it. It's like a super-fast, low-energy radio for your gadgets. But, you might be banging your head against the wall when you try to send data, especially when you're dealing with more complex stuff like JSON. This guide is for all of you, beginners, who are pulling your hair out trying to get this to work. We're going to break down how to send JSON over ESP-Now in a way that's easy to understand, with no fancy tech jargon.

What is ESP-Now and Why Use It?

Before we dive in, let's get the basics. ESP-Now is a communication protocol developed by Espressif, the folks who make the ESP32. Think of it as a simplified version of Wi-Fi, specifically designed for fast, one-way communication between devices. Unlike Wi-Fi, it doesn't need a router, making it ideal for projects where you have two or more ESP32s that need to quickly share data without the overhead of a full network. The reason why this technology is useful, is because it can work without the need to connect to a Wi-Fi network. It creates a direct communication channel between two devices, which reduces the need for a router. This makes it more efficient and consumes less power.

Now, why would you use ESP-Now? Well, imagine you're building a smart home project. You might have a sensor that needs to send data to a central hub. Instead of setting up a complex Wi-Fi network, you can use ESP-Now to send that data directly, saving power and simplifying setup. Or, maybe you're working on a remote control system, where speed and reliability are key. With ESP-Now, you can get data transferred quickly, which is essential for real-time control. ESP-Now is also great because it's pretty efficient when it comes to battery life. This is crucial when you're working on devices that need to last a long time without needing to be recharged.

Setting Up Your ESP32s for ESP-Now

Alright, let's get our hands dirty with some code! First things first, you'll need the Arduino IDE or PlatformIO set up with your ESP32 board installed. Make sure you have the ESP32 board package installed in your IDE. Then, you will need two ESP32 boards, because it is necessary to have two devices for communication.

Here's a basic code snippet to get started. This sets up ESP-Now on both devices. This code is going to be the foundation, so you can send JSON data over ESP-Now:

#include <esp_now.h>
#include <WiFi.h>

// MAC Address of the receiver (replace with your receiver's MAC address)
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Structure example to send data
// Must match the receiver structure
typedef struct {
    int sensorValue;
    String message;
} dataStruct;

dataStruct myData;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("Last Packet Send Status: ");
  if (status == ESP_NOW_SEND_SUCCESS) {
    Serial.println("Delivery success");
  } else {
    Serial.println("Delivery fail");
  }
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to get the status of Trasnmit status
  esp_now_register_send_cb(OnDataSent);

  // Register peer
  esp_now_peer_info_t peerInfo;
  peerInfo.channel = 0; 
  peerInfo.encrypt = false;
  // Copies the MAC address of the receiver to the peerInfo structure
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);

  // Add peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
}

void loop() {
  // Set values to send
  myData.sensorValue = random(0, 100);
  myData.message = "Hello ESP-Now!";

  // Send message via ESP-NOW
  esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
  delay(2000);
}

Important: Replace broadcastAddress[] with the MAC address of the other ESP32. You can find this in the Serial Monitor when the other device is running. This code initializes the ESP-Now, sets up a structure to hold your data (crucial for JSON later), and sends a simple message. Make sure to upload this code to both ESP32s, but change the MAC address in each one to the other device's MAC address.

Sending JSON Data Over ESP-Now

Now, this is where things get interesting. Instead of sending a simple structure, you're going to send JSON data. Here's the deal: you need to convert your data into a JSON format before sending it. You'll need a JSON library in your Arduino IDE. A popular and easy-to-use one is ArduinoJson by Benoit Blanchon. Install it through the Library Manager in the Arduino IDE. This library will handle converting your data into JSON strings, and then back again on the receiving end. You will need to include the library into the code. Once you've got your library installed, you can start converting your data into a format that's easy for your devices to understand. Remember, you want to serialize the data on one side (encode it into JSON) and deserialize it on the other side (decode it from JSON).

Here's a sample sender code using the ArduinoJson library:

#include <esp_now.h>
#include <WiFi.h>
#include <ArduinoJson.h>

uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Structure example to send data
typedef struct {
    int sensorValue;
    String message;
} dataStruct;

dataStruct myData;

// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("Last Packet Send Status: ");
  if (status == ESP_NOW_SEND_SUCCESS) {
    Serial.println("Delivery success");
  } else {
    Serial.println("Delivery fail");
  }
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for Send CB to get the status of Trasnmit status
  esp_now_register_send_cb(OnDataSent);

  // Register peer
  esp_now_peer_info_t peerInfo;
  peerInfo.channel = 0; 
  peerInfo.encrypt = false;
  // Copies the MAC address of the receiver to the peerInfo structure
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);

  // Add peer
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
}

void loop() {
  // Prepare data
  myData.sensorValue = random(0, 100);
  myData.message = "Hello ESP-Now!";

  // Create a JSON document
  StaticJsonDocument<200> doc;
  doc["sensorValue"] = myData.sensorValue;
  doc["message"] = myData.message;

  // Serialize JSON to a string
  String jsonString;
  serializeJson(doc, jsonString);

  // Send message via ESP-NOW
  esp_now_send(broadcastAddress, (uint8_t *) jsonString.c_str(), jsonString.length());
  delay(2000);
}

This sender code does the following:

  1. Includes Libraries: It includes the necessary libraries, including ArduinoJson.
  2. Defines Data: It creates the data you want to send.
  3. Creates JSON Document: It creates a StaticJsonDocument to hold your data. The size (e.g., <200>) depends on how much data you're sending.
  4. Populates JSON: It adds your data to the JSON document using key-value pairs.
  5. Serializes to String: It converts the JSON document into a String called jsonString.
  6. Sends Data: It sends the jsonString over ESP-Now.

Receiving and Parsing JSON Data

Now, on the receiving end, you'll need to take that JSON string and turn it back into usable data. The receiver code will look something like this:

#include <esp_now.h>
#include <WiFi.h>
#include <ArduinoJson.h>

// Structure example to receive data
typedef struct {
    int sensorValue;
    String message;
} dataStruct;

dataStruct receivedData;

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  // Parse the JSON string
  StaticJsonDocument<200> doc;
  deserializeJson(doc, incomingData);

  // Read values
  receivedData.sensorValue = doc["sensorValue"];
  receivedData.message = doc["message"];

  // Print values
  Serial.print("Sensor Value: ");
  Serial.println(receivedData.sensorValue);
  Serial.print("Message: ");
  Serial.println(receivedData.message);
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  // Once ESPNow is successfully Init, we will register for recv CB to get the status of Trasnmit status
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  // Do nothing
}

This receiver code does the following:

  1. Includes Libraries: It includes the necessary libraries, including ArduinoJson.
  2. Sets up Callback: It sets up a callback function OnDataRecv that is triggered when data is received.
  3. Deserializes JSON: It uses deserializeJson() to parse the incoming data (which is a JSON string) into a JsonDocument.
  4. Reads Data: It reads the values from the JsonDocument using the keys you defined in the sender.
  5. Uses the Data: It uses the received data.

Important: Make sure the structure of your JSON matches on both the sender and receiver sides. If you're sending "sensorValue" and "message", make sure the receiver is looking for those same keys. Also, ensure the size of the StaticJsonDocument is large enough to hold the incoming JSON data.

Troubleshooting Common Issues

Having trouble? Happens to the best of us! Here's a quick troubleshooting guide:

  • MAC Address: Double-check the MAC addresses! They're case-sensitive and need to be correct on both sides.
  • JSON Size: Make sure the size of your StaticJsonDocument is big enough to handle your data. If it's too small, you might not get all the data.
  • Library Issues: Ensure you've installed the ArduinoJson library correctly.
  • Data Types: Make sure the data types (int, String, etc.) match between the sender and receiver.
  • Serial Monitor: Use the Serial Monitor to print messages and see what's going on. It's your best friend for debugging!
  • ESP-Now Initialization: Make sure that esp_now_init() is successful and that you handle any errors during initialization.
  • No Data Received: If no data is received, check the sending device and make sure it is sending data.

Wrapping Up

So, there you have it! Sending JSON over ESP-Now isn't as scary as it seems. With a little bit of setup, a good understanding of the JSON format, and the right libraries, you can get your ESP32s communicating in no time. Remember to double-check your MAC addresses, make sure your JSON structures match, and use the Serial Monitor to see what's happening. Keep experimenting, and don't be afraid to try new things. You've got this!

Photo of Mr. Loba Loba

Mr. Loba Loba

A journalist with more than 5 years of experience ·

A seasoned journalist with more than five years of reporting across technology, business, and culture. Experienced in conducting expert interviews, crafting long-form features, and verifying claims through primary sources and public records. Committed to clear writing, rigorous fact-checking, and transparent citations to help readers make informed decisions.