Index: /fact/BIASctrl/BIASctrl.cc
===================================================================
--- /fact/BIASctrl/BIASctrl.cc	(revision 11914)
+++ /fact/BIASctrl/BIASctrl.cc	(revision 11915)
@@ -19,5 +19,5 @@
 
 // Main program
-int main() {
+int main(int argc, char *argv[]) {
 
   char *Command;
@@ -36,5 +36,5 @@
    
   // Construct main instance
-  static User M;
+  static User M(argc == 2 ? argv[1] : string());
   
   // Handle command-line input
Index: /fact/BIASctrl/Crate.cc
===================================================================
--- /fact/BIASctrl/Crate.cc	(revision 11914)
+++ /fact/BIASctrl/Crate.cc	(revision 11915)
@@ -25,5 +25,4 @@
   Name = new char [CrateName.size()+1];
   strcpy(Name, CrateName.c_str());
-  CrateNumber = Number;
   WrapCount = -1;
   LastReset = 0;
@@ -41,5 +40,5 @@
   // Create DIM services
   stringstream ID;
-  ID << setfill('0') << setw(2) << CrateNumber;
+  ID << setfill('0') << setw(2) << Number;
 
   NameService = new DimService ((SERVER_NAME"/NAME/ID"+ID.str()).c_str(), Name);
@@ -51,5 +50,5 @@
   // Open device
   if ((fDescriptor = open(("/dev/"+CrateName).c_str(), O_RDWR|O_NOCTTY|O_NDELAY)) == -1) {
-    if (errno != 2) m->PrintMessage("Error: Could not open device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
+    if (errno != 2) m->PrintMessage("Error: Could not open device %s (%s)\n", Name, strerror(errno));
     return;
   }
@@ -57,5 +56,5 @@
   // Generate FILE pointer
   if ((File = fdopen(fDescriptor, "rb+")) == NULL) {
-    m->PrintMessage("Error: fdopen() failed on device %d/%s (%s)\n", CrateNumber, Name, strerror(errno));
+    m->PrintMessage("Error: fdopen() failed on device %s (%s)\n", Name, strerror(errno));
     return;
   }
@@ -93,5 +92,5 @@
 
   if(fDescriptor != -1) {
-    if (!GlobalSet(0)) m->Message(m->ERROR, "Could not global set crate %d to zero voltage", Name);
+    if (!GlobalSet(0)) m->Message(m->ERROR, "Could not global set crate %s to zero voltage", Name);
 
     if (File == NULL) {
@@ -231,5 +230,5 @@
 	OC[i] = Data[Count] & 128;
 	Present[i] = (Data[Count+2] & 0x70) == 0 ? true : false;
-	if (!ResetHit) ResetHit = (Data[Count+2] & 0x80) == 0 ? false : true;
+	ResetHit |= (Data[Count+2] & 0x80) == 0 ? false : true;
 	Count += 3;
   }
@@ -243,4 +242,5 @@
   // Limit voltage
   Voltage = min(Voltage, atof(m->GetConfig("VoltageLimit").c_str()));
+  Voltage = max(Voltage, 0.0);
 
   // Calculate DAC value
@@ -271,6 +271,7 @@
   // Build and execute commands
   for (map<unsigned int, double>::iterator it = V.begin(); it != V.end(); ++it) {
-    // Limit maximum voltage
+    // Limit voltage
 	it->second = min(it->second, atof(m->GetConfig("VoltageLimit").c_str()));
+	it->second = max(it->second, 0.0);
 
     // If DAC value unchanged, do not send command
Index: /fact/BIASctrl/Crate.h
===================================================================
--- /fact/BIASctrl/Crate.h	(revision 11914)
+++ /fact/BIASctrl/Crate.h	(revision 11915)
@@ -16,5 +16,5 @@
 const unsigned int MAX_NUM_BOARDS = 13;	// Maximum number of boards per crate
 const unsigned int NUM_CHANNELS = 32;	// Channels per bias board
-const float RESISTOR = 1000;			// Resistance in Ohm for voltage correction
+const float RESISTOR = 2000;			// Resistance in Ohm for voltage correction
 const int MAX_ERR_COUNT = 10;	// Maximum number of errors before reporting stopped
 class User;
@@ -23,5 +23,4 @@
   
     class User *m;
-	int CrateNumber;
 	int fDescriptor;
 	FILE *File;
Index: /fact/BIASctrl/History.txt
===================================================================
--- /fact/BIASctrl/History.txt	(revision 11914)
+++ /fact/BIASctrl/History.txt	(revision 11915)
@@ -17,2 +17,5 @@
 5/8/2011	Default voltages now given per bias channel, not per pixel
 15/8/2011	Added global voltage limit and minimum time between system resets.
+24/8/2011	Ramping also for decreasing voltages.
+26/8/2011	Removed support for multiple crates. Crate name can be given as
+			command line argument.
Index: /fact/BIASctrl/User.cc
===================================================================
--- /fact/BIASctrl/User.cc	(revision 11914)
+++ /fact/BIASctrl/User.cc	(revision 11915)
@@ -16,12 +16,11 @@
 								const char *Help;
   } CommandList[] = 
-   {{"pixel", &User::cmd_hv, 2, true, "<range> <voltage|default|info>", "Change bias of pixels (to default)"},
-	{"channel", &User::cmd_hv, 2, true, "<range> <voltage|default|info>", "Change bias of channels of active crate (to default)"},
+   {{"pixel", &User::cmd_hv, 2, true, "<range> <voltage|default|info>", "Change bias of pixels"},
+	{"channel", &User::cmd_hv, 2, true, "<range> <voltage|default|info>", "Change bias of channels of active crate"},
     {"gs", &User::cmd_gs, 1, true, "[crate] <volt>", "Global voltage set active crate"},
 	{"reset", &User::cmd_reset, 0, true, "", "Reset active crate"},
 	{"synch", &User::cmd_synch, 0, true, "", "Synchronize active crate"},
-	{"crate", &User::cmd_crate, 1, true, "<number>", "Select active crate"},
 	{"status", &User::cmd_status, 0, false, "[dac|current]", "Show status information (DAC values if requested)"},
-	{"mode", &User::cmd_mode, 1, false, "<static|dynamic>", "Set voltage stabilization mode (experimental)"},
+	{"mode", &User::cmd_mode, 1, true, "<static|dynamic>", "Set voltage stabilization mode (experimental)"},
 	{"load", &User::cmd_load, 1, true, "<file>", "Load and set bias settings from file"},
 	{"save", &User::cmd_save, 1, true, "<file>", "Save current bias settings to file"},
@@ -33,5 +32,5 @@
 // Constructor
 //
-User::User(): EvidenceServer(SERVER_NAME) {
+User::User(string Board): EvidenceServer(SERVER_NAME) {
 
   MainThread = pthread_self();
@@ -42,5 +41,5 @@
 
   // Get/initialize configuration data
-  vector<string> Boards = Tokenize(GetConfig("Boards", "dummy"), " \t");
+  if (Board.empty()) Board = GetConfig("Boards", "dummy");
   GetConfig("TimeOut");
   GetConfig("VoltageLimit");
@@ -48,5 +47,4 @@
   GetConfig("RampSpeed");
   GetConfig("UpdatePeriod");
-
   vector<string> Text = Tokenize(GetConfig("DefaultVoltage", ""), " \t");
   
@@ -55,19 +53,13 @@
   }
 
-  // Open devices
-  for (unsigned int i=0; i<Boards.size(); i++) {
-  
-    class Crate *New = new class Crate(Boards[i], Crates.size(), this);
-
-    if (New->InitOK) {
-       PrintMessage("Synchronized and reset crate %s (#%d)\n", Boards[i].c_str(), Crates.size());
-       Crates.push_back(New);
-    }
-    else {
-      Message(WARN, "Failed to synchronize crate %s", Boards[i].c_str());
-	  delete New;
-    }
-  }
-  ActiveCrate = 0;
+  // Open device
+  Dev = new class Crate(Board, 0, this);
+
+  if (Dev->InitOK) PrintMessage("Synchronized and reset crate %s\n", Board.c_str());
+  else {
+    Message(WARN, "Failed to synchronize crate %s", Board.c_str());
+	delete Dev;
+	Dev = NULL;
+  }
 
   // Create PixelMap instance (map from config server)
@@ -98,6 +90,6 @@
   if ((Ret = pthread_join(Thread, NULL)) != 0) Message(ERROR, "pthread_join() failed (%s)", strerror(Ret));
 
-  // Delete all crates
-  for (unsigned int i=0; i<Crates.size(); i++) delete Crates[i];
+  // Delete crate
+  delete Dev;
 
   delete DIMCommand;    
@@ -143,6 +135,6 @@
 	  }
 
-	  // Check if crates needed
-	  if (CommandList[CmdNumber].NeedCrate && Crates.empty()) {
+	  // Check if crate needed
+	  if (CommandList[CmdNumber].NeedCrate && Dev==NULL) {
 		PrintMessage("No crate available\n");
 		return;
@@ -172,31 +164,10 @@
 
 //
-// Synchronize boards
+// Synchronize crate
 //
 void User::cmd_synch() {
 
-  if (Crates[ActiveCrate]->Synch()) PrintMessage("Synchronized crate %d\n", ActiveCrate);
-  else PrintMessage("Failed to synchronize crate %d\n", ActiveCrate);
-}
-
-//
-// Select active crate
-//
-void User::cmd_crate() {
-
-  int Crate;
-
-  if (!ConvertToInt(Parameter[1], &Crate)) {
-     PrintMessage("Error: Wrong number format\n");
-     return;   
-  }
-
-  // Check limits
-  if (Crate<0 || Crate>=(int) Crates.size()) {
-    PrintMessage("Crate number %d not existing\n", Crate);
-    return;
-  }
-
-  ActiveCrate = Crate;
+  if (Dev->Synch()) PrintMessage("Synchronized crate\n");
+  else PrintMessage("Failed to synchronize crate\n");
 }
 
@@ -206,10 +177,9 @@
 void User::cmd_hv() {
 
-  unsigned int Errors=0;
+  unsigned int Channel, Errors = 0;
   double Double;
   struct Range Chan, Pixel;
-  unsigned int Crate, Channel;
-  vector< map<unsigned int, double> > Voltages (Crates.size());
-  vector < pair <unsigned int, unsigned int> > P;
+  map<unsigned int, double> Voltages;
+  vector<unsigned int> Channels;
 
   // Loop over all parameters
@@ -223,5 +193,5 @@
 
 	// Extract affected channels for this argument pair
-	P.clear();
+	Channels.clear();
 
 	// Pixel identification?
@@ -236,10 +206,9 @@
 	  
 	  for (int i=Pixel.Min; i<=Pixel.Max; i++) {
-	    Crate = PixMap->Pixel_to_HVcrate(i);
 		Channel = PixMap->Pixel_to_HVboard(i)*NUM_CHANNELS + PixMap->Pixel_to_HVchannel(i);
 		
 		// Skip if pixel ID or corresponding channels not existing 
-		if (Crate!=PixMap->PM_ERROR_CODE && Crate<Crates.size() && Channel<MAX_NUM_BOARDS*NUM_CHANNELS) {
-		  P.push_back(make_pair(Crate, Channel));
+		if (PixMap->Pixel_to_HVcrate(i) == 0 && Channel<MAX_NUM_BOARDS*NUM_CHANNELS) {
+		  Channels.push_back(Channel);
 		}
 	  }
@@ -255,20 +224,19 @@
 	  }
 	  
-	  for (int i=Chan.Min; i<=Chan.Max; i++) P.push_back(make_pair(ActiveCrate, i));	  
+	  for (int i=Chan.Min; i<=Chan.Max; i++) Channels.push_back(i);	  
 	}
   
 	// Loop over all given channels
-	for (unsigned int i=0; i<P.size(); i++) {
-	  Crate = P[i].first;
-	  Channel = P[i].second;
+	for (unsigned int i=0; i<Channels.size(); i++) {
+	  Channel = Channels[i];
 
 	  // Should only information be printed?
 	  if (Match(Parameter[n+1], "info")) {
-		PrintMessage("Crate %2d, channel %3d  ", Crate, Channel);
-		if (!Crates[Crate]->Present[Channel]) PrintMessage("(channel not present in crate)");
-		PrintMessage("\n  Channel is on board %d, board channel %d\n", Channel/32, Channel%32);
+		PrintMessage("Channel %d ", Channel);
+		if (!Dev->Present[Channel]) PrintMessage(" is not present in crate\n");
+		else PrintMessage("is on board %d, board channel %d\n", Channel/32, Channel%32);
 
 		// Print pixel information
-		vector<unsigned int> List = PixMap->HV_to_Pixel(Crate, Channel/NUM_CHANNELS, Channel%NUM_CHANNELS);
+		vector<unsigned int> List = PixMap->HV_to_Pixel(0, Channel/NUM_CHANNELS, Channel%NUM_CHANNELS);
 		PrintMessage("\n  Default voltage: %.2f    Pixel IDs: ", Channel < DefaultVoltage.size() ? DefaultVoltage[Channel] : 0);
 		for (unsigned int j=0; j<List.size(); j++) PrintMessage("%u ", List[j]);
@@ -276,7 +244,7 @@
 
 		// Print voltage and current
-		PrintMessage("\n  Voltage setpoint: %.2f V (DAC %u)    Current: %.2f uA ", Crates[Crate]->GetVoltage(Channel), Crates[Crate]->GetDAC(Channel), Crates[Crate]->GetCurrent(Channel));
-
-		if (Crates[Crate]->OC[Channel]) PrintMessage("(overcurrent)\n");
+		PrintMessage("\n  Voltage setpoint: %.2f V (DAC %u)    Current: %.2f uA ", Dev->GetVoltage(Channel), Dev->GetDAC(Channel), Dev->GetCurrent(Channel));
+
+		if (Dev->OC[Channel]) PrintMessage("(overcurrent)\n");
 		else PrintMessage("\n");
 
@@ -284,11 +252,9 @@
 	  }
 
-	  // Check that indices are in legal range (safety check, should be unnecessary)
-	  if (Crate >= Crates.size() || Channel >=MAX_NUM_BOARDS*NUM_CHANNELS) continue;
- 
-	  // Voltage change (number starts with + oder -) ignored if current DAC value is zero
-	  if (Parameter[n+1][0]=='+' || Parameter[n+1][0]=='-') {
-		if (Crates[Crate]->GetDAC(Channel) == 0) continue;
-	  }
+	  // Get current voltage on first change of a channel
+	  if (Voltages.count(Channel) == 0) Voltages[Channel] = Dev->GetVoltage(Channel);
+
+	  // Voltage change (number starts with + oder -) ignored if voltage is zero
+	  if (Parameter[n+1][0]=='+' || Parameter[n+1][0]=='-') if (Voltages[Channel] == 0) continue;
 	
 	  // Should the default value be set?
@@ -297,22 +263,18 @@
 		else Double = 0;
 	  }
-
+	  
 	  // Relative or absolute change?
-	  if (isdigit(Parameter[n+1][0]) == 0) Voltages[Crate][Channel] = Crates[Crate]->GetVoltage(Channel) + Double;
-	  else Voltages[Crate][Channel] = Double;
+	  if (Parameter[n+1][0]=='+' || Parameter[n+1][0]=='-') Voltages[Channel] += Double;
+	  else Voltages[Channel] = Double;
 	} // Channels
   } // Loop over command argument
 
   // Ramp voltages and update DIM services
-  for (unsigned int i=0; i<Voltages.size(); i++) {
-	Errors += RampVoltages(i, Voltages[i]);
-    Crates[i]->UpdateDIM();
-  }
+  Errors += RampVoltages(Voltages);
+  Dev->UpdateDIM();
 
   // Error message only if not yet too many errors
   if (Errors > 0) {
-	for (unsigned int i=0; i<Crates.size(); i++) {
-	  if (Crates[i]->ErrorCount > MAX_ERR_COUNT) return;
-	}
+	if (Dev->ErrorCount > MAX_ERR_COUNT) return;
     Message(ERROR, "%d errors occurred from SetChannels()", Errors);
   }
@@ -338,29 +300,25 @@
 
   // Scan through file line by line
-  while (fgets(Buffer, sizeof(Buffer), File) != NULL) {
-    for (unsigned int Crate=0; Crate<Crates.size(); Crate++) if (Match(Crates[Crate]->Name, Buffer)) {
-
-	  if (Crate != ActiveCrate) continue;
-	  PrintMessage("Found bias settings for crate %s (#%d)\n\r", Crates[Crate]->Name, Crate);
-
-	  Voltages.clear();
-	  Channel = 0;
-	  while (fscanf(File, "%lf", &Value)==1 && Channel<MAX_NUM_BOARDS*NUM_CHANNELS) {
-		Voltages[Channel++] = Value;
-	  }
-
-	  // Ramp channels
-	  Errors += RampVoltages(Crate, Voltages);
-
-      // Update DIM service
-	  Crates[Crate]->UpdateDIM();
-
-	  if (ferror(File) != 0) {
-		PrintMessage("Error reading DAC value from file, terminating. (%s)\n",strerror(errno));
-    	return;
-	  }
-	  else PrintMessage("\nFinished updating board\n");
-    } // Loop over boards
-  } // while()
+  while (fgets(Buffer, sizeof(Buffer), File) != NULL) if (Match(Dev->Name, Buffer)) {
+	PrintMessage("Found bias settings for crate %s\n\r", Dev->Name);
+
+	Voltages.clear();
+	Channel = 0;
+	while (fscanf(File, "%lf", &Value)==1 && Channel<MAX_NUM_BOARDS*NUM_CHANNELS) {
+	  Voltages[Channel++] = Value;
+	}
+
+	// Ramp channels
+	Errors += RampVoltages(Voltages);
+
+    // Update DIM service
+	Dev->UpdateDIM();
+
+	if (ferror(File) != 0) {
+	  PrintMessage("Error reading DAC value from file, terminating. (%s)\n",strerror(errno));
+      return;
+	}
+	else PrintMessage("\nFinished updating board\n");
+  } // if()
     	    
   if (Errors != 0) PrintMessage("Warning: %d error(s) occurred\n", Errors);
@@ -369,10 +327,10 @@
 	     
 //
-// Reset crates
+// Reset crate
 //
 void User::cmd_reset() {
 
-  if (Crates[ActiveCrate]->SystemReset()) PrintMessage("System reset of crate %d\n", ActiveCrate);
-  else PrintMessage("Error: Could not reset crate %d\n", ActiveCrate);
+  if (Dev->SystemReset()) PrintMessage("System reset of crate\n");
+  else PrintMessage("Error: Could not reset crate\n");
 }
 
@@ -389,6 +347,6 @@
   }
   
-  if (!Crates[ActiveCrate]->GlobalSet(Voltage)) {
-	PrintMessage("Error: Could not global set crate %d\n", ActiveCrate);
+  if (!Dev->GlobalSet(Voltage)) {
+	PrintMessage("Error: Could not global set crate\n");
   }  
 }
@@ -408,11 +366,8 @@
 
   fprintf(File,"********** Bias settings of %s **********\n\n", ctime(&Time));
-
-  for (unsigned int i=0; i<Crates.size(); i++) {
-    fprintf(File, "%s\n\n", Crates[i]->Name);
-
-    for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) fprintf(File,"%.3f ",Crates[i]->GetVoltage(j));
-    fprintf(File, "\n");
-  }
+  fprintf(File, "%s\n\n", Dev->Name);
+
+  for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) fprintf(File,"%.3f ", Dev->GetVoltage(j));
+  fprintf(File, "\n");
 
   if (fclose(File) != 0) {
@@ -429,7 +384,5 @@
   else {
     Mode = mode_dynamic;
-	for (unsigned int i=0; i<Crates.size(); i++) {
-	  Crates[i]->SetRefCurrent();
-	}
+	Dev->SetRefCurrent();
   }
 } 
@@ -440,37 +393,39 @@
 void User::cmd_status() {
 
-  PrintMessage(" Number of crates:   %d\n", Crates.size());
-  PrintMessage(" Active crate:       %d\n", ActiveCrate);  
-  PrintMessage(" Update delay:       %d sec\n", min(atoi(GetConfig("UpdatePeriod").c_str()), 1));
-  PrintMessage(" Time out:           %.2f sec\n", atof(GetConfig("TimeOut").c_str()));
-  PrintMessage(" Max ramp speed      %.2f V/10 ms\n", atof(GetConfig("RampSpeed").c_str()));
-  PrintMessage(" Voltage limit:      %.2f V\n", atof(GetConfig("VoltageLimit").c_str()));
-  PrintMessage(" Minium reset delay: %u sec\n", atoi(GetConfig("MinResetPeriod").c_str()));
-  
-  for (unsigned int i=0; i<Crates.size(); i++) {
-
-    PrintMessage(" CRATE %d (%s)\n   Wrap counter: %s (%d)  Reset: %s  Error count: %d %s\n ",
-		i, Crates[i]->Name,	Crates[i]->WrapOK ? "ok":"error", Crates[i]->WrapCount, 
-		Crates[i]->ResetHit ? "yes" : "no", Crates[i]->ErrorCount, Crates[i]->Disabled ? "(DISABLED)":"");
-
-	// Read all channels
-	if (!Crates[i]->ReadAll()) {
-	  PrintMessage("Could not update status from crate %d\n", i);
-	  continue;
-	}
-
-	if (Parameter.size() == 1) PrintMessage("Channel voltages (in V)");
-    else if (Match(Parameter[1], "dac")) PrintMessage("Channel voltages (in DAC values)");
-	else PrintMessage("Channel currents (in uA)");
-
-    for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) {
-	  if (j%12 == 0) PrintMessage("\n%3.1d:  ", j);
-	  if (!Crates[i]->Present[j]) PrintMessage("  -   ");
-      else if (Parameter.size() == 1) PrintMessage("%#5.2f ",Crates[i]->GetVoltage(j));
-	  else if (Match(Parameter[1], "dac")) PrintMessage("%5d ", Crates[i]->GetDAC(j));
-	  else PrintMessage("%#5.2f %s ", Crates[i]->GetCurrent(j), Crates[i]->OC[j] ? "OC":"");
-    }
-	PrintMessage("\n");
-  }
+  // Overview information
+  PrintMessage("Update delay:   %2d sec    Time out:    %.2f sec    Minium reset delay:   %u sec\n",
+	min(atoi(GetConfig("UpdatePeriod").c_str()), 1), atof(GetConfig("TimeOut").c_str()),
+	atoi(GetConfig("MinResetPeriod").c_str()));
+  PrintMessage("Voltage limit:   %.2f V  Ramp speed:  %.2f V/10 ms\n",
+	atof(GetConfig("VoltageLimit").c_str()), atof(GetConfig("RampSpeed").c_str()));
+  
+  if (Dev == NULL) return;
+
+  // Details
+  PrintMessage("\nCRATE %s   Wrap counter: %s (%d)  Reset: %s  Error count: %d %s\n ",
+	  Dev->Name, Dev->WrapOK ? "ok":"error", Dev->WrapCount, 
+	  Dev->ResetHit ? "yes" : "no", Dev->ErrorCount, Dev->Disabled ? "(DISABLED)":"");
+
+  // Read all channels
+  if (!Dev->ReadAll()) {
+	PrintMessage("Could not update status, ReadAll() failed\n");
+	return;
+  }
+
+  // Voltage or current list
+  if (Parameter.size() == 1) PrintMessage("Channel voltages (in V)");
+  else if (Match(Parameter[1], "dac")) PrintMessage("Channel voltages (in DAC values)");
+  else PrintMessage("Channel currents (in uA)");
+
+  for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) {
+	if (j%12 == 0) PrintMessage("\n%3.1d:  ", j);
+	if (!Dev->Present[j]) PrintMessage("  -   ");
+    else if (Parameter.size() == 1) PrintMessage("%#5.2f", Dev->GetVoltage(j));
+	else if (Match(Parameter[1], "dac")) PrintMessage("%5d", Dev->GetDAC(j));
+	else PrintMessage("%#5.2f", Dev->GetCurrent(j));
+	// Print overcurrent marker
+	PrintMessage("%s ", Dev->OC[j] ? "*":" ");
+  }
+  PrintMessage("\n");
 } 
 
@@ -523,28 +478,35 @@
 
 // Ramp to new voltage with given maximum step
-// No ramping when decreasing voltage
-unsigned int User::RampVoltages(int Crate, map<unsigned int, double> Voltages) {
+unsigned int User::RampVoltages(map<unsigned int, double> Voltages) {
 
   map<unsigned int, double> Target;
   int Errors = 0;
-  double MaxDiff = atof(GetConfig("RampSpeed").c_str());
-
-  // Ramp until all channels at desired value
+  double V, Lim, MaxDiff = atof(GetConfig("RampSpeed").c_str());
+
   while (!Voltages.empty() && Errors < MAX_ERR_COUNT) {
-    // Remove channels already at target (check for DAC, not for floating-point voltage)
-	for (map<unsigned int, double>::iterator it = Voltages.begin(); it != Voltages.end(); ++it) {
-	  if (fabs(Crates[Crate]->GetVoltage(it->first)-it->second) < 0.001) Voltages.erase(it);
+	// Voltage limit evaluate here in case of asynchronous update in config file
+    Lim = atof(GetConfig("VoltageLimit").c_str());
+
+	// Remove channels already at target or at voltage limit
+	for (map<unsigned int, double>::iterator it = Voltages.begin(); it != Voltages.end(); ++it) {	
+	  // Channel at target?
+	  if (fabs(Dev->GetVoltage(it->first)-it->second) < 0.001) Voltages.erase(it);
+	  // Channel at voltage limit?
+	  if (it->second > Lim && Dev->GetVoltage(it->first) == Lim) Voltages.erase(it);
+	  if (it->second < 0 && Dev->GetVoltage(it->first) == 0) Voltages.erase(it);
 	}
 	
-	// Limit voltage changes to fMaxDiff
+	// Limit voltage changes to MaxDiff
 	Target = Voltages;
 	for (map<unsigned int, double>::iterator it = Target.begin(); it != Target.end(); ++it) {
-	  if (Crates[Crate]->GetVoltage(it->first) + MaxDiff < it->second) {
-		it->second = Crates[Crate]->GetVoltage(it->first) + MaxDiff;
-	  }
+	  V = Dev->GetVoltage(it->first);
+	  // Ramp up
+	  if ((V < it->second) && (V + MaxDiff < it->second)) it->second = V + MaxDiff;
+	  // Ramp down
+	  if ((V > it->second) && (V - MaxDiff > it->second)) it->second = V - MaxDiff;
 	}	
 	
 	// Set channels to next target and wait 10 ms
-	if (!Crates[Crate]->SetChannels(Target)) Errors++;
+	if (!Dev->SetChannels(Target)) Errors++;
 	usleep(10000);
   }
@@ -561,6 +523,8 @@
   int Ret;
 
+  // End if no crate available
+  if (Dev == NULL) return;
+
   while (!ExitRequest) {
-
   	// Wait (this is the only allowed cancelation point)
 	if ((Ret=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL)) != 0) {
@@ -572,35 +536,30 @@
 	}
 
-	// Check all crates
-	for (unsigned int i=0; i<Crates.size(); i++) {
-	  // Crate disabled because of too many errors?
-      if (Crates[i]->Disabled) continue;
-
-	  // Read all channels
-      if (!Crates[i]->ReadAll()) {
-    	Message(ERROR, "Monitor thread could not read status from crate %d", i);
-		continue;
-      }
-
-	  // Check if crate push button was hit
-      if (Crates[i]->ResetHit) {
-    	Message(INFO, "Manual reset of crate %d, setting voltages to zero and issuing system reset", i);
-		if (!Crates[i]->GlobalSet(0)) Message(ERROR, "Global set to zero voltage of crate %d failed", i);
-		if (!Crates[i]->SystemReset()) Message(ERROR, "System reset of crate %d failed", i);
-      }
-
-	  // Check for overcurrent and set voltage to zero if occurred
-	  map<unsigned int, double> Voltages;
-	  
-      for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) {
-    	if (Crates[i]->OC[j]) {
-		  Message(WARN, "Overcurrent on crate %d, board %d, channel %d, setting voltage to zero", i, j/NUM_CHANNELS, j%NUM_CHANNELS);
-		  Voltages[j] = 0;
-    	}
-      }
-	  if (!Crates[i]->SetChannels(Voltages)) Message(ERROR, "Error when setting voltages of crate %d", i);
-	  
-	  if (Mode == mode_dynamic) Crates[i]->AdaptVoltages();
-	} // for
+	// Check crate
+    if (Dev->Disabled) continue;
+
+	// Read all channels
+    if (!Dev->ReadAll()) {
+      Message(ERROR, "Monitor thread could not read status, ReadAll() failed\n");
+	  continue;
+    }
+
+	// Check if crate push button was hit
+    if (Dev->ResetHit) {
+      Message(INFO, "Manual reset of crate, setting voltages to zero and issuing system reset");
+	  if (!Dev->GlobalSet(0)) Message(ERROR, "Global set to zero voltage of crate failed");
+	  if (!Dev->SystemReset()) Message(ERROR, "System reset of crate failed");
+    }
+
+	// Check for overcurrent and set voltage to zero if occurred
+	map<unsigned int, double> Voltages;
+
+    for (unsigned int j=0; j<MAX_NUM_BOARDS*NUM_CHANNELS; j++) if (Dev->OC[j]) Voltages[j] = 0;
+	if (!Voltages.empty()) {
+	  if (!Dev->SetChannels(Voltages)) Message(ERROR, "Error setting voltage to zero for channels with overcurrent");
+	  Dev->UpdateDIM();
+	}
+
+	if (Mode == mode_dynamic) Dev->AdaptVoltages();
   } // while
 }
Index: /fact/BIASctrl/User.h
===================================================================
--- /fact/BIASctrl/User.h	(revision 11914)
+++ /fact/BIASctrl/User.h	(revision 11915)
@@ -31,5 +31,5 @@
 	RunMode Mode;
 
-	std::vector<class Crate *> Crates;
+	class Crate *Dev;
 	std::vector<double> DefaultVoltage;
 
@@ -47,11 +47,9 @@
 
  public:
-	unsigned int ActiveCrate;
-
-	User();
+	User(std::string);
 	~User();
 
 	void PrintMessage(const char *, ...);
-	unsigned int RampVoltages(int, std::map<unsigned int, double>);
+	unsigned int RampVoltages(std::map<unsigned int, double>);
 	void Monitor();
 	static void LaunchMonitor(User *);
@@ -62,5 +60,5 @@
 	void cmd_exit();	void cmd_reset();
 	void cmd_help();	void cmd_mode();
-	void cmd_crate();	void cmd_shell();
+	void cmd_shell();
 };
 
