How to use class TPolControl



Introduction

TPolControl is designed to control the Polarized Ion Source via a RS232 serial communication line.
The control device consists of a set of DACs to vary parameters in the ion source as well as a set of ADCs to read back resulting values.

TPolControl is implemented within the ROOT/MARaBOU environment.
It may easily be called interactively from the ROOT interpreter.

This is a short description only - for more details on class definitions and class methods follow the links in the text.

Initialization


   {
	gROOT->Macro("LoadPolarLibs.C");
	TPolControl * pc = new TPolControl("/dev/ttyS1");

	pc->SerIO()->Setup(9600, 7, 0, 1);
	pc->SerIO()->Open();
	pc->SetSubdevs(0, 1, 2, 3, 4);
	pc->ReadNameTable("polNames.dat");

	pc->Print();
	pc->PrintNameTable();
   }


  1.    gROOT->Macro("LoadPolarLibs.C");
    

    Load MARaBOU libraries needed
    (Make sure Unix.*.Root.MacroPath in your .rootrc file contains a path $MARABOU/macros)

  2.    TPolControl * pc = new TPolControl("/dev/ttyS1");
    

    Instantiate class TPolControl
    Returns a pointer (handle) pc to an object of type TPolControl which uses serial port #1 (/dev/ttyS1) for communication

  3.    pc->SerIO()->Setup(9600, 7, 0, 1);
       pc->SerIO()->Open();
    

    Configure and open the serial port
    Opens serial port with 9600 baud, 7 data bits, no parity, 1 stop bit

  4.    pc->SetSubdevs(0, 1, 2, 3, 4);
    

    Activate subdevices
    A subdevice is a hardware box containing 32 ADCs and 20 DACs which may be addressed independently.


  5.    pc->ReadNameTable("polNames.dat");
    

    Read name table
    Allows to address DACs and ADCs via names rather than via channel numbers.
    There a 3 different ways of addressing ADCs and DACs:

    relative pairs of numbers (subdev, channel),
    subdev as given by pc->SetSubdevs(),
    channel=0..31 for ADCs, =0..19 for DACs
    absolute addr is calculated by subdev*32 + channel
    by name addr will be taken from name table,
    table entries are ":"-separated strings of the form name:subdevice:channel:type[:comment]

    Example of a name table file:
    
        # This is a sample name table
        ADC0:4:0:A
        ADC1:4:1:A
        ADC2:4:2:A
        ADC3:4:3:A
        ADC4:4:4:A
        ADC5:4:5:A
        DAC0:4:0:D
    
    


  6.    pc->Print();
       pc->PrintNameTable();
    

    Print settings
    The above init script will give the following output:

    
     Polarized Ion Source Control:
     -----------------------------------------------------------------
     Subdevices             : 0 1 2 3 4
     ADC Channels           : 0:[0..31] 1:[32..63] 2:[64..95] 3:[96..127] 4:[128..159]
     DAC Channels           : 0:[0..19] 1:[32..51] 2:[64..83] 3:[96..115] 4:[128..147]
     Wait states            : 500 ms (AV), 500 ms (AR), 500 ms (SD)
    
     RS232 Settings:
     -----------------------------------------------------------------
     Name                   : tty1
     Port                   : /dev/ttyS1
     State                  : open
     Baud rate              : 9600
     Number of data bits    : 7
     Number of stop bits    : 1
     Parity                 : none
     Terminator #1          : \000
                #2          : \000
     Handshake              : none
     Ignore CR              : yes
     Delay                  : 0 s
     Prefix                 :
     Postfix                : \r
     Bytes received         : 0
     Bytes transmitted      : 0
    
    

    The contents of the name table look like

    
     Name table (7 entries read from file polNames.dat):
     -----------------------------------------------------------------------------------
     Name      Type      AbsChn    Subdev    RelChn
     ...................................................................................
     ADC0      A            128         4         0
     ADC1      A            129         4         1
     ADC2      A            130         4         2
     ADC3      A            131         4         3
     ADC4      A            132         4         4
     ADC5      A            133         4         5
     DAC0      D            128         4         0
    
    

Input/Output


   {
	pc->SetDac(4, 0, 1.5);
	pc->SetDac(128, 1.5);
	pc->SetDac("DAC0", 1.5);

	Int_t adcVal;
	adcVal = pc->ReadAdc(4, 3);
	adcVal = pc->ReadAdc(131);
	adcVal = pc->ReadAdc("ADC3");

	adcVal = pc->SetDac(4, 0, 1.5, 1);
	adcVal = pc->SetDac(128, 1.5, 129);
	adcVal = pc->SetDac("DAC0", 1.5, "ADC1");
   }


  1.    pc->SetDac(4, 0, 1.5);
       pc->SetDac(128, 1.5);
       pc->SetDac("DAC0", 1.5);
    

    Set DAC value
    Sets DAC #0 in subdevice #4 to 1.5 V. Addressing is relative, absolute, or by name, respectively.

  2.    adcVal = pc->ReadAdc(4, 3);
       adcVal = pc->ReadAdc(131);
       adcVal = pc->ReadAdc("ADC3");
    

    Read ADC value
    Returns value of ADC #3 in subdevice #4. Three different addr modes.

  3.    adcVal = pc->SetDac(4, 0, 1.5, 1);
       adcVal = pc->SetDac(128, 1.5, 129);
       adcVal = pc->SetDac("DAC0", 1.5, "ADC1");
    

    Set DAC value and read back result
    Sets DAC #0 in subdevice #4 to 1.5 V. Then reads result from ADC #1.

Plotting ADC vs. DAC


   {
	TH1F * histo;
	histo = pc->Plot("SampleHist", 4, 0, 1, 0.0, 5.0, 0.1, "DAC0", "ADC1");
	histo = pc->Plot("SampleHist", 128, 129, 0.0, 5.0, 0.1, "DAC0", "ADC1");
	histo = pc->Plot("SampleHist", "DAC0", "ADC1", 0.0, 5.0, 0.1);
	histo->Draw();
   }


Plot ADC value as a function of DAC value
Creates a 1-dim histogram named SampleHist,
then varies X values for DAC #0 from 0.0 V to 5.0 V in steps of 0.1 V
and reads back Y results from ADC #1.
DAC0 and ADC1 are titles for X and Y axis, respectively.
histo is a pointer to the resulting histogram, it may be drawn by method TH1::Draw().

Monitoring ADC channels


   {
	TNtuple * ntuple;
	ntuple = pc->Monitor("test.root", "Monitor test", "ADC0:ADC1:ADC2:ADC3", 100, 1);
	ntuple = pc->Monitor("test.root", "Monitor test", "128:129:130:131", 100, 1);
	ntuple = pc->Monitor("test.root", "Monitor test", "4-0:4-1:4-2:4-3", 100, 1);

	pc->PrintMonitorLayout();
   }


Monitor ADC channels
ADCs given in list (addressing by name, absolute, or relative) will be scanned 100 times, scan interval is 1 s.
ADC data are stored together with a timestamp as ROOT ntuples in file test.root.

The monitor layout then looks like


 Monitor layout (file test.root):
 -----------------------------------------------------------------------------------
 Name      Type      AbsChn    Subdev    RelChn
 ...................................................................................
 ADC0      A            128         4         0
 ADC1      A            129         4         1
 ADC2      A            130         4         2
 ADC3      A            131         4         3

Replaying monitor data from file


   {
	TNtuple * ntuple;
	ntuple = pc->Monitor("test.root");

	TArrayF adcData;
        UInt_t timeStamp;

	for (Int_t i = 0; i < pc->GetNofEntries(); i++) {
	   Int_t n = pc->GetEntry(i, timeStamp, adcData);
	   for (Int_t j = 0; j < n; j++) {
	      cout << "ADC #" << j << " has value " << adcData[j] << endl;
           }
        }

	pc->PrintRecords(0, 9);
    }


Play back monitor data from ROOT file
User has to loop over the number of entries in file.
Method TPolControl::GetEntry() then fills local array adcData with ntuple data from entry i.
Variable timeStamp gives the unix time of the current entry.
Method TPolControl::PrintRecords() may be used to output a couple of records to cout.

Download sample script

Click here to download a sample script containing the above (blue coloured) lines.


Author: R. Lutter
Modified: Dez 4 13:33:48 CET 2002