diff --git a/arduino/protocol/lib/commsControl/commsConstants.h b/arduino/protocol/lib/commsControl/commsConstants.h
index 422f9066d4b9d789ad4eb04d5550b1a1f7598a52..1d9f3088644a95c8906c993b743e53d00797e542 100644
--- a/arduino/protocol/lib/commsControl/commsConstants.h
+++ b/arduino/protocol/lib/commsControl/commsConstants.h
@@ -3,7 +3,7 @@
 
 #include <Arduino.h>
 
-#define CONST_MAX_SIZE_QUEUE 1
+#define CONST_MAX_SIZE_QUEUE 16
 #define CONST_MAX_SIZE_PACKET 64
 #define CONST_MAX_SIZE_BUFFER 128
 #define CONST_MIN_SIZE_PACKET 7
diff --git a/raspberry-dataserver/commsControl.py b/raspberry-dataserver/commsControl.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a3f3a0e451a6184b5b3934caa779e7414641c3d
--- /dev/null
+++ b/raspberry-dataserver/commsControl.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python3
+
+# Communication protocol between rasp and arduino based on HDLC format
+# author Peter Svihra <peter.svihra@cern.ch>
+
+import serial
+from serial.tools import list_ports
+
+import time
+
+import commsFormat
+from collections import deque
+import logging
+logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
+
+import asyncio
+import serial_asyncio
+
+# communication class that governs talking between devices
+class commsControl(asyncio.Protocol):
+    def __init__(self, queueSize = 16):
+        # takes care of all serial port initializations
+        super().__init__()
+        self.transport_ = None
+
+        # queues are FIFO ring-buffers of the defined size
+        self.alarms_   = deque(maxlen = queueSize)
+        self.commands_ = deque(maxlen = queueSize)
+        self.data_     = deque(maxlen = queueSize)
+        
+        # needed to find packet frames
+        self.received_ = []
+        self.foundStart_ = False
+        self.timeLastTransmission_ = int(round(time.time() * 1000))
+        
+    # virtual function from asyncio.Protocol
+    def connection_made(self, transport):
+        self.transport_ = transport
+        logging.info('port opened')
+        self.transport_.serial.rts = False # no idea what this is, copy-pasted
+     
+    # virtual function from asyncio.Protocol, reads from serial port, "random" number of bytes
+    def data_received(self, data):
+        self.receiver(data)
+     
+    # virtual function from asyncio.Protocol
+    def connection_lost(self, exc):
+        logging.info('port closed')
+        self.transport_.loop.stop()
+     
+    # virtual function from asyncio.Protocol
+    def pause_writing(self):
+        logging.info('pause writing')
+        logging.debug(self.transport_.get_write_buffer_size())
+    
+    # virtual function from asyncio.Protocol
+    def resume_writing(self):
+        logging.debug(self.transport_.get_write_buffer_size())
+        logging.info('resume writing')
+        
+    # have yet to figure out how to call this automatically
+    def sender(self):
+        self.checkQueue(self.alarms_  ,  10)
+        self.checkQueue(self.commands_,  50)
+        self.checkQueue(self.data_    , 100)
+    
+    def checkQueue(queue, timeout):
+        if len(queue) > 0:
+            if int(round(time.time() * 1000)) > (self.timeLastTransmission_ + timeout):
+                self.send(queue[0])
+
+    def receiver(self, data):
+        for byte in data:
+            byte = bytes([byte])
+            # TODO: this could be written in more pythonic way
+            # force read byte by byte
+            self.received_.append(byte)
+            logging.debug(byte)
+            if not self.foundStart_ and byte == bytes([0x7E]):
+                self.foundStart_    = True
+                self.receivedStart_ = len(self.received_)
+            elif byte == bytes([0x7E]) :
+                decoded = self.decoder(self.received_, self.receivedStart_)
+                if decoded is not None:
+                    logging.debug("Preparing ACK")
+                    self.send(commsFormat.commsACK(address = decoded[1]))
+                else:
+                    logging.debug("Preparing NACK")
+                    self.send(commsFormat.commsNACK(address = decoded[1]))
+                
+                self.received_.clear()
+                
+                self.foundStart_    = False
+                self.receivedStart_ = -1                
+        
+    def registerData(self, value):
+        tmpData = commsFormat.commsDATA()
+        tmpData.setInformation(value)
+        self.data_.append(tmpData)
+        
+    def send(self, comms):
+        logging.debug("Sending data...")
+        self.transport_.write(self.encoder(comms.getData()))
+
+    # escape any 0x7D or 0x7E with 0x7D and swap bit 5
+    def escapeByte(self, byte):
+        if byte == 0x7D or byte == 0x7E:
+            return [0x7D, byte ^ (1<<5)]
+        else:
+            return [byte]
+
+    # encoding data according to the protocol - escape any 0x7D or 0x7E with 0x7D and swap 5 bit
+    def encoder(self, data):
+        try:
+            stream = [escaped for byte in data[1:-1] for escaped in self.escapeByte(byte)]
+            result = bytearray([data[0]] + stream + [data[-1]])
+            return result
+        except:
+            return None
+    
+    # decoding data according to the defined protocol - escape any 0x7D or 0x7E with 0x7D and swap 5 bit
+    def decoder(self, data, start):
+        try:
+            packets = data[start:-1]
+
+            indRemove = [idx for idx in range(len(packets)) if packets[idx] == bytes([0x7D])]
+            indChange = [idx+1 for idx in indRemove]
+
+            stream = [packets[idx][0] ^ (1<<5) if idx in indChange else packets[idx][0] for idx in range(len(packets)) if idx not in indRemove]
+            result = bytearray([data[start - 1][0]] + stream + [data[-1][0]])
+            return result
+        except:
+            return None
+
+if __name__ == "__main__" :
+    # get port number for arduino, mostly for debugging
+    for port in list_ports.comports():
+        try:
+            if "ARDUINO" in port.manufacturer.upper():
+                port = port.device
+        except:
+            pass
+
+    loop = asyncio.get_event_loop()
+    connection = serial_asyncio.create_serial_connection(loop, commsControl, port, baudrate=115200)
+    loop.run_until_complete(connection)
+    loop.run_forever()
+    loop.close()
\ No newline at end of file
diff --git a/raspberry-dataserver/commsFormat.py b/raspberry-dataserver/commsFormat.py
new file mode 100644
index 0000000000000000000000000000000000000000..8252da29bfcfcc5695e39f6808eff6ef462192cf
--- /dev/null
+++ b/raspberry-dataserver/commsFormat.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+# Communication protocol based on HDLC format
+# author Peter Svihra <peter.svihra@cern.ch>
+
+import libscrc
+
+# basic format based on HDLC
+class commsFormat:
+    def __init__(self, infoSize = 0, address = 0x00, control = [0x00, 0x00]):
+        self.data_ = bytearray(7 + infoSize)
+        self.infoSize_ = infoSize
+        self.crc_ = None
+        
+        self.assignBytes(self.getStart()  , bytes([0x7E]))
+        self.assignBytes(self.getAddress(), bytes([address]))
+        self.assignBytes(self.getControl(), bytes(control))
+        self.assignBytes(self.getStop()   , bytes([0x7E]))
+        
+    def getStart(self):
+        return 0
+    def getAddress(self):
+        return 1
+    def getControl(self):
+        return 2
+    def getInformation(self):
+        return 4
+    def getFcs(self):
+        return 4 + self.infoSize_
+    def getStop(self):
+        return 4 + self.infoSize_ + 2
+    
+    def assignBytes(self, start, values, isCrc = False):
+        for idx in range(len(values)):
+            self.data_[start + idx] = values[idx]
+        if not isCrc:
+            self.generateCrc()
+        
+    # generate checksum
+    def generateCrc(self, assign = True):
+        self.crc_ = libscrc.x25(bytes(self.data_[self.getAddress():self.getFcs()])).to_bytes(2, byteorder='little')
+        if assign:
+            self.assignBytes(self.getFcs(), self.crc_, isCrc = True)
+            
+    def compareCrc(self):
+        self.generateCrc(False)
+        
+        return (self.crc_ == self.fcs_)
+    
+    def setInformation(self, value, size = 2):
+        # convert provided value
+        self.assignBytes(self.getInformation(), value.to_bytes(size, byteorder='little'))
+    
+    def getData(self):
+        return self.data_
+
+    def setData(self, data):
+        self.infoSize_ = len(data)
+        self.data_     = data.to_bytes(self.infoSize_, byteorder='little')
+        
+# DATA specific formating
+class commsDATA(commsFormat):
+    def __init__(self):
+        super().__init__(infoSize = 8, address = 0x40)
+
+# CMD specific formating
+class commsCMD(commsFormat):
+    def __init__(self):
+        super().__init__(infoSize = 8, address = 0x80)
+
+# ALARM specific formating
+class commsALARM(commsFormat):
+    def __init__(self):
+        super().__init__(infoSize = 4, address = 0xC0)
+
+# ACK specific formating
+class commsACK(commsFormat):
+    def __init__(self, address):
+        super().__init__(control = [0x00, 0x01], address = address)
+        
+# NACK specific formating
+class commsNACK(commsFormat):
+    def __init__(self, address):
+        super().__init__(control = [0x00, 0x05], address = address)