diff --git a/src/fpga.cpp b/src/fpga.cpp
index ed17cbee2642be445811a6033b530afc4fb0e767..fae3e191de6f6324e87df09a1f9b5e05243d12bf 100644
--- a/src/fpga.cpp
+++ b/src/fpga.cpp
@@ -57,6 +57,8 @@ Fpga::Fpga(list<class Node*>& nodelist)
     pointMap->add_register("fpga_status_R",  0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_BOOLEAN);
     pointMap->add_register("fpga_temp_R",    0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_FLOAT);
     pointMap->add_register("fpga_version_R", 0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
+    pointMap->add_register("fpga_firmware_version_R", 0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
+    pointMap->add_register("fpga_hardware_version_R", 0, nodes.size(), 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
 
 
     uint32_t scrap_span = 0;
@@ -162,6 +164,10 @@ bool Fpga::point(const uint clientId, TermOutput& termout, const char cmd, const
         relative_addr = "fpga/temp";
     } else if(addr == "fpga_version_R") {
         relative_addr = "fpga/name";
+    } else if(addr == "fpga_firmware_version_R") {
+        relative_addr = "fpga/firmware_version";
+    } else if(addr == "fpga_hardware_version_R") {
+        relative_addr = "fpga/hardware_version";        
     } else if(addr == "fpga_scrap_R") {
         relative_addr = "fpga/scrap_R";
     } else if(addr == "fpga_scrap_RW") {
diff --git a/src/node.cpp b/src/node.cpp
index f42c8e526ae869287896e911a54ab096d506239a..799cbca25d987e34361b6d7b286bfa3d0602431a 100644
--- a/src/node.cpp
+++ b/src/node.cpp
@@ -77,7 +77,7 @@ void Node::worker(const int clientId)
 
     printf("Node::worker thread for client[%d] Uniboard=%d New node IP=%s  type=%s localnr=%d globalnr=%d\n",
            clientId,UniboardNr, myIPaddr.c_str(), Type.c_str(), LocalNr, GlobalNr);
-    printf("sizeof(pread_cmd_struct)=%d sizeof(pread_reply_struct)=%d\n",sizeof(pread_reply_struct),sizeof(pread_cmd_struct));
+    printf("sizeof(pread_cmd_struct)=%ld sizeof(pread_reply_struct)=%ld\n",sizeof(pread_reply_struct),sizeof(pread_cmd_struct));
 
     while(WorkersRunning) {
         ssize_t ret;
diff --git a/src/opcua/ua_server.cpp b/src/opcua/ua_server.cpp
index 8ebd670ffd994959ef6f2873996bc16c93516d3f..5ac5f7729d9e7b25e5553cb76fba7df2b8afc3c0 100644
--- a/src/opcua/ua_server.cpp
+++ b/src/opcua/ua_server.cpp
@@ -413,6 +413,7 @@ static void ua_add_Variable_string(UA_Server *server, std::string regname, unsig
     if(is_scalar) {
         UA_String value = UA_STRING_ALLOC((char *)"unknown");
         UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_STRING]);
+        vattr.valueRank = UA_VALUERANK_SCALAR;
         
     } else {
         UA_String *values = (UA_String *) UA_Array_new(size, &UA_TYPES[UA_TYPES_STRING]);
@@ -459,6 +460,7 @@ static void ua_add_Variable_integer(UA_Server *server, std::string regname, unsi
     if(is_scalar) {
         UA_Int32 value = UA_Int32(0);
         UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_INT32]);
+        vattr.valueRank = UA_VALUERANK_SCALAR;
     } else {
         UA_Int32 *values = (UA_Int32 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT32]);
         for(unsigned int i=0;i<size;i++) {
@@ -504,6 +506,7 @@ static void ua_add_Variable_int16(UA_Server *server, std::string regname, unsign
     if(is_scalar) {
         UA_Int16 value = UA_Int16(0);
         UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_INT16]);
+        vattr.valueRank = UA_VALUERANK_SCALAR;
     } else {
         UA_Int16 *values = (UA_Int16 *) UA_Array_new(size, &UA_TYPES[UA_TYPES_INT16]);
         for(unsigned int i=0;i<size;i++) {
@@ -550,6 +553,7 @@ static void ua_add_Variable_float(UA_Server *server, std::string regname, unsign
     if(is_scalar) {
         UA_Float value = UA_Float(0.0);
         UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_FLOAT]);
+        vattr.valueRank = UA_VALUERANK_SCALAR;
     } else {
         UA_Float *values = (UA_Float *) UA_Array_new(size, &UA_TYPES[UA_TYPES_FLOAT]);
         for(unsigned int i=0;i<size;i++) {
@@ -595,6 +599,7 @@ static void ua_add_Variable_boolean(UA_Server *server, std::string regname, unsi
     if(is_scalar) {
         UA_Boolean value = UA_Boolean(false);
         UA_Variant_setScalar(&vattr.value, &value, &UA_TYPES[UA_TYPES_BOOLEAN]);
+        vattr.valueRank = UA_VALUERANK_SCALAR;
     } else {
         UA_Boolean *values = (UA_Boolean *) UA_Array_new(size, &UA_TYPES[UA_TYPES_BOOLEAN]);
         for(unsigned int i=0;i<size;i++) {
diff --git a/src/periph/fpga.cpp b/src/periph/fpga.cpp
index 91099192d45422408fd5aabac48e373d34accdbb..c0a473b79c1675fee592527eb0c9b23a37414995 100644
--- a/src/periph/fpga.cpp
+++ b/src/periph/fpga.cpp
@@ -49,6 +49,7 @@ Periph_fpga::Periph_fpga(UCP *ucp,
     my_expected_design_name      = expected_design_name;
     my_expected_firmware_version = expected_firmware_version;
     my_current_status = "offline";
+    my_current_fw_version = "-.-";
     my_current_temp = -1.;
     
     Enabled = enabled;
@@ -63,6 +64,8 @@ Periph_fpga::Periph_fpga(UCP *ucp,
     registerMap->add_register("fpga/name",    0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
     registerMap->add_register("fpga/stamps",  0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
     registerMap->add_register("fpga/note",    0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
+    registerMap->add_register("fpga/firmware_version", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
+    registerMap->add_register("fpga/hardware_version", 0, 0, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INT16);
     registerMap->add_register("fpga/temp",    0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
     registerMap->add_register("fpga/status",  0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
     registerMap->add_register("fpga/enable_mask_RW", 0, 1, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_BOOLEAN);
@@ -234,6 +237,9 @@ bool Periph_fpga::read_system_info(UCP *ucp, TermOutput& termout)
     uint firmware_version    = (data & 0x00F00000) >> 20;
     uint firmware_subversion = (data & 0x000F0000) >> 16;
     termout.strout << firmware_version << "." << firmware_subversion;
+    my_current_fw_version = std::to_string(firmware_version) + "." + std::to_string(firmware_subversion);
+    
+    my_current_hw_version = (data & 0x0000300) >> 8;
 
     if(design_name == my_expected_design_name && firmware_version >= my_expected_firmware_version) {
         my_current_status = "online";
@@ -277,6 +283,7 @@ bool Periph_fpga::read(UCP *ucp, TermOutput& termout, const std::string addr,
         } else if(addr == "fpga/name"){ 
             string str = read_design_name(ucp);
             termout.strout << str;
+            termout.nof_vals = str.size();
             termout.datatype = format;
             strcpy(termout.val, str.c_str());
             retval = true;
@@ -285,6 +292,10 @@ bool Periph_fpga::read(UCP *ucp, TermOutput& termout, const std::string addr,
         } else if(addr == "fpga/note") {
             termout.strout << read_design_note(ucp);
             retval = true;
+        } else if(addr == "fpga/firmware_version") {
+            retval = read_firmware_version(ucp, termout, format);    
+        } else if(addr == "fpga/hardware_version") {
+            retval = read_hardware_version(ucp, termout, format);    
         } else if(addr == "fpga/temp") {
             retval = read_fpga_temperature(ucp, termout, format);
         } else if(addr == "fpga/epcs_wait_busy") {
@@ -488,6 +499,67 @@ string Periph_fpga::read_design_note(UCP *ucp)
     return (retval ? note : "? (error)");
 }
 
+bool Periph_fpga::read_hardware_version(UCP *ucp, TermOutput& termout, int format)
+{
+    bool retval = true;
+    uint32_t nof_regs = 1;
+    uint32_t nvalues = nof_regs;
+    uint32_t data[20];
+    uint hw_version_nr;
+    string hw_version;
+    memset((void *)data, 0, 20);
+    retval = Read(ucp, "mm/0/unb2b/system/info", 0, nvalues, data);
+    hw_version_nr = (data[0] & 0x0000300) >> 8;
+    if (hw_version_nr == 1) {
+        hw_version = "UniBoard2b";
+    } else if (hw_version_nr == 2) {
+        hw_version = "UniBoard2c";
+    } else {
+        hw_version = "Unknown";
+    }
+    termout.nof_vals = hw_version.size();
+    termout.datatype = format;
+    strcpy(termout.val, hw_version.c_str());
+    termout.strout << "hardware_version= " << hw_version << endl;
+    return retval;
+}
+
+bool Periph_fpga::read_firmware_version(UCP *ucp, TermOutput& termout, int format)
+{
+    uint32_t design_name_regs_offset = 2;
+    uint32_t nof_design_name_regs = 4;
+    uint32_t stamp_regs_offset = 15;
+    uint32_t nof_stamp_regs = 3;
+    
+    bool retval = true;
+    uint32_t data[20];
+    
+    memset((void *)data, 0, 20);
+    retval = Read(ucp, "mm/0/unb2b/system/info", design_name_regs_offset, nof_design_name_regs, data);
+    char *str_ptr = (char *)data;
+    string design_name = string(str_ptr);
+    if (retval == false) return retval;
+    
+    memset((void *)data, 0, 20);
+    retval = Read(ucp, "mm/0/unb2b/system/info", stamp_regs_offset, nof_stamp_regs, data);
+    string date = std::to_string(data[0]);
+    string time = std::to_string(data[1]);
+    string revision = std::to_string(data[2]);
+
+    string firmware_version;
+    firmware_version = date.substr(0,2) + "-" + date.substr(2,2) + "-" + date.substr(4,2);
+    firmware_version += "T";
+    firmware_version += time.substr(0,2) + ":" + time.substr(2,2) + ":" + time.substr(4,2);
+    firmware_version += "_";
+    firmware_version += revision + "-" + design_name;
+
+    termout.nof_vals = firmware_version.size();
+    termout.datatype = format;
+    strcpy(termout.val, firmware_version.c_str());
+    termout.strout << "firmware_version= " << firmware_version << endl;
+    return retval;
+}
+
 bool Periph_fpga::read_stamps(UCP *ucp, TermOutput& termout)
 {
     uint32_t nof_regs = 3;
diff --git a/src/periph/fpga.h b/src/periph/fpga.h
index e217e9c96f9e98d86b94e36c963514d025a0f5c6..0401173af0d1833c2e6fc86d3b296fe887b0b831 100644
--- a/src/periph/fpga.h
+++ b/src/periph/fpga.h
@@ -35,7 +35,11 @@ private:
   RegisterMap *registerMap;
   std::string my_expected_design_name;
   uint my_expected_firmware_version;
+  
   std::string my_current_status;
+  std::string my_current_fw_version;
+  uint my_current_hw_version;
+  
   float my_current_temp;
   bool Enabled;
 
@@ -65,6 +69,8 @@ private:
   bool read_fpga_enable_mask(TermOutput& termout, int format);
   bool write_fpga_enable_mask(const char *data);
 
+  bool read_hardware_version(UCP *ucp, TermOutput& termout, int format);
+  bool read_firmware_version(UCP *ucp, TermOutput& termout, int format);
   bool read_stamps(UCP *ucp, TermOutput& termout);
   bool read_fpga_temp(TermOutput& termout);
 
diff --git a/src/tr.cpp b/src/tr.cpp
index a1adc222f8d2b2fef4b3c855958604353cccfa49..353231945b70868b18b89311aef64e25fef264f7 100644
--- a/src/tr.cpp
+++ b/src/tr.cpp
@@ -58,10 +58,11 @@ TranslatorMap::TranslatorMap()
     translatorMap = new RegisterMap();
 
     // Add translator (virtual) registers:
-    translatorMap->add_register("tr_reload_W", 0, 1, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_BOOLEAN);
-    translatorMap->add_register("tr_busy_R",   0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_BOOLEAN);
-    translatorMap->add_register("tr_tod_R",    0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
-    translatorMap->add_register("tr_uptime_R", 0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
+    translatorMap->add_register("tr_reload_W",           0, 1, 0xffffffff, 0, "RW", "COMP", 0, REG_FORMAT_BOOLEAN);
+    translatorMap->add_register("tr_software_version_R", 0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_STRING);
+    translatorMap->add_register("tr_busy_R",             0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_BOOLEAN);
+    translatorMap->add_register("tr_tod_R",              0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
+    translatorMap->add_register("tr_uptime_R",           0, 1, 0xffffffff, 0, "RO", "COMP", 0, REG_FORMAT_INTEGER);
 }
 
 
@@ -95,6 +96,8 @@ bool TranslatorMap::translator(const uint clientId, TermOutput& termout, const c
             cout << "Tr: tr_reload_W: initiate RELOAD now" << endl;
             raise(SIGHUP);
         }
+    } else if(addr == "tr_software_version_R") {
+        strcpy(termout.val, TR_SW_VERSION);
     } else if(addr == "tr_busy_R") {
         bool *ptr_out = (bool *)termout.val;
         *ptr_out = (bool)SD.busy;
diff --git a/src/tr.h b/src/tr.h
index 15e1358efc1a49d5d2f5b5050f87f5d99a72ec00..a862ea2209ca48b40f03ad423171adbd65c7b35b 100644
--- a/src/tr.h
+++ b/src/tr.h
@@ -29,6 +29,8 @@
 #include "tools/util.h"
 #include "registers.h"
 
+#define TR_SW_VERSION "2021-04-13T14:06:22_sdptr"
+
 namespace ublas = boost::numeric::ublas;