This is a small centrifugal governor experiment. The centrifugal governor came into widespread use to control the speed of steam engines. The centrifugal forces push apart rotating levers. The spreading angle of the levers is then used to control the speed.

Like with our letter scale project we chose the light sensor to measure the spreading angle. Thus we have a very lightweight, small setup. The governor needs to be on a dark surface so that the light sensor can detect when a bright stick passes by. As the light sensor measures the instantaneous brightness and often measures when there is no stick underneath, the maximum of 100 consecutive measurements is taken.

The control loop increases the motor speed when the light value is below a certain threshold and decreases it when it is above another threshold. The light sensor can be moved to modify the angle at which it detects the rotating sticks.

To visualize the control activity, the program plots the light value (lower line) and the speed setting of the motor (upper line).

The NXT screen figure shows a situation where the light sensor is moved form the outside to the centre. The increased light value causes a reduction of the rotational speed until the system wobbles around the equilibrium value.

NXC Source Code:

 
    
#define RAD OUT_A
#define LICHT IN_1
#define X_MAX 99
#define Y_MAX 63
#define LICHT_GRENZWERT_UNTEN 140
#define LICHT_GRENZWERT_OBEN 150
#define MOTOR_MAX 60
#define LEISTUNG_SCHRITT 1

inline void plotLine(int x, int value)
{
  int yValue=value/10;
  PointOut(x,yValue);
}
inline void plotSpeed(int x)
{
  int yValue=MotorActualSpeed(RAD);
  PointOut(x,yValue);
}
inline int getLicht()
{
  int lichtMax=0;
  int zaehler=0;
  do
  {
    Wait(1);
    zaehler++;
    int lichtJetzt=Sensor(LICHT);
    if (lichtMax<lichtJetzt)
    {
       lichtMax=lichtJetzt;
    }
  } while (zaehler<100);
  return lichtMax;
}
task main ()
{
     int i=0;
     ClearScreen();
     SetSensorType(LICHT,IN_TYPE_LIGHT_ACTIVE);
     SetSensorMode(LICHT,IN_MODE_RAW);
     ResetSensor(LICHT);
     int motorLeistung=0;
     do
     {
         Wait(100);
         i++;
         int licht=getLicht();
         plotLine(i,licht);
         plotSpeed(i);
         if (licht< LICHT_GRENZWERT_UNTEN 
             && motorLeistung < MOTOR_MAX)
         {
           motorLeistung += LEISTUNG_SCHRITT;
           OnFwd(RAD,motorLeistung);
         }
         if (licht> LICHT_GRENZWERT_OBEN 
           && motorLeistung > LEISTUNG_SCHRITT)
         {
           motorLeistung -= LEISTUNG_SCHRITT;
           OnFwd(RAD,motorLeistung);
         }
         if (i==X_MAX)
         {
           i=0;
           ClearScreen();
         }
     } while (true);
}