The Ultimate Zero-Copy Data-Sync Engine for Arduino
Stop fighting with manual Serial parsing. APASerialSync is a high-performance, memory-thrifty library that makes synchronizing complex data structures between microcontrollers as easy as a single function call.
- 💎 Zero-Copy Performance: RAM is a luxury on 8-bit MCUs. Our architecture writes data directly into your variables, eliminating redundant internal buffers and maximizing efficiency.
- 🔄 True Bi-Directional Sync: Move data both ways simultaneously without complex state machines or blocking your code.
- 🌍 MCU Agnostic: Works seamlessly across AVR (Uno/Nano), ESP32, ESP8266, STM32, and more.
- ⚡ Non-Blocking Logic: No
delay()calls. Your main loop stays fast and responsive. - 🛡️ Rock-Solid Reliability: CRC16 checksums and Packet ID tracking ensure your data arrives 100% intact.
- 🧩 Type-Safe Templates: Uses C++ templates to handle any
structorclasswith full type safety.
Don't waste time writing boilerplate code by hand! We provide a powerful companion tool to help you get started:
- Online Version: Use the Live Web Designer to visually build your data structure and generate code.
- Local Version: Check the
/DESIGNERfolder in this repository. It contains a ZIP file with the full designer tool that you can run locally on your machine (just openindex.htmlin any browser).
- Download this repository as a
.zipfile. - In the Arduino IDE: Sketch -> Include Library -> Add .ZIP Library...
- Select the downloaded file.
- Note: If using
SoftwareSerial, ensure you have it installed (usually built-in for AVR).
To make the MCUs talk, you must follow these three rules:
- Cross the wires: MCU1 TX goes to MCU2 RX. MCU1 RX goes to MCU2 TX.
- Common Ground: Connect the GND pins of both MCUs together.
- Voltage Match: If using a 5V MCU (Uno) with a 3.3V MCU (ESP32), use a logic level shifter.
Both MCUs must use the exact same struct. We use #pragma pack(push, 1) to ensure the memory layout is identical on both sides.
#pragma pack(push, 1)
struct MyData {
int counter;
float temperature;
bool ledStatus;
};
#pragma pack(pop)Initialize the Serial port first, then the library.
MyData myData;
// Pass the Serial port (e.g. Serial1) and your data variable
APASerialSync<MyData> sync(Serial1, myData);
void setup() {
// 1. Start the Serial port at your desired speed
Serial1.begin(9600);
// 2. Initialize the library
sync.apaBegin();
}void loop() {
// Check for incoming data (non-blocking)
if (sync.apaSync()) {
// 'myData' has been updated automatically!
digitalWrite(LED_BUILTIN, myData.ledStatus);
}
// Send local changes (e.g. every 2 seconds)
static unsigned long lastSend = 0;
if (millis() - lastSend > 2000) {
myData.counter++;
sync.apaSend();
lastSend = millis();
}
}src/: Library source code (APASerialSync.h).examples/: Organized samples (Basic, Intermediate, Advanced).DESIGNER/: Local version of the web-based code generator tool.library.properties: Arduino library metadata.keywords.txt: Syntax highlighting for Arduino IDE.
- Forgot GND: If grounds aren't connected, the signal has no reference and will fail.
- Struct Mismatch: If MCU1 has 4 variables and MCU2 has 3, the sync will fail CRC checks.
- Blocking Code: If your loop has long
delay()calls, you might miss incoming serial data.
Released under the MIT License. See LICENSE for details.
