Custom Communication Protocol
Raspberry Pi → Arduino • One Clock Wire + One Data Wire
Overview
I designed and implemented a lightweight custom communication protocol to send messages from a Raspberry Pi to an Arduino using only two wires: one for clock and one for data. The protocol includes start/stop flags, byte encoding, and character translation for ASCII-like messaging.
Code
import RPi.GPIO as GPIO
import time
DELAY = 0.0001
CLK = 27
DATA = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(DATA, GPIO.OUT)
GPIO.setup(CLK, GPIO.OUT)
def sendData(data):
if data == 1:
GPIO.output(CLK, GPIO.LOW)
GPIO.output(DATA, GPIO.HIGH)
time.sleep(DELAY)
GPIO.output(CLK, GPIO.HIGH)
time.sleep(DELAY)
elif data == 0:
GPIO.output(CLK, GPIO.LOW)
GPIO.output(DATA, GPIO.LOW)
time.sleep(DELAY)
GPIO.output(CLK, GPIO.HIGH)
time.sleep(DELAY)
def sendByte(data):
binary_str = format(data, '08b')
bits = [int(bit) for bit in binary_str]
for i, bit in enumerate(binary_str):
sendData(bits[i])
def encode(c):
table = { 'START': 0xFF, 'STOP': 0x00, 'A': 0x25, 'B': 0x26, 'C': 0x27, ... }
return table.get(c, None)
def sendString(s):
sendByte(encode('START'))
for c in s:
sendByte(encode(c))
sendByte(encode('STOP'))
try:
while True:
inputStr = input("Enter message: ")
sendString(inputStr)
except KeyboardInterrupt:
print("Exiting...")
GPIO.cleanup()
#define DATA_Pin 3
#define CLK_Pin 4
const int maxMessageLength = 200;
int lastClkState = LOW;
int strtCnt = 0;
int stopCnt = 0;
int charCnt = 0;
bool letter[8];
bool read = false;
char message[maxMessageLength];
int msgIndex = 0;
void setup() {
Serial.begin(9600);
pinMode(DATA_Pin, INPUT);
pinMode(CLK_Pin, INPUT);
}
void loop() {
int currentClkState = digitalRead(CLK_Pin);
if (lastClkState == LOW && currentClkState == HIGH) {
int data = digitalRead(DATA_Pin);
if (read) {
if (data == 0) {
stopCnt++;
} else {
stopCnt = 0;
}
letter[charCnt] = data;
charCnt++;
if (charCnt >= 8) {
char decoded = decodeEightBitChar(letter);
if (msgIndex < maxMessageLength - 1) {
message[msgIndex++] = decoded;
}
charCnt = 0;
}
if (stopCnt == 8) {
message[msgIndex] = '\0';
Serial.println(message);
read = false;
stopCnt = 0;
charCnt = 0;
msgIndex = 0;
}
} else {
if (data == 1) {
strtCnt++;
} else {
strtCnt = 0;
}
if (strtCnt == 8) {
read = true;
strtCnt = 0;
charCnt = 0;
stopCnt = 0;
msgIndex = 0;
}
}
}
lastClkState = currentClkState;
}
char decodeEightBitChar(bool bits[8]) {
byte value = 0;
for (int i = 0; i < 8; i++) {
value = (value << 1) | bits[i];
}
switch (value) {
case 0x00: return NULL;
case 0x81: return '1';
case 0x82: return '2';
case 0x83: return '3';
case 0x84: return '4';
case 0x85: return '5';
case 0x86: return '6';
case 0x87: return '7';
case 0x88: return '8';
case 0x89: return '9';
case 0x8A: return '0';
case 0x8B: return 'a';
case 0x8C: return 'b';
case 0x8D: return 'c';
case 0x8E: return 'd';
case 0x8F: return 'e';
case 0x10: return 'f';
case 0x11: return 'g';
case 0x12: return 'h';
case 0x13: return 'i';
case 0x14: return 'j';
case 0x15: return 'k';
case 0x16: return 'l';
case 0x17: return 'm';
case 0x18: return 'n';
case 0x19: return 'o';
case 0x1A: return 'p';
case 0x1B: return 'q';
case 0x1C: return 'r';
case 0x1D: return 's';
case 0x1E: return 't';
case 0x1F: return 'u';
case 0x20: return 'v';
case 0x21: return 'w';
case 0x22: return 'x';
case 0x23: return 'y';
case 0x24: return 'z';
case 0x25: return 'A';
case 0x26: return 'B';
case 0x27: return 'C';
case 0x28: return 'D';
case 0x29: return 'E';
case 0x2A: return 'F';
case 0x2B: return 'G';
case 0x2C: return 'H';
case 0x2D: return 'I';
case 0x2E: return 'J';
case 0x2F: return 'K';
case 0x30: return 'L';
case 0x31: return 'M';
case 0x32: return 'N';
case 0x33: return 'O';
case 0x34: return 'P';
case 0x35: return 'Q';
case 0x36: return 'R';
case 0x37: return 'S';
case 0x38: return 'T';
case 0x39: return 'U';
case 0x3A: return 'V';
case 0x3B: return 'W';
case 0x3C: return 'X';
case 0x3D: return 'Y';
case 0x3E: return 'Z';
case 0x3F: return ' ';
case 0x40: return '!';
case 0x41: return '?';
case 0x42: return '.';
case 0x43: return '*';
case 0x44: return '/';
case 0x45: return '&';
case 0x46: return ':';
case 0x47: return '"';
case 0x48: return '(';
case 0x49: return ')';
case 0x4A: return '@';
case 0x4B: return ',';
case 0x4C: return '#';
case 0x4D: return '\'';
case 0x4E: return '=';
case 0x4F: return '+';
default: return '?';
}
}
Back to Projects