Regenerative Electric

With Rail3D scripts we can model many different types of locomotive control systems, in this example we are going to model the control system of a modern electric locomotive with regenerative braking.

You can find a demo layout with this loco at http://www.rail3d.info/packages/MetreRackSoundDemo.trp

The prototype

The prototype I’m thinking of is a swiss metre guage rack and adhesion loco with modern drive electronics, however for the pruposes of this article, we’ll ignore the rack, so this script can easily be adjusted for any modern electric loco.


The main control is a combined power/regenerative braking control: it’s turned to the right to apply power, centre is off and turned left for increasing braking effects. At low speed, or if the braking force gets too big, the air brakes are automatically brought into effect by the control systems. There are supplementary controls that directly apply the air brake and the loco parking brake.


The control desk has quite a lot of gauges:

These display amps (three different gauges) voltage (line voltage), speed, and three different pressures from the brake systems. Some of these parameters are built into Rail3D - others we will need to model in our script.

As far as we can deduce, the three current gauges display

  • Auxiliary current to the train (heating, air-con etc)
  • Traction current
  • Current to/from the line in regeneration

See also Controls And Gauges

Setting up the model

We need to set a few things in the model to specify the controls:

	NumControls	1
	Combinedcontrol 0,-100,Combined

This defines one control (on the drive dialog - cab controls are defined elsewhere) and that the control is a combined power/brake control, it has 100 steps and you push it up to apply power.

In practice this loco has a seperate air brake control as well as the main combined control, but we can’t do that with the simple drive dialog, we can model the brake control as well with the 3D cab controls.

The script

this script requires program build 102.3 or later

We’ll try to keep the script generic so it can be used for different loco’s.

First of all, I’m going to add some debug code to the script timer function, so we can see what is going on:

	float speed;
	float TargetSpeed;

	float cPower=Train.GetControl(0);
	float cCombined=Train.GetControl(5);
	float cBrake=Train.GetControl(1);


	debug.print("Speed: ");
	debug.print("Target: ");

	debug.print("Power: ");
	debug.print("Combine: ");
	debug.print("Brake: ");



Now we need to consider the loco dynamics, if I remember the maths correctly:

  • Motor torque is proportional to current
  • Motor back emf is proportional to speed
  • Current is proportional to controller position, but reduced by effect of back emf

I know this loco has a microprocessor control system, but the fundamental physics remains the same.

So, approximatly

    Amps=ControllerPosition.(LineVoltage-BackEMF)/MotorResistance  (ignoring any field weakening effects)

Now there are several unknown factors there (Constants A & B and MotorResistance) but for a reasonable model (and given we are trying to write a generic script) we do have enough information to be able to produce a reasonable script.

Firstly, although we do know the line voltage, for a generic script we can simplify LineVoltage-BackEMF to a percentage value and assume that is ranges from 100% at rest to (say) 25% at maximum speed.

Secondly, we don’t know the value of constant A which relates amps to Force or the motor resistance which gives me the amps. However I do know that for this loco, the maximum traction current is 1150 Amps (this is written on a plate in the cab), but this is not actually required. Since I want to write a generic script, it would be more useful to calculate the current as a percentage of the maximum value - we can then set up the cab gauges appropriatly in each loco where we use the script to display meaningful values.

Also, if I want a generic script, I will need to get values of constants such as maximum speed and maximum tractive effort from the stock definition.

So, my simplifed and generic equations are

    AmpPercent = ControllerPosition * (Vmax - Speed*3/4)/Vmax
    Force = MaxTE * AmpPercent


  • Vmax is the loco’s maximum speed (the factor 3/4 gives me the 25% referred to above)
  • ControllerPosition is 0 to 100%
  • AmpPercent is percentage of maximum amps (0 to 100%)
  • MaxTE is the locos maximum te (from the stock definition)

So, the script function for the traction power is:


	float fMaxSpeed=Train.GetStockMax();
	float Speed=Train.GetSpeed();
	float fMaxTE=Train.GetStockTE();

	float cCombined=Train.GetControl(5);
	float fPower=0;
	float fAmps=0;

		fAmps=(fMaxSpeed-(0.75*Speed))/fMaxSpeed;  // 0 to 1

		fPower=2*(cCombined-50)/100;	// 0 to 1.0

	fAmps=100*fAmps;		//0 to 100

	// Adjust ammeter parameter (with damping)
	float f=Train.GetParam(16);

	// Adjust second ammeter parameter (with damping)

	return fPower;


  • Provided the controller is in the power range, amps and therefore power is calculated accoring to the equations above.
  • The amps (in the range 0 to 100%) is stored in train parameters 16 and 17 - these parameters are reserved for use by scripts and will be used by the locos cab controls to drive the ammeters.


Next we need to code the regenerative braking force.

I don’t have any information to hand about the characteristics of solid-state regenerative braking systems, so we’re going to have to make some approximations:

  • Braking effect is proportional to controller position and speed
  • Since Electrical systems are generally about 90% efficient, the braking force will be about 80% of the traction force for the same current.

So my braking code looks like this:


	float fMaxSpeed=Train.GetStockMax();
	float Speed=Train.GetSpeed();
	float fMaxTE=Train.GetStockTE();

	float cCombined=Train.GetControl(5);
	float fPower=0;
	float fAmps=0;

		fAmps=Speed/fMaxSpeed;  // 0 to 1

		fPower=2*(50-cCombined)/100;	// 0 to 1.0

		fAmps=100*fAmps;		//0 to 100

		// Adjust second ammeter parameter (with damping)
		float f=Train.GetParam(17);

	return fPower;

Note that the braking current is passed to Parameter[17] which is going to be the cab current to/from wire gauge.

Computer driving

Now that we’ve changed the loco characteristics, we also need to supply some code to control the train as the defualt code in the program won’t understand this new control system.

	Train.SetControl(1,0);	// Train air brake

	float TargetSpeed=Train.GetParam(12);
	float Speed=Train.GetSpeed();

	float c=50+50*(TargetSpeed-Speed);


	float d=Train.GetControl(5);


// NB this call may effect power and brake controls as these drive things like the sound system etc
// we need to override (eg) brake if we don't want it to activate

	Train.SetControl(1,0);	// Train air brake

So, we get the target speed and the current speed and compare them. The difference of the two values gives us the position of the controller. As simple as that.

There are a couple of points of fine detail:

  • To stop the controller going from 0 to 100 in one leap we damp the value (4/5 calculation)
  • When we set the combined controller (SetControl(5,d)) this also effects the power and brake controls due to the way Rail3D handles the controls internally. This doesn’t matter as the accleration and brake force are handled by our code (above), but it does mean the cab brake gauges are doing strange things, so we set the brake control to 0 after setting the combined control to hide this effect.