diff --git a/MQ/monitor/CMakeLists.txt b/MQ/monitor/CMakeLists.txt
index b4832fbd67b5bcadd92d3de53436a61ed15abb56..e8366b2b7f979524e6d2fb91149a75f44f9f0e19 100644
--- a/MQ/monitor/CMakeLists.txt
+++ b/MQ/monitor/CMakeLists.txt
@@ -3,6 +3,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/startMQSamplerT0Monitor2020.sh.in ${C
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/startMQSamplerTofMonitor2020.sh.in ${CMAKE_BINARY_DIR}/bin/MQ/topologies/startMQSamplerTofMonitor2020.sh)
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/startMQSamplerT0Monitor2021.sh.in ${CMAKE_BINARY_DIR}/bin/MQ/topologies/startMQSamplerT0Monitor2021.sh)
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/startMQSamplerTofMonitor2021.sh.in ${CMAKE_BINARY_DIR}/bin/MQ/topologies/startMQSamplerTofMonitor2021.sh)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/startMQSamplerPsdMonitor2021.sh.in ${CMAKE_BINARY_DIR}/bin/MQ/topologies/startMQSamplerPsdMonitor2021.sh)
+
 
 set(INCLUDE_DIRECTORIES
     ${CMAKE_CURRENT_SOURCE_DIR}
@@ -14,8 +16,11 @@ set(INCLUDE_DIRECTORIES
     ${CBMROOT_SOURCE_DIR}/fles/flestools
     ${CBMDATA_DIR}
     ${CBMDATA_DIR}/tof
+    ${CBMDATA_DIR}/psd
     ${CBMDATA_DIR}/raw
     ${CBMBASE_DIR}
+
+    ${CBMDETECTORBASE_DIR}/psd
 )
 
 Set(SYSTEM_INCLUDE_DIRECTORIES
@@ -107,3 +112,24 @@ set(DEPENDENCIES
 #GENERATE_LIBRARY()
 GENERATE_EXECUTABLE()
 
+set(EXE_NAME PsdMonitorMcbm2018)
+set(SRCS CbmDeviceMonitorPsd.cxx runMonitorPsd.cxx)
+
+set(DEPENDENCIES
+  ${DEPENDENCIES}
+  ${FAIR_LIBS}
+  ${BOOST_LIBS}
+  fles_ipc
+  CbmFlibMcbm2018
+  CbmFlibFlesTools
+  CbmBase
+  CbmData
+  Core
+  RIO
+  Net
+  Hist
+  RHTTP
+)
+#GENERATE_LIBRARY()
+GENERATE_EXECUTABLE()
+
diff --git a/MQ/monitor/CbmDeviceMonitorPsd.cxx b/MQ/monitor/CbmDeviceMonitorPsd.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..697bb62dd9304edcbd4638302ab094dba9d679f7
--- /dev/null
+++ b/MQ/monitor/CbmDeviceMonitorPsd.cxx
@@ -0,0 +1,339 @@
+/**
+ * CbmDeviceMonitorPsd.cxx
+ *
+ * @since 2021-02-17
+ * @author N. Karpushkin
+ * @comment based on CbmDeviceMonitorT0 by F. Uhlig
+ */
+
+#include "CbmDeviceMonitorPsd.h"
+
+#include "CbmFlesCanvasTools.h"
+#include "CbmMQDefs.h"
+#include "CbmMcbm2018MonitorAlgoPsd.h"
+
+#include "StorableTimeslice.hpp"
+
+#include "FairMQLogger.h"
+#include "FairMQProgOptions.h"  // device->fConfig
+#include "FairParGenericSet.h"
+
+#include "TCanvas.h"
+#include "TFile.h"
+#include "TH1.h"
+#include "TList.h"
+#include "TNamed.h"
+
+#include "BoostSerializer.h"
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/utility.hpp>
+
+#include <array>
+#include <iomanip>
+#include <stdexcept>
+#include <string>
+
+#include "RootSerializer.h"
+struct InitTaskError : std::runtime_error {
+  using std::runtime_error::runtime_error;
+};
+
+using namespace std;
+
+CbmDeviceMonitorPsd::CbmDeviceMonitorPsd()
+  : fbIgnoreOverlapMs {false}
+  , fsChannelNameDataInput {"psdcomponent"}
+  , fsChannelNameHistosInput {"histogram-in"}
+  , fsChannelNameHistosConfig {"histo-conf"}
+  , fsChannelNameCanvasConfig {"canvas-conf"}
+  , fuPublishFreqTs {100}
+  , fdMinPublishTime {0.5}
+  , fdMaxPublishTime {5.0}
+  , fuHistoryHistoSize {3600}
+  , fviHistoChargeArgs(3, 0)
+  , fviHistoAmplArgs(3, 0)
+  , fviHistoZLArgs(3, 0)
+  , fsAllowedChannels {fsChannelNameDataInput}
+  , fParCList {nullptr}
+  , fulNumMessages {0}
+  , fulTsCounter {0}
+  , fLastPublishTime {std::chrono::system_clock::now()}
+  , fMonitorAlgo {new CbmMcbm2018MonitorAlgoPsd()}
+  , fArrayHisto {}
+  , fvpsHistosFolder {}
+  , fvpsCanvasConfig {}
+{
+}
+
+void CbmDeviceMonitorPsd::InitTask()
+try {
+  /// Read options from executable
+  LOG(info) << "Init options for CbmMqStarHistoServer.";
+  fbIgnoreOverlapMs         = fConfig->GetValue<bool>("IgnOverMs");
+  fbMonitorMode             = fConfig->GetValue<bool>("MonitorMode");
+  fbMonitorChanMode         = fConfig->GetValue<bool>("MonitorChanMode");
+  fbMonitorWfmMode          = fConfig->GetValue<bool>("MonitorWfmMode");
+  fbMonitorFitMode          = fConfig->GetValue<bool>("MonitorFitMode");
+  fuHistoryHistoSize        = fConfig->GetValue<uint32_t>("HistEvoSz");
+  fviHistoChargeArgs        = fConfig->GetValue<std::vector<int>>("HistChrgArgs");
+  fviHistoAmplArgs          = fConfig->GetValue<std::vector<int>>("HistAmplArgs");
+  fviHistoZLArgs            = fConfig->GetValue<std::vector<int>>("HistZlArgs");
+  fuPublishFreqTs           = fConfig->GetValue<uint32_t>("PubFreqTs");
+  fdMinPublishTime          = fConfig->GetValue<double_t>("PubTimeMin");
+  fdMaxPublishTime          = fConfig->GetValue<double_t>("PubTimeMax");
+  fsChannelNameDataInput    = fConfig->GetValue<std::string>("TsNameIn");
+  fsChannelNameHistosInput  = fConfig->GetValue<std::string>("ChNameIn");
+  fsChannelNameHistosConfig = fConfig->GetValue<std::string>("ChNameHistCfg");
+  fsChannelNameCanvasConfig = fConfig->GetValue<std::string>("ChNameCanvCfg");
+  fsAllowedChannels[0]      = fsChannelNameDataInput;
+
+  LOG(info) << "Histograms publication frequency in TS:    " << fuPublishFreqTs;
+  LOG(info) << "Histograms publication min. interval in s: " << fdMinPublishTime;
+  LOG(info) << "Histograms publication max. interval in s: " << fdMaxPublishTime;
+
+  // Get the information about created channels from the device
+  // Check if the defined channels from the topology (by name)
+  // are in the list of channels which are possible/allowed
+  // for the device
+  // The idea is to check at initilization if the devices are
+  // properly connected. For the time beeing this is done with a
+  // nameing convention. It is not avoided that someone sends other
+  // data on this channel.
+  //logger::SetLogLevel("INFO");
+
+  int noChannel = fChannels.size();
+  LOG(info) << "Number of defined channels: " << noChannel;
+  for (auto const& entry : fChannels) {
+    LOG(info) << "Channel name: " << entry.first;
+    if (std::string::npos != entry.first.find(fsChannelNameDataInput)) {
+      if (!IsChannelNameAllowed(entry.first)) throw InitTaskError("Channel name does not match.");
+      OnData(entry.first, &CbmDeviceMonitorPsd::HandleData);
+    }  // if( entry.first.find( "ts" )
+  }    // for( auto const &entry : fChannels )
+  InitContainers();
+}
+catch (InitTaskError& e) {
+  LOG(error) << e.what();
+  // Wrapper defined in CbmMQDefs.h to support different FairMQ versions
+  cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound);
+}
+
+bool CbmDeviceMonitorPsd::IsChannelNameAllowed(std::string channelName)
+{
+  for (auto const& entry : fsAllowedChannels) {
+    std::size_t pos1 = channelName.find(entry);
+    if (pos1 != std::string::npos) {
+      const vector<std::string>::const_iterator pos =
+        std::find(fsAllowedChannels.begin(), fsAllowedChannels.end(), entry);
+      const vector<std::string>::size_type idx = pos - fsAllowedChannels.begin();
+      LOG(info) << "Found " << entry << " in " << channelName;
+      LOG(info) << "Channel name " << channelName << " found in list of allowed channel names at position " << idx;
+      return true;
+    }  // if (pos1!=std::string::npos)
+  }    // for(auto const &entry : fsAllowedChannels)
+  LOG(info) << "Channel name " << channelName << " not found in list of allowed channel names.";
+  LOG(error) << "Stop device.";
+  return false;
+}
+
+Bool_t CbmDeviceMonitorPsd::InitContainers()
+{
+  LOG(info) << "Init parameter containers for CbmDeviceMonitorPsd.";
+
+  fParCList = fMonitorAlgo->GetParList();
+
+  for (int iparC = 0; iparC < fParCList->GetEntries(); iparC++) {
+    FairParGenericSet* tempObj = (FairParGenericSet*) (fParCList->At(iparC));
+    fParCList->Remove(tempObj);
+    std::string paramName {tempObj->GetName()};
+    // NewSimpleMessage creates a copy of the data and takes care of its destruction (after the transfer takes place).
+    // Should only be used for small data because of the cost of an additional copy
+
+    // Her must come the proper Runid
+    std::string message = paramName + ",111";
+    LOG(info) << "Requesting parameter container " << paramName << ", sending message: " << message;
+
+    FairMQMessagePtr req(NewSimpleMessage(message));
+    FairMQMessagePtr rep(NewMessage());
+
+    FairParGenericSet* newObj = nullptr;
+
+    if (Send(req, "parameters") > 0) {
+      if (Receive(rep, "parameters") >= 0) {
+        if (rep->GetSize() != 0) {
+          CbmMQTMessage tmsg(rep->GetData(), rep->GetSize());
+          newObj = static_cast<FairParGenericSet*>(tmsg.ReadObject(tmsg.GetClass()));
+          LOG(info) << "Received unpack parameter from the server:";
+          newObj->print();
+        }
+        else {
+          LOG(error) << "Received empty reply. Parameter not available";
+        }  // if (rep->GetSize() != 0)
+      }    // if (Receive(rep, "parameters") >= 0)
+    }      // if (Send(req, "parameters") > 0)
+    fParCList->AddAt(newObj, iparC);
+    delete tempObj;
+  }  // for ( int iparC = 0; iparC < fParCList->GetEntries(); iparC++ )
+
+  /// Need to add accessors for all options
+  fMonitorAlgo->SetIgnoreOverlapMs(fbIgnoreOverlapMs);
+  fMonitorAlgo->SetMonitorMode(fbMonitorMode);
+  fMonitorAlgo->SetMonitorChanMode(fbMonitorChanMode);
+  fMonitorAlgo->SetMonitorWfmMode(fbMonitorWfmMode);
+  fMonitorAlgo->SetMonitorFitMode(fbMonitorFitMode);
+  fMonitorAlgo->SetHistoryHistoSize(fuHistoryHistoSize);
+  fMonitorAlgo->SetChargeHistoArgs(fviHistoChargeArgs);
+  fMonitorAlgo->SetAmplHistoArgs(fviHistoAmplArgs);
+  fMonitorAlgo->SetZLHistoArgs(fviHistoZLArgs);
+  //fMonitorAlgo->AddMsComponentToList(0, 0x80);
+
+  Bool_t initOK = fMonitorAlgo->InitContainers();
+
+  //   Bool_t initOK = fMonitorAlgo->ReInitContainers();
+
+  /// Histos creation and obtain pointer on them
+  /// Trigger histo creation on all associated algos
+  initOK &= fMonitorAlgo->CreateHistograms();
+
+  /// Obtain vector of pointers on each histo from the algo (+ optionally desired folder)
+  std::vector<std::pair<TNamed*, std::string>> vHistos = fMonitorAlgo->GetHistoVector();
+  /// Obtain vector of pointers on each canvas from the algo (+ optionally desired folder)
+  std::vector<std::pair<TCanvas*, std::string>> vCanvases = fMonitorAlgo->GetCanvasVector();
+
+  /// Add pointers to each histo in the histo array
+  /// Create histo config vector
+  /// ===> Use an std::vector< std::pair< std::string, std::string > > with < Histo name, Folder >
+  ///      and send it through a separate channel using the BoostSerializer
+  for (UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto) {
+    //         LOG(info) << "Registering  " << vHistos[ uHisto ].first->GetName()
+    //                   << " in " << vHistos[ uHisto ].second.data()
+    //                   ;
+    fArrayHisto.Add(vHistos[uHisto].first);
+    std::pair<std::string, std::string> psHistoConfig(vHistos[uHisto].first->GetName(), vHistos[uHisto].second);
+    fvpsHistosFolder.push_back(psHistoConfig);
+
+    /// Serialize the vector of histo config into a single MQ message
+    FairMQMessagePtr messageHist(NewMessage());
+    Serialize<BoostSerializer<std::pair<std::string, std::string>>>(*messageHist, psHistoConfig);
+
+    /// Send message to the common histogram config messages queue
+    if (Send(messageHist, fsChannelNameHistosConfig) < 0) {
+      LOG(error) << "Problem sending histo config";
+      return false;
+    }  // if( Send( messageHist, fsChannelNameHistosConfig ) < 0 )
+
+    LOG(info) << "Config of hist  " << psHistoConfig.first.data() << " in folder " << psHistoConfig.second.data();
+  }  // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
+
+  /// Create canvas config vector
+  /// ===> Use an std::vector< std::pair< std::string, std::string > > with < Canvas name, config >
+  ///      and send it through a separate channel using the BoostSerializer
+  for (UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv) {
+    //         LOG(info) << "Registering  " << vCanvases[ uCanv ].first->GetName()
+    //                   << " in " << vCanvases[ uCanv ].second.data();
+    std::string sCanvName = (vCanvases[uCanv].first)->GetName();
+    std::string sCanvConf = GenerateCanvasConfigString(vCanvases[uCanv].first);
+
+    std::pair<std::string, std::string> psCanvConfig(sCanvName, sCanvConf);
+
+    fvpsCanvasConfig.push_back(psCanvConfig);
+
+    /// Serialize the vector of canvas config into a single MQ message
+    FairMQMessagePtr messageCan(NewMessage());
+    Serialize<BoostSerializer<std::pair<std::string, std::string>>>(*messageCan, psCanvConfig);
+
+    /// Send message to the common canvas config messages queue
+    if (Send(messageCan, fsChannelNameCanvasConfig) < 0) {
+      LOG(error) << "Problem sending canvas config";
+      return false;
+    }  // if( Send( messageCan, fsChannelNameCanvasConfig ) < 0 )
+
+    LOG(info) << "Config string of Canvas  " << psCanvConfig.first.data() << " is " << psCanvConfig.second.data();
+  }  //  for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
+
+  return initOK;
+}
+
+
+// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
+bool CbmDeviceMonitorPsd::HandleData(FairMQMessagePtr& msg, int /*index*/)
+{
+  fulNumMessages++;
+  LOG(debug) << "Received message number " << fulNumMessages << " with size " << msg->GetSize();
+
+  if (0 == fulNumMessages % 10000) LOG(info) << "Received " << fulNumMessages << " messages";
+
+  std::string msgStr(static_cast<char*>(msg->GetData()), msg->GetSize());
+  std::istringstream iss(msgStr);
+  boost::archive::binary_iarchive inputArchive(iss);
+
+  /// Create an empty TS and fill it with the incoming message
+  fles::StorableTimeslice component {0};
+  inputArchive >> component;
+
+  /// Process the Timeslice
+  DoUnpack(component, 0);
+
+  /// Send histograms each 100 time slices. Should be each ~1s
+  /// Use also runtime checker to trigger sending after M s if
+  /// processing too slow or delay sending if processing too fast
+  std::chrono::system_clock::time_point currentTime = std::chrono::system_clock::now();
+  std::chrono::duration<double_t> elapsedSeconds    = currentTime - fLastPublishTime;
+  if ((fdMaxPublishTime < elapsedSeconds.count())
+      || (0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count())) {
+    SendHistograms();
+    fLastPublishTime = std::chrono::system_clock::now();
+  }  // if( ( fdMaxPublishTime < elapsedSeconds.count() ) || ( 0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count() ) )
+
+  return true;
+}
+
+bool CbmDeviceMonitorPsd::SendHistograms()
+{
+  /// Serialize the array of histos into a single MQ message
+  FairMQMessagePtr message(NewMessage());
+  Serialize<RootSerializer>(*message, &fArrayHisto);
+
+  /// Send message to the common histogram messages queue
+  if (Send(message, fsChannelNameHistosInput) < 0) {
+    LOG(error) << "Problem sending data";
+    return false;
+  }  // if( Send( message, fsChannelNameHistosInput ) < 0 )
+
+  /// Reset the histograms after sending them (but do not reset the time)
+  fMonitorAlgo->ResetHistograms(kFALSE);
+
+  return true;
+}
+
+
+CbmDeviceMonitorPsd::~CbmDeviceMonitorPsd() {}
+
+Bool_t CbmDeviceMonitorPsd::DoUnpack(const fles::Timeslice& ts, size_t /*component*/)
+{
+
+  if (kFALSE == fbComponentsAddedToList) {
+    for (uint32_t uCompIdx = 0; uCompIdx < ts.num_components(); ++uCompIdx) {
+      if (kusSysId == ts.descriptor(uCompIdx, 0).sys_id) {
+        fMonitorAlgo->AddMsComponentToList(uCompIdx, kusSysId);
+      }  // if( kusSysId == ts.descriptor( uCompIdx, 0 ).sys_id )
+    }    // for( uint32_t uComp = 0; uComp < ts.num_components(); ++uComp )
+    fbComponentsAddedToList = kTRUE;
+  }  // if( kFALSE == fbComponentsAddedToList )
+
+  if (kFALSE == fMonitorAlgo->ProcessTs(ts)) {
+    LOG(error) << "Failed processing TS " << ts.index() << " in unpacker algorithm class";
+    return kTRUE;
+  }  // if( kFALSE == fMonitorAlgo->ProcessTs( ts ) )
+
+  /// Clear the digis vector in case it was filled
+  fMonitorAlgo->ClearVector();
+
+  if (0 == fulTsCounter % 10000) LOG(info) << "Processed " << fulTsCounter << "TS";
+  fulTsCounter++;
+
+  return kTRUE;
+}
+
+
+void CbmDeviceMonitorPsd::Finish() {}
diff --git a/MQ/monitor/CbmDeviceMonitorPsd.h b/MQ/monitor/CbmDeviceMonitorPsd.h
new file mode 100644
index 0000000000000000000000000000000000000000..44c28213ccfb4ebed4420c679248ca1491f79ef6
--- /dev/null
+++ b/MQ/monitor/CbmDeviceMonitorPsd.h
@@ -0,0 +1,101 @@
+/**
+ * CbmDeviceMonitorPsd.h
+ *
+ * @since 2021-02-17
+ * @author N. Karpushkin
+ * @comment based on CbmDeviceMonitorT0 by F. Uhlig
+ */
+
+#ifndef CBMDEVICEMONITORPSD_H_
+#define CBMDEVICEMONITORPSD_H_
+
+#include "Timeslice.hpp"
+
+#include "FairMQDevice.h"
+
+#include "Rtypes.h"
+#include "TMessage.h"
+#include "TObjArray.h"
+
+#include <chrono>
+#include <map>
+#include <vector>
+
+class TList;
+class CbmMcbm2018MonitorAlgoPsd;
+
+class CbmDeviceMonitorPsd : public FairMQDevice {
+public:
+  CbmDeviceMonitorPsd();
+  virtual ~CbmDeviceMonitorPsd();
+
+protected:
+  virtual void InitTask();
+  bool HandleData(FairMQMessagePtr&, int);
+
+private:
+  /// Constants
+  static const uint16_t kusSysId = 0x80;
+  Bool_t fbComponentsAddedToList = kFALSE;
+
+  /// Control flags
+  Bool_t fbMonitorMode;       //! Switch ON the filling of a minimal set of histograms
+  Bool_t fbIgnoreOverlapMs;   //! Ignore Overlap Ms: all fuOverlapMsNb MS at the end of timeslice
+  Bool_t fbMonitorChanMode;   //! Switch ON the filling channelwise histograms
+  Bool_t fbMonitorWfmMode;    //! Switch ON the filling waveforms histograms
+  Bool_t fbMonitorFitMode;    //! Switch ON the filling waveform fitting histograms
+  Bool_t fbDebugMonitorMode;  //! Switch ON the filling of a additional set of histograms
+
+  /// User settings parameters
+  std::string fsChannelNameDataInput;
+  std::string fsChannelNameHistosInput;
+  std::string fsChannelNameHistosConfig;
+  std::string fsChannelNameCanvasConfig;
+  uint32_t fuPublishFreqTs;
+  double_t fdMinPublishTime;
+  double_t fdMaxPublishTime;
+
+  UInt_t fuHistoryHistoSize;
+  std::vector<Int_t> fviHistoChargeArgs; /** Charge histogram arguments in adc counts **/
+  std::vector<Int_t> fviHistoAmplArgs;   /** Amplitude histogram arguments in adc counts **/
+  std::vector<Int_t> fviHistoZLArgs;     /** ZeroLevel histogram arguments in adc counts **/
+
+
+  /// List of MQ channels names
+  std::vector<std::string> fsAllowedChannels;
+
+  /// Parameters management
+  TList* fParCList;
+
+  /// Statistics & first TS rejection
+  uint64_t fulNumMessages;
+  uint64_t fulTsCounter;
+  std::chrono::system_clock::time_point fLastPublishTime;
+
+  /// Processing algo
+  CbmMcbm2018MonitorAlgoPsd* fMonitorAlgo;
+
+  /// Array of histograms to send to the histogram server
+  TObjArray fArrayHisto;
+  /// Vector of string pairs with ( HistoName, FolderPath ) to send to the histogram server
+  std::vector<std::pair<std::string, std::string>> fvpsHistosFolder;
+  /// Vector of string pairs with ( CanvasName, CanvasConfig ) to send to the histogram server
+  /// Format of Can config is "NbPadX(U);NbPadY(U);ConfigPad1(s);....;ConfigPadXY(s)"
+  /// Format of Pad config is "GrixX(b),GridY(b),LogX(b),LogY(b),LogZ(b),HistoName(s),DrawOptions(s)"
+  std::vector<std::pair<std::string, std::string>> fvpsCanvasConfig;
+
+  bool IsChannelNameAllowed(std::string channelName);
+  Bool_t InitContainers();
+  Bool_t DoUnpack(const fles::Timeslice& ts, size_t component);
+  void Finish();
+  bool SendHistograms();
+};
+
+// special class to expose protected TMessage constructor
+class CbmMQTMessage : public TMessage {
+public:
+  CbmMQTMessage(void* buf, Int_t len) : TMessage(buf, len) { ResetBit(kIsOwner); }
+};
+
+
+#endif /* CBMDEVICEMONITORPSD_H_ */
diff --git a/MQ/monitor/runMonitorPsd.cxx b/MQ/monitor/runMonitorPsd.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..1b304ecf358ea3f47ecd5b1c1761b51db61bf20c
--- /dev/null
+++ b/MQ/monitor/runMonitorPsd.cxx
@@ -0,0 +1,38 @@
+#include "CbmDeviceMonitorPsd.h"
+
+#include <iomanip>
+#include <string>
+
+#include "runFairMQDevice.h"
+
+namespace bpo = boost::program_options;
+using namespace std;
+
+void addCustomOptions(bpo::options_description& options)
+{
+  options.add_options()("IgnOverMs", bpo::value<bool>()->default_value(true), "Ignore overlap MS if true");
+  options.add_options()("MonitorMode", bpo::value<bool>()->default_value(true), "Monitor mode ON/OFF");
+  options.add_options()("MonitorChanMode", bpo::value<bool>()->default_value(false), "Monitor channelwise mode ON/OFF");
+  options.add_options()("MonitorWfmMode", bpo::value<bool>()->default_value(false), "Monitor waveform mode ON/OFF");
+  options.add_options()("MonitorFitMode", bpo::value<bool>()->default_value(false), "Monitor fit waveform mode ON/OFF");
+  options.add_options()("HistEvoSz", bpo::value<uint32_t>()->default_value(1800),
+                        "Size of evolution histos in seconds");
+  options.add_options()("HistChrgArgs", bpo::value<vector<int>>()->multitoken(), "Charge histos arguments");
+  options.add_options()("HistAmplArgs", bpo::value<vector<int>>()->multitoken(), "Ampl histos arguments");
+  options.add_options()("HistZlArgs", bpo::value<vector<int>>()->multitoken(), "ZL histos arguments");
+  options.add_options()("PubFreqTs", bpo::value<uint32_t>()->default_value(100), "Histo publishing frequency in TS");
+  options.add_options()("PubTimeMin", bpo::value<double_t>()->default_value(1.0),
+                        "Minimal time between two publishing");
+  options.add_options()("PubTimeMax", bpo::value<double_t>()->default_value(10.0),
+                        "Maximal time between two publishing");
+  options.add_options()("TsNameIn", bpo::value<std::string>()->default_value("psdcomponent"),
+                        "MQ channel name for TS data");
+  options.add_options()("ChNameIn", bpo::value<std::string>()->default_value("histogram-in"),
+                        "MQ channel name for histos");
+  options.add_options()("ChNameHistCfg", bpo::value<std::string>()->default_value("histo-conf"),
+                        "MQ channel name for histos config");
+  options.add_options()("ChNameCanvCfg", bpo::value<std::string>()->default_value("canvas-conf"),
+                        "MQ channel name for canvases config");
+}
+
+FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) { return new CbmDeviceMonitorPsd(); }
diff --git a/MQ/monitor/startMQSamplerPsdMonitor2021.sh.in b/MQ/monitor/startMQSamplerPsdMonitor2021.sh.in
new file mode 100644
index 0000000000000000000000000000000000000000..02d5551fb0e5e9e069f4b812322172d9d2cecee6
--- /dev/null
+++ b/MQ/monitor/startMQSamplerPsdMonitor2021.sh.in
@@ -0,0 +1,111 @@
+#!/bin/bash
+$SIMPATH/bin/fairmq-shmmonitor --cleanup
+
+if [ $# -ge 1 ]; then
+  _nbmoni=$1
+
+  if [ $# -ge 4 ]; then
+    _filename=""
+    _dirname=""
+    _hostname=$4
+  elif [ $# -ge 2 ]; then
+    _filename=$2
+    _hostname=""
+    if [ $# -eq 3 ]; then
+      _dirname=$3
+    else
+      _dirname=""
+    fi
+  else
+    echo 'Starting connection to local stream'
+    echo ' for other usages, please supply at least a filename.'
+    echo 'Possible usages are:'
+    echo 'startMQSamplerPsdMonitor2021.sh'
+    echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes>'
+    echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> <full filename pattern list>'
+    echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> <filename pattern> <folder_path>'
+    echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> "" "" <hostname(s) list>'
+    _filename=""
+    _dirname=""
+    _hostname="localhost"
+  fi
+else
+  echo 'Starting connection to local stream with 1 monitor process'
+  echo ' for other usages, please supply at least a filename.'
+  echo 'Possible usages are:'
+  echo 'startMQSamplerPsdMonitor2021.sh'
+  echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes>'
+  echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> <full filename pattern list>'
+  echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> <filename pattern> <folder_path>'
+  echo 'startMQSamplerPsdMonitor2021.sh <Nb Monitor processes> "" "" <hostname(s) list>'
+  _filename=""
+  _dirname=""
+  _hostname="localhost"
+  _nbmoni=1
+fi
+
+_paramfile=/mnt/scratch/users/ploizeau/mcbm2020/cbmroot_pal/macro/beamtime/mcbm2020/mPsdPar.par
+##_paramfile=$VMCWORKDIR/macro/beamtime/mcbm2021/mPsdPar.par
+
+SAMPLER="MultiTsaSampler"
+SAMPLER+=" --id sampler1"
+SAMPLER+=" --max-timeslices 0"
+SAMPLER+=" --severity info"
+#SAMPLER+=" --flib-port 10"
+if [ "$_hostname" != "" ]; then
+  SAMPLER+=" --flib-host $_hostname"
+elif [ "$_filename" != "" ]; then
+  SAMPLER+=" --filename $_filename"
+  if [ "$_dirname" != "" ]; then
+    SAMPLER+=" --dirname $_dirname"
+  fi
+fi
+SAMPLER+=" --high-water-mark 1000"
+SAMPLER+=" --send-ts-per-sysid 1"
+SAMPLER+=" --channel-config name=psdcomponent,type=push,method=bind,address=tcp://127.0.0.1:11555"
+SAMPLER+=" --transport shmem"
+#SAMPLER+=" --transport zeromq"
+#SAMPLER+=" --transport nanomsg"
+xterm -l -geometry 80x23+0+0 -hold -e @CMAKE_BINARY_DIR@/bin/MQ/source/$SAMPLER &
+
+_iMoni=0
+((_oubfreqts = $_nbmoni*100 ))
+while (( _iMoni < _nbmoni )); do
+  (( _yOffset=100*_iMoni ))
+  (( _iMoni += 1 ))
+  MONITOR="PsdMonitorMcbm2018"
+
+  MONITOR+=" --id mon$_iMoni"
+  MONITOR+=" --severity info"
+  MONITOR+=" --HistEvoSz 600"
+  MONITOR+=" --HistChrgArgs 500 0 5000"
+  MONITOR+=" --HistAmplArgs 100 0 500"
+  MONITOR+=" --HistZlArgs   100 0 5000"
+  MONITOR+=" --PubFreqTs $_oubfreqts"
+  MONITOR+=" --channel-config name=psdcomponent,type=pull,method=connect,address=tcp://127.0.0.1:11555"
+  MONITOR+=" --transport shmem"
+  #MONITOR+=" --transport zeromq"
+  #MONITOR+=" --transport nanomsg"
+  MONITOR+=" --channel-config name=parameters,type=req,method=connect,transport=zeromq,address=tcp://127.0.0.1:11005,rateLogging=0"
+  MONITOR+=" --channel-config name=histogram-in,type=pub,method=connect,transport=zeromq,address=tcp://127.0.0.1:11666"
+  MONITOR+=" --channel-config name=histo-conf,type=pub,method=connect,transport=zeromq,address=tcp://127.0.0.1:11667"
+  MONITOR+=" --channel-config name=canvas-conf,type=pub,method=connect,transport=zeromq,address=tcp://127.0.0.1:11668"
+  xterm -l -geometry 80x23+500+$_yOffset -hold -e @CMAKE_BINARY_DIR@/bin/MQ/monitor/$MONITOR &
+done
+
+PARAMETERSERVER="parmq-server"
+PARAMETERSERVER+=" --id parmq-server"
+PARAMETERSERVER+=" --severity info"
+PARAMETERSERVER+=" --channel-name parameters"
+PARAMETERSERVER+=" --channel-config name=parameters,type=rep,method=bind,transport=zeromq,address=tcp://127.0.0.1:11005,rateLogging=0"
+PARAMETERSERVER+=" --first-input-name $_paramfile"
+PARAMETERSERVER+=" --first-input-type ASCII"
+PARAMETERSERVER+=" --libs-to-load=libCbmFlibMcbm2018" # doesn't work due to runtime problem
+xterm -geometry 80x23+1000+0 -hold -e @CMAKE_BINARY_DIR@/bin/MQ/parmq/$PARAMETERSERVER &
+
+HISTSERVER="MqHistoServer"
+HISTSERVER+=" --id server1"
+HISTSERVER+=" --channel-config name=histogram-in,type=sub,method=bind,transport=zeromq,address=tcp://127.0.0.1:11666"
+HISTSERVER+=" --channel-config name=histo-conf,type=sub,method=bind,transport=zeromq,address=tcp://127.0.0.1:11667"
+HISTSERVER+=" --channel-config name=canvas-conf,type=sub,method=bind,transport=zeromq,address=tcp://127.0.0.1:11668"
+xterm -geometry 800x230+1500+0 -hold -e @CMAKE_BINARY_DIR@/bin/MQ/histogramServer/$HISTSERVER &
diff --git a/MQ/source/CbmMQTsaMultiSampler.h b/MQ/source/CbmMQTsaMultiSampler.h
index b4e5523a58ba68a34f87589e0dd026a6471285af..2fc353313826fca849ff4242aba350598d05ede1 100644
--- a/MQ/source/CbmMQTsaMultiSampler.h
+++ b/MQ/source/CbmMQTsaMultiSampler.h
@@ -103,17 +103,17 @@ private:
   // TODO: Up to now we have three disconnected vectors which is very
   //       error prone. Find a better solution
 
-  std::vector<std::string> fAllowedChannels = {"stscomponent",  "richcomponent", "trdcomponent",
-                                               "muchcomponent", "tofcomponent",  "t0component"};
-  //    std::vector<int> fSysId = {16, 48, 64, 96, 144, 80};
-  std::vector<int> fSysId = {0x10, 0x30, 0x40, 0x50, 0x60, 0x90};
 
+  std::vector<std::string> fAllowedChannels = {"stscomponent", "richcomponent", "trdcomponent", "muchcomponent",
+                                               "tofcomponent", "t0component",   "psdcomponent"};
+  //    std::vector<int> fSysId = {16, 48, 64, 96, 144, 80};
+  std::vector<int> fSysId = {0x10, 0x30, 0x40, 0x50, 0x60, 0x90, 0x80};
 
-  std::vector<int> fComponentsToSend                    = {0, 0, 0, 0, 0, 0};
-  std::vector<std::vector<std::string>> fChannelsToSend = {{}, {}, {}, {}, {}, {}};
+  std::vector<int> fComponentsToSend                    = {0, 0, 0, 0, 0, 0, 0};
+  std::vector<std::vector<std::string>> fChannelsToSend = {{}, {}, {}, {}, {}, {}, {}};
 
   bool fbListCompPerSysIdReady                       = false;
-  std::vector<std::vector<uint32_t>> fvvCompPerSysId = {{}, {}, {}, {}, {}, {}};
+  std::vector<std::vector<uint32_t>> fvvCompPerSysId = {{}, {}, {}, {}, {}, {}, {}};
 
   bool fbListCompPerChannelReady                       = false;
   std::vector<std::string> fvChannelsToSend            = {};