> For the complete documentation index, see [llms.txt](https://freegrow-1.gitbook.io/product-docs-en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://freegrow-1.gitbook.io/product-docs-en/en-creator-kit-q1/uwb-creator-kit-q1-complete-setup-and-usage-guide/practice-examples/esp32-integration.md).

# ESP32 Integration

### In This Guide&#x20;

we will walk you through the process of connecting a **GrowSpace Developer Tag** to an **Arduino ESP32** board, and receiving and parsing real-time location data using the **lec** and **lep** commands.\
This step-by-step guide is designed to be beginner-friendly, even for those new to connecting ESP32 with tags.\
Unlike the UNO, the ESP32 supports multiple hardware serials, making it an ideal board for building compact test environments.

***

### Required Materials

<table><thead><tr><th width="302">Item</th><th>Purpose</th></tr></thead><tbody><tr><td><p>ESP32 Board (e.g. DevKitC)</p><p><img src="/files/vRqlRQkWtfF4LE8ZQPih" alt=""></p><p></p></td><td>For serial data reception and parsing</td></tr><tr><td><p>GrowSpace Developer Tag</p><p></p><p><img src="/files/uID0bJD78EhrJYgwNzxb" alt=""></p></td><td>Location Data Transmitting Device</td></tr><tr><td>Arduino IDE</td><td>Code Writing and Upload</td></tr><tr><td>Jumper Cables (4-pin)</td><td>For connecting TX, RX, GND, 3.3V</td></tr></tbody></table>

***

### Arduino IDE Setup

#### Installation

* Download the installation file from the **official Arduino IDE website**.\
  <https://www.arduino.cc/en/software&#x20>;
* For **Windows users**, it is recommended to use the **`.msi` installer**.

#### Add ESP32 Board

* Launch the **Arduino IDE**. → `File > Preferences`

<figure><img src="/files/0lAa7MU0NzuZaZesKiwt" alt=""><figcaption></figcaption></figure>

* In the **Preferences** window, add the following URL in the **Additional Boards Manager URLs** field:

```
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
```

<figure><img src="/files/bi5cXvOR8UibUjxGcMhI" alt=""><figcaption></figcaption></figure>

* `Tools > Board > Board Manager` → Search for **ESP32** and click **Install** for the **ESP32 by Espressif Systems** package.

<figure><img src="/files/DTyxpG9FW6K0YAYkfqD1" alt=""><figcaption></figcaption></figure>

* After installation, go to **`Tools`**` ``>`` `**`Board`**` ``>``  `**`ESP32 Dev Module`**
* Go to **`Tools`**` ``>`` `**`Port`** and select the **automatically detected port** for the ESP32.

<figure><img src="/files/9JnKnRswjtSCXnGbFfRZ" alt=""><figcaption></figcaption></figure>

***

### Serial Connection Setup

The **left connector** of the **GrowSpace Developer Tag** supports 3.3V serial communication.\
Connect the **TX** and **RX** pins of the tag to the **TX2/RX2 pins** on the **ESP32 board** as follows:

| Developer Tag | ESP32 Board   |
| ------------- | ------------- |
| TX            | GPIO 16 (RX2) |
| RX            | GPIO 17 (TX2) |
| GND           | GND           |
| 3.3V          | 3.3V          |

> ⚠️ **TX ↔ RX** must be connected **crossed** (TX to RX and RX to TX).\
> Example:  `TX` → ESP32 RX,  `RX` → ESP32 TX

<figure><img src="/files/u9sBdUeL7zRb0gi7UeOP" alt=""><figcaption></figcaption></figure>

Here is the pinout for the **ESP32 DevKit**. Please locate the **TX2** and **RX2** pins and make sure to connect them accurately as follows:

<figure><img src="https://grow-space.io/wp-content/uploads/2025/06/image-15.png" alt="" height="383" width="759"><figcaption></figcaption></figure>

***

### Serial Relay Example Code

This code allows the **ESP32** to relay serial data between a **PC** and a **GrowSpace Developer Tag**.

```cpp
#define SERIAL2_RX 16  // GPIO16
#define SERIAL2_TX 17  // GPIO17

String inputFromSerial = "";
String inputFromSerial2 = "";

void setup() {
  Serial.begin(115200);
  Serial2.begin(115200, SERIAL_8N1, SERIAL2_RX, SERIAL2_TX);
  Serial.println("ESP32 Serial <-> Serial2 중계 (\\n 기준, \\r 추가, lep/lec 파싱)");
}

void loop() {
  // Serial 입력 → Serial2로 전송
  while (Serial.available()) {
    char ch = (char)Serial.read();
    if (ch != '\n') {
      inputFromSerial += ch;
    }

    if (ch == '\n') {
      Serial2.print(inputFromSerial);
      Serial2.print('\r');  // CR 추가
      inputFromSerial = "";
    }
  }

  // Serial2 입력 → 파싱 및 출력
  while (Serial2.available()) {
    char ch = (char)Serial2.read();
    inputFromSerial2 += ch;

    if (ch == '\n') {
      inputFromSerial2.trim();

      if (inputFromSerial2.startsWith("POS,")) {
        parseLEP(inputFromSerial2);
      } else if (inputFromSerial2.startsWith("DIST,")) {
        parseLEC(inputFromSerial2);
      } else {
        Serial.print("[Serial2 → Serial] 수신: ");
        Serial.println(inputFromSerial2);
      }

      inputFromSerial2 = "";
    }
  }
}

```

* Serial Monitor Setup: Set baud rate to 115200 bps and enable newline transmission.
* If the device information appears after entering the `si` command, the connection is successful.

***

### Example: Parsing Location Data (lep / lec commands)

A developer tag returns current location data using the `lep` or `lec` command.\
The example below shows how to parse the response and display it in a readable format.

#### Parse response from `lep` command (tag location data)

```cpp
// ✅ LEP 결과 파서: POS,x,y,z,qf
void parseLEP(String line) {
  Serial.println("[LEP 위치 결과]");
  int idx = 0;
  String parts[5];

  while (line.length() > 0 && idx < 5) {
    int comma = line.indexOf(',');
    if (comma == -1) {
      parts[idx++] = line;
      break;
    } else {
      parts[idx++] = line.substring(0, comma);
      line = line.substring(comma + 1);
    }
  }

  Serial.print("X: "); Serial.println(parts[1]);
  Serial.print("Y: "); Serial.println(parts[2]);
  Serial.print("Z: "); Serial.println(parts[3]);
  Serial.print("품질(QF): "); Serial.println(parts[4]);
  Serial.println();
}

// 안전한 split 유틸(간단)
static void splitByComma(const String& s, std::vector<String>& out) {
  out.clear();
  int start = 0;
  while (start <= s.length()) {
    int comma = s.indexOf(',', start);
    if (comma == -1) {
      out.push_back(s.substring(start));
      break;
    } else {
      out.push_back(s.substring(start, comma));
      start = comma + 1;
    }
  }
}
```

#### Parse response from `lec` command (ranging + location data)

```cpp
// ✅ LEC 결과 파서(안전한 토큰 파싱): DIST, n, (ANk, id, x, y, z, d)*, POS, x, y, z, qf
void parseLEC(String line) {
  Serial.println("[LEC 거리 + 위치 결과]");

  line.trim();
  std::vector<String> t;
  splitByComma(line, t);
  if (t.size() < 2 || t[0] != "DIST") {
    Serial.println("→ 형식 오류: DIST 헤더 없음");
    return;
  }

  int i = 1;
  int anchorCount = t[i++].toInt(); // 예: 4
  int parsedAnchors = 0;

  // Anchor 묶음 파싱: ANk, id, x, y, z, d
  while (i + 5 < (int)t.size() && t[i].startsWith("AN")) {
    String anLabel = t[i++];      // AN0, AN1, ...
    String anId    = t[i++];      // 3364, 35BE, ...
    float x = t[i++].toFloat();   // -1.00
    float y = t[i++].toFloat();   // 11.48
    float z = t[i++].toFloat();   // 0.00
    float d = t[i++].toFloat();   // 2.80

    Serial.print(anLabel); Serial.print(" (ID ");
    Serial.print(anId); Serial.print("): ");
    Serial.print("x="); Serial.print(x);
    Serial.print(", y="); Serial.print(y);
    Serial.print(", z="); Serial.print(z);
    Serial.print(" → 거리: "); Serial.print(d); Serial.println("m");

    parsedAnchors++;
  }

  if (parsedAnchors != anchorCount) {
    Serial.print("→ 경고: DIST가 가리킨 Anchor 수(");
    Serial.print(anchorCount);
    Serial.print(")와 실제 파싱 수(");
    Serial.print(parsedAnchors);
    Serial.println(") 불일치");
  }

  // POS, x, y, z, qf
  if (i < (int)t.size() && t[i] == "POS") {
    // parseLEP는 "POS,..." 전체 문자열을 기대하므로 그대로 만들어 전달
    String posLine = "POS";
    for (int k = i + 1; k < (int)t.size(); ++k) {
      posLine += ",";
      posLine += t[k];
    }
    Serial.println("▶ 태그 위치:");
    parseLEP(posLine);
  } else {
    Serial.println("→ POS 정보 없음");
  }
}
```

LEP execution result

<figure><img src="/files/SpzJ4Hu3W52pShG6HPko" alt=""><figcaption></figcaption></figure>

LEC execution result

<figure><img src="/files/YYrXKQJINYqETNBovuu9" alt=""><figcaption></figcaption></figure>

***

### Test Method Summary

* Upload the code and open the Serial Monitor in the Arduino IDE.
* Enter the `lep` or `lec` command.
* Check if the location data is displayed correctly (e.g., XYZ coordinates, distance).

***

### **Conclusion**

In this manual, we showed how to connect the GrowSpace developer tag to an ESP32, send location commands via serial communication, and receive and parse the data.\
\
This process allows real-time location tracking of a single tag, and can be extended to experiments using BLE transmission, Wi-Fi integration, or MQTT communication.\
\
If you don’t see any response during testing, please double-check the TX/RX pin connections and your serial port settings.
