UART
The UART (Universal Asynchronous Receiver/Transmitter) interface provides asynchronous serial communication. Supports configurable baud rates from 300 to 3,000,000 bps with various data formats and voltage levels from 1.6V to 5.0V.
Some interfaces share the same GPIO pins, so only one can be used at a time. Check out the multiplexing tables in the introduction for more details.
Quick Start​
The example code below shows how to enable the UART interface, configure it, and transmit/receive data.
- NodeJS
- Python
import AT1000 from '@ikalogic/at1000';
let devices = await AT1000.findDevices(500); // Find devices with a 500ms timeout
let tester = devices[0]; // Target the first detected device
let uart = tester.com.uart(0); // Select the first UART interface
await uart.enable({
vcc: 3.3,
baud_rate: 115200,
data_bits: 8,
parity: 'none',
stop_bits: 1
}); // Enable UART with standard 115200 8N1 configuration
// Transmit data
await uart.tx("Hello, World!\r\n");
// Start continuous receive
await uart.start_rx();
// Wait for some data
await new Promise(resolve => setTimeout(resolve, 100));
// Read received data
let data = await uart.rx();
console.log("Received:", data);
// Stop reception
await uart.stop_rx();
// Disable UART interface
await uart.disable();
from ikalogic_at1000 import AT1000
import asyncio
devices = await AT1000.find_devices(500) # Find devices with a 500ms timeout
tester = devices[0] # Target the first detected device
uart = tester.com.uart(0) # Select the first UART interface
await uart.enable({
'vcc': 3.3,
'baud_rate': 115200,
'data_bits': 8,
'parity': 'none',
'stop_bits': 1
}) # Enable UART with standard 115200 8N1 configuration
# Transmit data
await uart.tx("Hello, World!\r\n")
# Start continuous receive
await uart.start_rx()
# Wait for some data
await asyncio.sleep(0.1)
# Read received data
data = await uart.rx()
print(f"Received: {data}")
# Stop reception
await uart.stop_rx()
# Disable UART interface
await uart.disable()
API Reference​
Accessing UART​
- NodeJS
- Python
const uart = tester.com.uart(id);
uart = tester.com.uart(id)
Parameters:
id(number): The UART interface identifier (0-based index)
Returns: Uart instance
Methods​
configure(config)​
Configures the UART interface parameters without changing the enabled state.
- NodeJS
- Python
await uart.configure({
baud_rate: 9600,
data_bits: 8,
parity: 'none',
stop_bits: 1,
vcc: 3.3
});
await uart.configure({
'baud_rate': 9600,
'data_bits': 8,
'parity': 'none',
'stop_bits': 1,
'vcc': 3.3
})
Parameters:
config(UartConfigPatch): Configuration object with optional properties:enabled(boolean, optional): Enable or disable the interfacebaud_rate(number, optional): Baud rate (300 to 3,000,000)data_bits(number, optional): Data bits per character (5, 6, 7, 8, or 9)parity(string, optional): Parity mode -'none','even', or'odd'stop_bits(number, optional): Stop bits (1 or 2)vcc(number, optional): Logic level voltage (1.6 to 5.0)
Returns: Promise<UartConfig> - The updated configuration
Exceptions:
- Throws validation error if
baud_rateis outside [300, 3000000] - Throws validation error if
data_bitsis not one of [5, 6, 7, 8, 9] - Throws validation error if
parityis not'none','even', or'odd' - Throws validation error if
stop_bitsis not 1 or 2 - Throws validation error if
vccis outside [1.6, 5.0]
enable([config])​
Enables the UART interface and optionally applies configuration.
- NodeJS
- Python
await uart.enable({
baud_rate: 115200,
data_bits: 8,
parity: 'none',
stop_bits: 1,
vcc: 3.3
});
await uart.enable({
'baud_rate': 115200,
'data_bits': 8,
'parity': 'none',
'stop_bits': 1,
'vcc': 3.3
})
Parameters:
config(UartEnableConfig, optional): Optional configuration to apply
Returns: Promise<UartConfig> - The updated configuration with enabled: true
disable()​
Disables the UART interface.
- NodeJS
- Python
await uart.disable();
await uart.disable()
Returns: Promise<UartConfig> - The updated configuration with enabled: false
tx(data)​
Transmits data over the UART interface.
- NodeJS
- Python
// Transmit string data
await uart.tx("Hello\r\n");
// Transmit raw bytes
await uart.tx([0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0D, 0x0A]);
# Transmit string data
await uart.tx("Hello\r\n")
# Transmit raw bytes
await uart.tx([0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x0D, 0x0A])
Parameters:
data(string | number[]): Data to transmit (up to 1024 bytes)
Returns: Promise<number> - Number of bytes transmitted
Exceptions:
- Throws validation error if data exceeds 1024 bytes
start_rx()​
Starts continuous reception. Data is buffered internally until read with rx().
- NodeJS
- Python
await uart.start_rx();
await uart.start_rx()
Returns: Promise<void>
stop_rx()​
Stops continuous reception.
- NodeJS
- Python
await uart.stop_rx();
await uart.stop_rx()
Returns: Promise<void>
rx()​
Reads received data from the internal buffer.
- NodeJS
- Python
// Read all available data
const data = await uart.rx();
console.log("Received:", data);
# Read all available data
data = await uart.rx()
print(f"Received: {data}")
Returns: Promise<SerialData> - Received data as byte array (number[])
Notes:
- Returns immediately with available data (non-blocking)
- Clears the receive buffer after reading
- Must call
start_rx()before receiving data
Types​
UartConfig​
Complete configuration object returned by configuration methods.
{
enabled: boolean,
baud_rate: number, // 300 to 3,000,000
data_bits: number, // 5, 6, 7, 8, or 9
parity: 'none' | 'even' | 'odd',
stop_bits: number, // 1 or 2
vcc: number // 1.6 to 5.0
}
UartConfigPatch​
Partial configuration for the configure() method. All properties are optional.
{
enabled?: boolean,
baud_rate?: number,
data_bits?: number,
parity?: 'none' | 'even' | 'odd',
stop_bits?: number,
vcc?: number
}
UartEnableConfig​
Optional configuration for the enable() method.
{
baud_rate?: number,
data_bits?: number,
parity?: 'none' | 'even' | 'odd',
stop_bits?: number,
vcc?: number
}
SerialData​
Output data type, always returned as a byte array.
number[] // Array of bytes (0-255)
Common Baud Rates​
| Baud Rate | Description |
|---|---|
| 300 | Low-speed legacy |
| 1200 | Legacy modems |
| 2400 | Legacy modems |
| 4800 | Legacy devices |
| 9600 | Common default |
| 19200 | Common |
| 38400 | Common |
| 57600 | Common |
| 115200 | Most common high-speed |
| 230400 | High-speed |
| 460800 | High-speed |
| 921600 | Very high-speed |
| 1000000 | 1 Mbps |
| 2000000 | 2 Mbps |
| 3000000 | 3 Mbps (maximum) |
Usage Example​
- NodeJS
- Python
import AT1000 from '@ikalogic/at1000';
// Find and connect to device
const devices = await AT1000.findDevices(500);
const tester = devices[0];
// Access UART interface 0
const uart = tester.com.uart(0);
// Enable with standard 115200 8N1 configuration
await uart.enable({
baud_rate: 115200,
data_bits: 8,
parity: 'none',
stop_bits: 1,
vcc: 3.3
});
// Start continuous reception
await uart.start_rx();
// Send a command
await uart.tx("AT\r\n");
// Wait for response
await new Promise(resolve => setTimeout(resolve, 100));
// Read response
const response = await uart.rx();
console.log("Response:", Buffer.from(response).toString());
// Stop reception and disable
await uart.stop_rx();
await uart.disable();
from ikalogic_at1000 import AT1000
import asyncio
# Find and connect to device
devices = await AT1000.find_devices(500)
tester = devices[0]
# Access UART interface 0
uart = tester.com.uart(0)
# Enable with standard 115200 8N1 configuration
await uart.enable({
'baud_rate': 115200,
'data_bits': 8,
'parity': 'none',
'stop_bits': 1,
'vcc': 3.3
})
# Start continuous reception
await uart.start_rx()
# Send a command
await uart.tx("AT\r\n")
# Wait for response
await asyncio.sleep(0.1)
# Read response
response = await uart.rx()
print(f"Response: {bytes(response).decode()}")
# Stop reception and disable
await uart.stop_rx()
await uart.disable()
Common Patterns​
AT Command Interface​
- NodeJS
- Python
async function sendATCommand(uart, command, timeout = 1000) {
// Clear any pending data
await uart.rx();
// Send command
await uart.tx(command + "\r\n");
// Wait for response
await new Promise(resolve => setTimeout(resolve, timeout));
// Read response
const response = await uart.rx();
return Buffer.from(response).toString().trim();
}
// Usage
await uart.start_rx();
const info = await sendATCommand(uart, "ATI");
console.log("Device info:", info);
const signal = await sendATCommand(uart, "AT+CSQ");
console.log("Signal quality:", signal);
import asyncio
async def send_at_command(uart, command, timeout=1.0):
# Clear any pending data
await uart.rx()
# Send command
await uart.tx(command + "\r\n")
# Wait for response
await asyncio.sleep(timeout)
# Read response
response = await uart.rx()
return bytes(response).decode().strip()
# Usage
await uart.start_rx()
info = await send_at_command(uart, "ATI")
print(f"Device info: {info}")
signal = await send_at_command(uart, "AT+CSQ")
print(f"Signal quality: {signal}")
GPS NMEA Receiver​
- NodeJS
- Python
// Configure for GPS module (9600 baud typical)
await uart.enable({
baud_rate: 9600,
data_bits: 8,
parity: 'none',
stop_bits: 1,
vcc: 3.3
});
await uart.start_rx();
// Read NMEA sentences
let buffer = '';
while (true) {
const data = await uart.rx();
if (data.length > 0) {
buffer += Buffer.from(data).toString();
// Process complete sentences
const lines = buffer.split('\r\n');
buffer = lines.pop(); // Keep incomplete sentence
for (const line of lines) {
if (line.startsWith('$GPGGA')) {
console.log("Position:", line);
} else if (line.startsWith('$GPRMC')) {
console.log("Navigation:", line);
}
}
}
await new Promise(resolve => setTimeout(resolve, 100));
}
import asyncio
# Configure for GPS module (9600 baud typical)
await uart.enable({
'baud_rate': 9600,
'data_bits': 8,
'parity': 'none',
'stop_bits': 1,
'vcc': 3.3
})
await uart.start_rx()
# Read NMEA sentences
buffer = ''
while True:
data = await uart.rx()
if len(data) > 0:
buffer += bytes(data).decode()
# Process complete sentences
lines = buffer.split('\r\n')
buffer = lines.pop() # Keep incomplete sentence
for line in lines:
if line.startswith('$GPGGA'):
print(f"Position: {line}")
elif line.startswith('$GPRMC'):
print(f"Navigation: {line}")
await asyncio.sleep(0.1)
Binary Protocol​
- NodeJS
- Python
// Send binary command with header and checksum
function buildPacket(command, data) {
const packet = [0xAA, 0x55, command, data.length, ...data];
const checksum = packet.reduce((a, b) => a ^ b, 0);
return [...packet, checksum];
}
// Read binary response
async function readPacket(uart, timeout = 1000) {
const startTime = Date.now();
let buffer = [];
while (Date.now() - startTime < timeout) {
const data = await uart.rx();
buffer.push(...data);
// Check for complete packet
if (buffer.length >= 4 && buffer[0] === 0xAA && buffer[1] === 0x55) {
const length = buffer[3];
if (buffer.length >= 5 + length) {
return buffer.slice(0, 5 + length);
}
}
await new Promise(resolve => setTimeout(resolve, 10));
}
throw new Error("Timeout waiting for packet");
}
// Usage
const packet = buildPacket(0x01, [0x10, 0x20]);
await uart.tx(packet);
const response = await readPacket(uart);
import asyncio
from functools import reduce
# Send binary command with header and checksum
def build_packet(command, data):
packet = [0xAA, 0x55, command, len(data)] + list(data)
checksum = reduce(lambda a, b: a ^ b, packet, 0)
return packet + [checksum]
# Read binary response
async def read_packet(uart, timeout=1.0):
start_time = asyncio.get_event_loop().time()
buffer = []
while asyncio.get_event_loop().time() - start_time < timeout:
data = await uart.rx()
buffer.extend(data)
# Check for complete packet
if len(buffer) >= 4 and buffer[0] == 0xAA and buffer[1] == 0x55:
length = buffer[3]
if len(buffer) >= 5 + length:
return buffer[:5 + length]
await asyncio.sleep(0.01)
raise TimeoutError("Timeout waiting for packet")
# Usage
packet = build_packet(0x01, [0x10, 0x20])
await uart.tx(packet)
response = await read_packet(uart)
Line-Based Protocol​
- NodeJS
- Python
class LineReader {
constructor(uart) {
this.uart = uart;
this.buffer = '';
}
async readLine(timeout = 5000) {
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
const data = await this.uart.rx();
this.buffer += Buffer.from(data).toString();
const newlineIndex = this.buffer.indexOf('\n');
if (newlineIndex !== -1) {
const line = this.buffer.substring(0, newlineIndex).replace('\r', '');
this.buffer = this.buffer.substring(newlineIndex + 1);
return line;
}
await new Promise(resolve => setTimeout(resolve, 10));
}
throw new Error("Timeout waiting for line");
}
async writeLine(text) {
await this.uart.tx(text + '\r\n');
}
}
// Usage
const reader = new LineReader(uart);
await reader.writeLine("GET STATUS");
const status = await reader.readLine();
console.log("Status:", status);
import asyncio
class LineReader:
def __init__(self, uart):
self.uart = uart
self.buffer = ''
async def read_line(self, timeout=5.0):
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < timeout:
data = await self.uart.rx()
self.buffer += bytes(data).decode()
newline_index = self.buffer.find('\n')
if newline_index != -1:
line = self.buffer[:newline_index].replace('\r', '')
self.buffer = self.buffer[newline_index + 1:]
return line
await asyncio.sleep(0.01)
raise TimeoutError("Timeout waiting for line")
async def write_line(self, text):
await self.uart.tx(text + '\r\n')
# Usage
reader = LineReader(uart)
await reader.write_line("GET STATUS")
status = await reader.read_line()
print(f"Status: {status}")
Echo Test​
- NodeJS
- Python
// Loop TX to RX for echo test
async function echoTest(uart, testData) {
await uart.start_rx();
// Send test data
await uart.tx(testData);
// Wait for echo
await new Promise(resolve => setTimeout(resolve, 100));
// Read response
const received = await uart.rx();
// Compare
const sent = typeof testData === 'string'
? Array.from(Buffer.from(testData))
: testData;
const match = sent.length === received.length &&
sent.every((v, i) => v === received[i]);
console.log(`Echo test: ${match ? 'PASS' : 'FAIL'}`);
return match;
}
await echoTest(uart, "Hello, World!");
import asyncio
# Loop TX to RX for echo test
async def echo_test(uart, test_data):
await uart.start_rx()
# Send test data
await uart.tx(test_data)
# Wait for echo
await asyncio.sleep(0.1)
# Read response
received = await uart.rx()
# Compare
if isinstance(test_data, str):
sent = list(test_data.encode())
else:
sent = list(test_data)
match = len(sent) == len(received) and all(
s == r for s, r in zip(sent, received)
)
print(f"Echo test: {'PASS' if match else 'FAIL'}")
return match
await echo_test(uart, "Hello, World!")
Notes​
- The UART interface supports TTL-level signals only (not RS-232 voltage levels)
- Use appropriate level shifters for 5V logic when
vccis set higher - Flow control (RTS/CTS) is not supported
- The receive buffer has limited capacity; read frequently to avoid overflow
- For very high baud rates (> 1 Mbps), ensure signal integrity and short cable lengths
- Always call
start_rx()before expecting to receive data - The maximum single transmission is 1024 bytes