Kinematrix provides five distinct serial communication modules, each optimized for specific use cases from simple hardware serial to robust packet protocols.
Available Modules
EnhancedSerial Production-grade serial with buffering and error handling
HardSerial Simple hardware serial wrapper for basic communication
SoftSerial Software serial for additional ports (AVR/ESP8266)
SwapSerial Custom pin mapping for ESP32/ESP8266
NemaSerial Packet-based protocol with CRC and acknowledgment
Feature Comparison
Feature EnhancedSerial HardSerial SoftSerial SwapSerial NemaSerial Buffering Circular buffer String-based String-based String-based Platform-adaptive Error Handling Comprehensive Basic Basic Basic CRC16 + ACK Platform All All AVR/ESP8266 ESP32/ESP8266 All Pin Config Fixed Fixed Custom Custom Fixed Packet Protocol No No No No Yes Data Types Template Template Template Template Type-safe
EnhancedSerial
Production-grade serial communication with advanced features including buffering, error handling, and asynchronous operations.
Key Features
Circular Buffer : Configurable size with overflow protection
Error Handling : Timeout, buffer overflow, invalid data detection
Stream Interface : Full Arduino Stream compatibility
Echo Mode : Debug mode for monitoring communication
Callbacks : Asynchronous data handling with callbacks
Class Definition
lib/modules/communication/wired/serial/enhanced-serial.h
class EnhancedSerial : public Stream {
public:
enum class Error {
NONE ,
TIMEOUT ,
BUFFER_OVERFLOW ,
INVALID_DATA ,
MEMORY_ERROR
};
explicit EnhancedSerial ( size_t bufferSize = 2 );
~EnhancedSerial ();
void begin ( Stream * _serialPtr , unsigned long timeout = 1000 );
// Data operations
template < typename T >
void addData ( T newData , char separator = ';' );
void clearData ();
bool sendData ();
bool sendDataCb ( void (* onReceive )( const String & ));
String sendDataCbWaitDataWithTimeout (
void (* onSend )( const String & ) = nullptr ,
unsigned long timeout = 1000 ,
int maxRetries = 3 ,
bool wdtTimeout = false
);
// Configuration
void setEcho ( bool enable );
void setAutoClean ( bool enable );
void setTimeout ( unsigned long ms );
// Error handling
Error getLastError () const ;
String getErrorString () const ;
};
Basic Usage
#define ENABLE_MODULE_SERIAL_ENHANCED
#include "Kinematrix.h"
EnhancedSerial enhanced ( 256 ); // 256-byte buffer
void setup () {
Serial . begin ( 115200 );
Serial1 . begin ( 9600 );
enhanced . begin ( & Serial1, 2000 ); // 2-second timeout
enhanced . setEcho ( true ); // Enable debug echo
}
void loop () {
enhanced . clearData ();
enhanced . addData ( "TEMP" );
enhanced . addData ( 25.67 );
enhanced . addData ( millis ());
if ( enhanced . sendData ()) {
Serial . println ( "Data sent successfully" );
} else {
Serial . print ( "Error: " );
Serial . println ( enhanced . getErrorString ());
}
delay ( 5000 );
}
Advanced Features
// Send data and wait for response with retry
void onDataSent ( const String & data ) {
Serial . println ( "Sent: " + data);
}
String response = enhanced . sendDataCbWaitDataWithTimeout (
onDataSent,
5000 , // 5-second timeout
3 , // Max 3 retries
false // Don't use WDT timeout
);
if ( response . length () > 0 ) {
Serial . println ( "Response: " + response);
}
Data Parsing
// Parse received data
String data = "25.5;60.2;1013.25" ;
float temp = enhanced . getFloat (data, 0 , ";" ); // 25.5
float humidity = enhanced . getFloat (data, 1 , ";" ); // 60.2
float pressure = enhanced . getFloat (data, 2 , ";" ); // 1013.25
HardSerial
Simple hardware serial wrapper providing basic send/receive functionality.
Basic Usage
#define ENABLE_MODULE_SERIAL_HARD
#include "Kinematrix.h"
HardSerial serial;
void setup () {
Serial . begin ( 115200 );
serial . begin ( & Serial1, 9600 );
}
void loop () {
serial . clearData ();
serial . addData ( "Sensor1" );
serial . addData ( analogRead (A0));
serial . sendData ();
delay ( 1000 );
}
Asynchronous Communication
void onDataReceived ( const String & data ) {
Serial . println ( "Received: " + data);
float value = serial . getData (data, 0 , ( char * ) ";" );
String id = serial . getStrData (data, 1 , ( char * ) ";" );
}
void loop () {
serial . receiveAsync ( 500 , onDataReceived);
}
SoftSerial
Software serial for additional serial ports on AVR and ESP8266 platforms.
ESP32 Not Supported : SoftSerial is not available on ESP32. Use SwapSerial or additional hardware serial ports instead.
Pin-Based Initialization
#if ! defined ( ESP32 ) // Not available on ESP32
#define ENABLE_MODULE_SERIAL_SOFT
#include "Kinematrix.h"
SoftSerial soft;
void setup () {
Serial . begin ( 115200 );
// Initialize with RX=10, TX=11, 9600 baud
soft . begin ( 10 , 11 , 9600 );
}
void loop () {
soft . clearData ();
soft . addData ( "GPS" );
soft . addData ( "Data" );
soft . sendData ();
delay ( 1000 );
}
#endif
Using SoftwareSerial Object
SoftwareSerial mySerial ( 10 , 11 ); // RX, TX
SoftSerial soft;
void setup () {
soft . begin ( & mySerial, 9600 );
}
SwapSerial
Hardware serial with custom GPIO pin mapping for ESP32 and ESP8266.
ESP32/ESP8266 Only : This module is only available on ESP32 and ESP8266 platforms with flexible GPIO.
GPIO Pin Options (ESP32)
/*
* Valid ESP32 GPIO pairs for serial:
* GPIO32/33, GPIO25/26, GPIO27/14, GPIO13/15
* GPIO21/22, GPIO17/16
*/
Custom Pin Configuration
#if defined ( ESP32 ) || defined ( ESP8266 )
#define ENABLE_MODULE_SERIAL_SWAP
#include "Kinematrix.h"
SwapSerial swap;
void setup () {
Serial . begin ( 115200 );
// Configure Serial2 with custom pins
swap . begin (
& Serial2, // Hardware serial port
115200 , // Baud rate
SERIAL_8N1, // Config (8 data, no parity, 1 stop)
16 , // RX pin
17 // TX pin
);
}
void loop () {
swap . clearData ();
swap . addData ( "Custom" );
swap . addData ( millis ());
swap . sendData ( true , true ); // debug=true, endln=true
delay ( 1000 );
}
#endif
Timeout Control
void setup () {
swap . begin ( & Serial2, 9600 , SERIAL_8N1, 16 , 17 );
swap . setTimeOut ( 5000 ); // 5-second timeout
}
NemaSerial
Robust packet-based protocol with NMEA-like structure, CRC error detection, and acknowledgment system.
Protocol Features
Binary Packet Protocol : Start/end markers with byte stuffing
CRC16 Error Detection : Automatic checksum validation
ACK/NAK System : Reliable delivery confirmation
JSON Support : ArduinoJson integration for structured data
Type-Safe Serialization : int8/16/32, uint8/16/32, float, string, bool
Platform-Adaptive Buffers : 64B (AVR), 256B (ESP8266), 512B (ESP32)
Packet Structure
[START][SEQUENCE][COMMAND][LENGTH][DATA...][CRC][END]
0x7E 1B 1B 2B 0-NB 2B 0x7F
Command Set
lib/modules/communication/wired/serial/nema-serial.h
#define CMD_ACK 0x 06 // Acknowledgment
#define CMD_NAK 0x 15 // Negative acknowledgment
#define CMD_PING 0x 01 // Ping request
#define CMD_DATA 0x 02 // Generic data
#define CMD_REGISTER_READ 0x 03 // Read register
#define CMD_REGISTER_WRITE 0x 04 // Write register
#define CMD_JSON_DATA 0x 10 // JSON payload
#define CMD_MIXED_DATA 0x 11 // Mixed type data
#define CMD_CUSTOM_START 0x 40 // Custom commands start here
Data Types
#define DATA_TYPE_INT8 0x 01
#define DATA_TYPE_INT16 0x 02
#define DATA_TYPE_INT32 0x 03
#define DATA_TYPE_UINT8 0x 04
#define DATA_TYPE_UINT16 0x 05
#define DATA_TYPE_UINT32 0x 06
#define DATA_TYPE_FLOAT 0x 07
#define DATA_TYPE_STRING 0x 08
#define DATA_TYPE_BOOL 0x 09
Basic Packet Communication
#define ENABLE_MODULE_SERIAL_NEMA
#include "Kinematrix.h"
NemaSerial nema;
void setup () {
Serial . begin ( 115200 );
Serial1 . begin ( 9600 );
nema . begin ( & Serial1, 256 ); // 256-byte buffer
nema . setRequireAck ( true ); // Enable acknowledgments
nema . setMaxRetries ( 3 ); // Retry up to 3 times
nema . setTimeout ( 1000 ); // 1-second timeout
}
void loop () {
// Build and send packet
nema . beginPacket ()
. writeFloat ( 25.67 ) // Temperature
. writeFloat ( 60.2 ) // Humidity
. writeString ( "SENSOR_01" ) // Device ID
. writeBool ( true ) // Status OK
. endPacket (CMD_DATA);
delay ( 5000 );
}
Receiving Packets
void onPacketReceived ( uint8_t command , uint8_t * data , uint16_t length ) {
Serial . print ( "Command: 0x" );
Serial . println (command, HEX);
if (command == CMD_DATA) {
uint16_t index = 0 ;
float temp = nema . readFloat (data, & index);
float humidity = nema . readFloat (data, & index);
String deviceId = nema . readString (data, & index);
bool status = nema . readBool (data, & index);
Serial . print ( "Temperature: " );
Serial . println (temp);
Serial . print ( "Humidity: " );
Serial . println (humidity);
Serial . print ( "Device: " );
Serial . println (deviceId);
}
}
void setup () {
// ... previous setup ...
nema . setPacketHandler (onPacketReceived);
}
void loop () {
nema . processIncoming (); // Check for incoming packets
}
JSON Communication
#include <ArduinoJson.h>
void sendJsonData () {
StaticJsonDocument < 200 > doc;
doc [ "sensor" ] = "DHT22" ;
doc [ "temp" ] = 25.67 ;
doc [ "humidity" ] = 60.2 ;
doc [ "timestamp" ] = millis ();
nema . sendJson (doc, CMD_JSON_DATA);
}
void onJsonReceived ( JsonDocument & doc ) {
const char * sensor = doc [ "sensor" ];
float temp = doc [ "temp" ];
float humidity = doc [ "humidity" ];
Serial . print ( "Sensor: " );
Serial . println (sensor);
Serial . print ( "Temp: " );
Serial . println (temp);
}
void setup () {
nema . begin ( & Serial1, 512 );
nema . setJsonHandler (onJsonReceived);
}
Debugging and Statistics
void setup () {
nema . begin ( & Serial1, 256 );
nema . setDebugLevel (DEBUG_VERBOSE); // DEBUG_NONE, DEBUG_ERRORS, DEBUG_INFO, DEBUG_VERBOSE
nema . setDebugStream (Serial); // Output debug to Serial
}
void loop () {
// ... communication ...
// Print statistics every 10 seconds
static unsigned long lastStats = 0 ;
if ( millis () - lastStats > 10000 ) {
lastStats = millis ();
nema . dumpStats ();
}
}
Error Handling
void onError ( uint8_t errorCode ) {
Serial . print ( "Error: " );
Serial . println ( nema . getErrorString (errorCode));
}
void setup () {
nema . begin ( & Serial1, 256 );
nema . setErrorHandler (onError);
}
// Error codes
// ERR_NONE, ERR_TIMEOUT, ERR_CRC, ERR_LENGTH,
// ERR_COMMAND, ERR_BUFFER_OVERFLOW, ERR_FORMAT,
// ERR_SEQUENCE, ERR_BUSY, ERR_JSON, ERR_MEMORY
ESP32
ESP8266
Arduino (AVR)
Available Modules : EnhancedSerial, HardSerial, SwapSerial, NemaSerial// Multiple hardware serial ports
Serial // USB (GPIO1/3)
Serial1 // GPIO9/10 (typically flash)
Serial2 // GPIO16/17 (configurable)
// NemaSerial buffer
#define DEFAULT_BUFFER_SIZE 512
#define DEFAULT_CHUNK_SIZE 128
Available Modules : All modules supported// Hardware serial
Serial // USB (GPIO1/3)
Serial1 // TX only (GPIO2)
// Software serial available
SoftwareSerial (RX, TX)
// NemaSerial buffer
#define DEFAULT_BUFFER_SIZE 256
#define DEFAULT_CHUNK_SIZE 64
Available Modules : EnhancedSerial, HardSerial, SoftSerial, NemaSerial// Single hardware serial
Serial // GPIO0/1 (Uno/Nano)
// Software serial essential for multiple ports
SoftwareSerial (RX, TX)
// NemaSerial buffer (optimized for low RAM)
#define DEFAULT_BUFFER_SIZE 64
#define DEFAULT_CHUNK_SIZE 16
Use Case Selection Guide
Use EnhancedSerial When...
You need robust error handling
Working with high-speed data streams
Require buffering to prevent data loss
Need timeout detection and retry logic
Building production systems
Simple point-to-point communication
Minimal overhead is required
Basic send/receive is sufficient
Educational or prototype projects
Need multiple serial ports on AVR
Hardware serial is unavailable
Low-speed communication (<9600 baud)
GPS, simple sensors, or debugging
Need custom GPIO pins (ESP32/ESP8266)
Default pins conflict with other hardware
Multiple hardware serial ports required
High-speed communication needed
Reliability is critical
Working in noisy environments
Need guaranteed delivery (ACK/NAK)
Structured data with type safety
JSON communication required
Industrial or medical applications
Common Patterns
Request-Response Pattern
// Master sends request
void sendRequest () {
serial . clearData ();
serial . addData ( "READ" );
serial . addData ( "TEMP" );
serial . sendData ();
}
// Slave responds
void onRequest ( const String & data ) {
String command = serial . getStrData (data, 0 , ( char * ) ";" );
if (command == "READ" ) {
serial . clearData ();
serial . addData ( "TEMP" );
serial . addData ( 25.67 );
serial . sendData ();
}
}
Heartbeat Pattern
unsigned long lastHeartbeat = 0 ;
const unsigned long HEARTBEAT_INTERVAL = 5000 ;
void loop () {
if ( millis () - lastHeartbeat > HEARTBEAT_INTERVAL) {
lastHeartbeat = millis ();
serial . clearData ();
serial . addData ( "HEARTBEAT" );
serial . addData ( millis () / 1000 ); // Uptime
serial . sendData ();
}
}
Modbus Protocol Industrial serial protocol with Modbus
I2C Communication Alternative wired protocol for sensors