diff --git a/tangostationcontrol/tangostationcontrol/clients/opcua_client.py b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
index 073933ad7dc01576e3817505c81c970fbe87ff1d..f94ec4e16fa7d1baf117d8108bc3f896560df70f 100644
--- a/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
+++ b/tangostationcontrol/tangostationcontrol/clients/opcua_client.py
@@ -243,6 +243,21 @@ class ProtocolAttribute:
         value = await self.node.get_value()
 
         try:
+            # Pytango strings are Latin-1, and will crash on receiving Unicode strings
+            # (see https://gitlab.com/tango-controls/pytango/-/issues/72)
+            # So we explicitly convert to Latin-1 and replace errors with '?'.
+            #
+            # Note that PyTango also accepts byte arrays as strings, so we don't
+            # have to actually decode() the result.
+
+            def fix_string(s):
+                return s.encode('latin-1',errors="replace").decode('latin-1')
+
+            if type(value) == list and len(value) > 0 and type(value[0]) == str:
+                value = [fix_string(v) for v in value]
+            elif type(value) == str:
+                value = fix_string(value)
+
             if self.dim_y + self.dim_x == 1:
                 # scalar
                 return value
diff --git a/tangostationcontrol/tangostationcontrol/devices/beam.py b/tangostationcontrol/tangostationcontrol/devices/beam.py
index d62a49e368598ccf5868f5c74402233d5eb403cf..afcdf78871e321a2489339f747f61351643790b2 100644
--- a/tangostationcontrol/tangostationcontrol/devices/beam.py
+++ b/tangostationcontrol/tangostationcontrol/devices/beam.py
@@ -87,6 +87,13 @@ class Beam(lofar_device):
     # --------
     # overloaded functions
     # --------
+
+    def init_device(self):
+        super().init_device()
+
+        # thread to perform beam tracking
+        self.HBAT_beam_tracker = None
+
     @log_exceptions()
     def configure_for_initialise(self):
         super().configure_for_initialise()
@@ -126,8 +133,9 @@ class Beam(lofar_device):
     
     @log_exceptions()
     def configure_for_off(self):
-        # Stop thread object
-        self.HBAT_beam_tracker.stop()
+        if self.HBAT_beam_tracker:
+            # Stop thread object
+            self.HBAT_beam_tracker.stop()
 
         super().configure_for_off()
 
diff --git a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
index a483aec43eacf571a6344ee1b1823cf62af96a92..5f0feb5e661dba53d8cd800273d15ae7c35692bd 100644
--- a/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
+++ b/tangostationcontrol/tangostationcontrol/devices/sdp/sdp.py
@@ -112,6 +112,10 @@ class SDP(opcua_device):
     FPGA_boot_image_RW = attribute_wrapper(comms_annotation=["FPGA_boot_image_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
     FPGA_global_node_index_R = attribute_wrapper(comms_annotation=["FPGA_global_node_index_R"], datatype=numpy.uint32, dims=(16,))
     FPGA_hardware_version_R = attribute_wrapper(comms_annotation=["FPGA_hardware_version_R"], datatype=numpy.str, dims=(16,))
+    FPGA_pps_present_R = attribute_wrapper(comms_annotation=["FPGA_pps_present_R"], datatype=numpy.bool_, dims=(16,))
+    FPGA_pps_capture_cnt_R = attribute_wrapper(comms_annotation=["FPGA_pps_capture_cnt_R"], datatype=numpy.uint32, dims=(16,))
+    FPGA_pps_expected_cnt_R = attribute_wrapper(comms_annotation=["FPGA_pps_expected_cnt_R"], datatype=numpy.uint32, dims=(16,))
+    FPGA_pps_expected_cnt_RW = attribute_wrapper(comms_annotation=["FPGA_pps_expected_cnt_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
     FPGA_processing_enable_R = attribute_wrapper(comms_annotation=["FPGA_processing_enable_R"], datatype=numpy.bool_, dims=(16,))
     FPGA_processing_enable_RW = attribute_wrapper(comms_annotation=["FPGA_processing_enable_RW"], datatype=numpy.bool_, dims=(16,), access=AttrWriteType.READ_WRITE)
     FPGA_scrap_R = attribute_wrapper(comms_annotation=["FPGA_scrap_R"], datatype=numpy.int32, dims=(8192,))
@@ -128,6 +132,7 @@ class SDP(opcua_device):
     FPGA_sdp_info_station_id_RW = attribute_wrapper(comms_annotation=["FPGA_sdp_info_station_id_RW"], datatype=numpy.uint32, dims=(16,), access=AttrWriteType.READ_WRITE)
     FPGA_subband_weights_R = attribute_wrapper(comms_annotation=["FPGA_subband_weights_R"], datatype=numpy.uint32, dims=(12 * 512, 16))
     FPGA_subband_weights_RW = attribute_wrapper(comms_annotation=["FPGA_subband_weights_RW"], datatype=numpy.uint32, dims=(12 * 512, 16), access=AttrWriteType.READ_WRITE)
+    FPGA_time_since_last_pps_R = attribute_wrapper(comms_annotation=["FPGA_time_since_last_pps_R"], datatype=numpy.uint32, dims=(16,))
     FPGA_temp_R = attribute_wrapper(comms_annotation=["FPGA_temp_R"], datatype=numpy.float_, dims=(16,))
     FPGA_wg_amplitude_R = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_R"], datatype=numpy.float_, dims=(12, 16))
     FPGA_wg_amplitude_RW = attribute_wrapper(comms_annotation=["FPGA_wg_amplitude_RW"], datatype=numpy.float_, dims=(12, 16), access=AttrWriteType.READ_WRITE)
diff --git a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
index 25968deded93d8d45160c5a1949521784ab59e7a..4582c608888b2dbb2d0b26b5abd3f1a683c76c6c 100644
--- a/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
+++ b/tangostationcontrol/tangostationcontrol/test/clients/test_opcua_client.py
@@ -178,6 +178,35 @@ class TestOPCua(base.AsyncTestCase):
                 comp = val == get_test_value()
                 self.assertTrue(comp.all(), "Read value unequal to expected value: \n\t{} \n\t{}".format(val, get_test_value()))
 
+    async def test_read_unicode(self):
+        """
+        Test whether unicode characters are replaced by '?'.
+        """
+        # test 0-2 dimensions of strings
+        for dims in range(0,2):
+            # wrap a value in the current number of dimensions
+            def wrap_dims(x):
+              if dims == 0:
+                 return x
+              elif dims == 1:
+                 return [x]
+              elif dims == 2:
+                 return [[x]]
+
+            # return a constructed value with unicode
+            async def get_value():
+               return wrap_dims(b'foo \xef\xbf\xbd bar'.decode('utf-8'))
+
+            m_node = asynctest.asynctest.CoroutineMock()
+            m_node.get_value = get_value
+
+            # create the ProtocolAttribute to test
+            test = opcua_client.ProtocolAttribute(m_node, 1, 0, opcua_client.numpy_to_OPCua_dict[str])
+
+            # check if unicode is replaced by ?
+            val = await test.read_function()
+            self.assertEqual(wrap_dims("foo ? bar"), val)
+
     def test_type_map(self):
         for numpy_type, opcua_type in opcua_client.numpy_to_OPCua_dict.items():
             # derive a default value that can get lost in a type translation