Esempio n. 1
0
        /// <summary>
        /// Runs the sample.
        /// </summary>
        /// <param name="lamp">The lamp, as an analog output.</param>
        public static void Run(ISingleOutput lamp)
        {
            // Check parameters:
            if (lamp == null)
            {
                throw new ArgumentNullException(nameof(lamp));
            }

            // Smoothly blink the output:

            const int Steps     = 10;
            const int PauseInMs = 50;

            while (true)
            {
                for (int step = 0; step < Steps; step++)
                {
                    lamp.Value = (float)step / (float)Steps;
                    Thread.Sleep(PauseInMs);
                }
                for (int step = Steps; step > 0; step--)
                {
                    lamp.Value = (float)step / (float)Steps;
                    Thread.Sleep(PauseInMs);
                }
            }
        }
Esempio n. 2
0
 /// <summary>
 /// Creates a <see cref="SingleMappedFromBooleanOutput"/> object mapping the boolean values false/true to two
 /// float values.
 /// </summary>
 /// <param name="targetOutput">The target output receiving the float values.</param>
 /// <param name="falseValue">The value that the <paramref name="targetOutput"/> shall be set to when the
 /// <see cref="IBooleanInput.Value"/> property is false.</param>
 /// <param name="trueValue">The value that the <paramref name="targetOutput"/> shall be set to when the
 /// <see cref="IBooleanInput.Value"/> property is true.</param>
 /// <returns></returns>
 public static SingleMappedFromBooleanOutput MappedFromBoolean(
     this ISingleOutput targetOutput,
     float falseValue,
     float trueValue)
 {
     return(new SingleMappedFromBooleanOutput(targetOutput, falseValue, trueValue));
 }
Esempio n. 3
0
 /// <summary>
 /// Creates a <see cref="SingleSmoothedOutput"/> object which will slowly approach the
 /// <paramref name="targetOutput"/> value to the goal <see cref="ISingleOutput.Value"/>.
 /// </summary>
 /// <param name="targetOutput">The target output to be smoothed.</param>
 /// <param name="valueChangePerSecond">The amount by that the <paramref name="targetOutput"/> value shall change
 /// per second in order to reach the <see cref="Value"/> property which definies the goal value.</param>
 /// <param name="rampIntervalMs">The interval, in milliseconds, in which the <paramref name="targetOutput"/>
 /// value shall be computed and set. The smaller this value, the more often and more smoothly will the target
 /// value be adapted.</param>
 /// <returns>The created <see cref="SingleSmoothedOutput"/> object.</returns>
 public static SingleSmoothedOutput Smoothed(
     this ISingleOutput targetOutput,
     float valueChangePerSecond,
     int rampIntervalMs)
 {
     return(new SingleSmoothedOutput(targetOutput, valueChangePerSecond, rampIntervalMs));
 }
Esempio n. 4
0
 /// <summary>
 /// Creates a <see cref="SingleScaledOutput"/> object which will scale values linear using a factor and an
 /// offset.
 /// </summary>
 /// <param name="targetOutput">The target output to received the scaled values.</param>
 /// <param name="quadraticCoefficient">The factor by which the square of the value will be used.</param>
 /// <param name="factor">The factor to use.</param>
 /// <param name="offset">The offset to use.</param>
 /// <returns>The created <see cref="SingleScaledOutput"/> object.</returns>
 /// <remarks>The <paramref name="targetOutput"/> will receive values scaled by the formula:
 /// <see cref="ISingleOutput.Value">Value</see> * <paramref name="factor"/> + <paramref name="offset"/>.
 /// </remarks>
 public static SingleScaledOutput Scaled(
     this ISingleOutput targetOutput,
     float quadraticCoefficient,
     float factor,
     float offset)
 {
     return(new SingleScaledOutput(targetOutput, quadraticCoefficient, factor, offset));
 }
 /// <summary>
 /// Creates an instance given a factor only, using 0.0 as the offset.
 /// </summary>
 /// <param name="target">The target output which shall receive the scaled values.</param>
 /// <param name="factor">The factor to scale the output.</param>
 /// <remarks>Setting the <see cref="Value"/> will set the <paramref name="target"/> value to
 /// <see cref="Value"/> * <paramref name="factor"/>.</remarks>
 public SingleScaledOutput(ISingleOutput target, float factor)
 {
     if (target == null)
     {
         throw new ArgumentNullException(nameof(target));
     }
     _target = target;
     _factor = factor;
 }
Esempio n. 6
0
 /// <summary>
 /// Creates an instance.
 /// </summary>
 /// <param name="targetOutput">The target output receiving the float values.</param>
 /// <param name="falseValue">The value that the <paramref name="targetOutput"/> shall be set to when the
 /// <see cref="IBooleanInput.Value"/> property is false.</param>
 /// <param name="trueValue">The value that the <paramref name="targetOutput"/> shall be set to when the
 /// <see cref="IBooleanInput.Value"/> property is true.</param>
 public SingleMappedFromBooleanOutput(ISingleOutput targetOutput, float falseValue, float trueValue)
 {
     if (targetOutput == null)
     {
         throw new ArgumentNullException(nameof(targetOutput));
     }
     _targetOutput       = targetOutput;
     _falseValue         = falseValue;
     _trueValue          = trueValue;
     _targetOutput.Value = falseValue;
 }
Esempio n. 7
0
        /// <summary>
        /// Creates an instance given a quadratic and linear factor and an offset (y = ax² + bx + c).
        /// </summary>
        /// <param name="target">The target output which shall receive the scaled values.</param>
        /// <param name="quadraticCoefficient">The factor by which the square of the value will be used.</param>
        /// <param name="factor">The factor to scale the output.</param>
        /// <param name="offset">The offset to add to the output.</param>
        /// <remarks>Setting the <see cref="Value"/> will set the <paramref name="target"/> value to
        /// <see cref="Value"/> * <paramref name="factor"/> + <paramref name="offset"/>.</remarks>
        public SingleScaledOutput(ISingleOutput target, float quadraticCoefficient, float factor, float offset)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }

            _target = target;
            _quadraticCoefficient = quadraticCoefficient;
            _factor = factor;
            _offset = offset;
        }
        /// <summary>
        /// Creates an instance.
        /// </summary>
        /// <param name="targetOutput">The target output to be smoothed.</param>
        /// <param name="valueChangePerSecond">The amount by that the <paramref name="targetOutput"/> value shall change
        /// per second in order to reach the <see cref="Value"/> property which definies the goal value.</param>
        /// <param name="rampIntervalMs">The interval, in milliseconds, in which the <paramref name="targetOutput"/>
        /// value shall be computed and set. The smaller this value, the more often and more smoothly will the target
        /// value be adapted.</param>
        public SingleSmoothedOutput(ISingleOutput targetOutput, float valueChangePerSecond, int rampIntervalMs)
        {
            _targetOutput = targetOutput ?? throw new ArgumentNullException(nameof(targetOutput));
            if (valueChangePerSecond <= 0.0f)
            {
                throw new ArgumentOutOfRangeException(nameof(valueChangePerSecond));
            }
            if (rampIntervalMs <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rampIntervalMs));
            }

            _valueChangePerTick = valueChangePerSecond / TimeSpan.TicksPerSecond;
            _rampIntervalMs     = rampIntervalMs;
        }
        public static void Run(ISingleInput input, ISingleOutput lamp)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }
            if (lamp == null)
            {
                throw new ArgumentNullException(nameof(lamp));
            }

            while (true)
            {
                lamp.Value = input.Value;
                Thread.Sleep(100); // Only to give you a chance to redeploy usung firmware as of 2018-04-08.
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="StepperMotor"/> class.
        /// </summary>
        /// <param name="phase1Output">The H-Bridge that controls motor phase 1.</param>
        /// <param name="phase2Output">The H-Bridge that controls motor phase 2.</param>
        /// <param name="stepsPerStepCycle">The steps per step cycle.</param>
        public StepperMotor(
            ISingleOutput phase1Output,
            ISingleOutput phase2Output,
            int stepsPerStepCycle)
        {
            if (phase1Output == null)
            {
                throw new ArgumentNullException(nameof(phase1Output));
            }
            if (phase2Output == null)
            {
                throw new ArgumentNullException(nameof(phase2Output));
            }
            if (phase1Output == phase2Output)
            {
                throw new ArgumentException("Use different phaseOutputs.");
            }

            _phase1Output = phase1Output;
            _phase2Output = phase2Output;
            _maxIndex     = stepsPerStepCycle - 1;
            _phaseIndex   = 0;

            // Configure step tables:
            if (stepsPerStepCycle == 4)
            {
                ComputeWholeStepTables();
            }
            else if (stepsPerStepCycle == 8)
            {
                ComputeHalfStepTables();
            }
            else if (stepsPerStepCycle >= 8)
            {
                ComputeMicrostepTables(stepsPerStepCycle);
            }
            else
            {
                throw new ArgumentException(
                          "Use 4 for full steps; 8 for half steps; or >8 for stepsPerStepCycle", nameof(stepsPerStepCycle));
            }
        }
Esempio n. 11
0
 public void SetConnection(ISingleOutput input)
 {
     Input = input;
 }
Esempio n. 12
0
 public void Connect(ISingleOutput dendrite)
 {
     _dendrites.Add(dendrite);
 }
Esempio n. 13
0
 /// <summary>
 /// Creates a <see cref="SingleScaledOutput"/> object which will scale values linear using a factor only and
 /// 0.0 as the offset.
 /// </summary>
 /// <param name="targetOutput">The target output to received the scaled values.</param>
 /// <param name="factor">The factor to use.</param>
 /// <returns>The created <see cref="SingleScaledOutput"/> object.</returns>
 /// <remarks>The <paramref name="targetOutput"/> will receive values scaled by the formula:
 /// <see cref="ISingleOutput.Value">Value</see> * <paramref name="factor"/>.</remarks>
 public static SingleScaledOutput Scaled(this ISingleOutput targetOutput, float factor)
 {
     return(new SingleScaledOutput(targetOutput, factor));
 }
        /// <summary>
        /// Runs a "Turmbergbahn" train, that is, 2 trains hanging on a single steel wire driven by a motor, running on
        /// the same rails using a "Abt'sche Weiche".
        /// </summary>
        /// <param name="trainMotor">The motor driving both trains at once. +1.0 is output for the direction so that
        /// train 1 drives upwards and train 2 drives downwards, -1.0 vice versa.</param>
        /// <param name="train1ReachedBottomStation">Signals true when train 1 reached the bottom station (and thus
        /// train 2 reached the top station).</param>
        /// <param name="train2ReachedBottomStation">Signals true when train 2 reached the bottom station (and thus
        /// train 1 reached the top station).</param>
        /// <param name="doorMotor">The motor driving all doors on both trains at once. +1.0 is output for opening,
        /// -1.0 for closing.</param>
        /// <param name="redLight">True shall light up a red traffic light when people shall not enter or leave the
        /// train.</param>
        /// <param name="greenLight">True shall light up a green traffic light when people may enter or leave the
        /// train.</param>
        /// <param name="waitForDoorsToMoveInMs">The time, in milliseconds, to wait for the
        /// <paramref name="doorMotor"/> to have operated all doors reliably.</param>
        /// <param name="waitWithOpenDoorsInMs">The time, in milliseconds, that the doors shall remain open.</param>
        /// <param name="waitAroundDoorOperationsInMs">The time, in milliseconds, to wait after the train stopped and
        /// before opening the door, and after the doors were closed again before the train starts.</param>
        public static void Run(ISingleOutput trainMotor,
                               IBooleanInput trainReachedBottomStation,
                               ISingleOutput doorMotor,
                               int waitForDoorsToMoveInMs,
                               int waitWithOpenDoorsInMs,
                               int waitAroundDoorOperationsInMs)
        {
            // Check arguments:

            if (trainMotor == null)
            {
                throw new ArgumentNullException(nameof(trainMotor));
            }
            if (trainReachedBottomStation == null)
            {
                throw new ArgumentNullException(nameof(trainReachedBottomStation));
            }
            if (doorMotor == null)
            {
                throw new ArgumentNullException(nameof(doorMotor));
            }
            if (waitForDoorsToMoveInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitForDoorsToMoveInMs));
            }
            if (waitWithOpenDoorsInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitWithOpenDoorsInMs));
            }
            if (waitAroundDoorOperationsInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitAroundDoorOperationsInMs));
            }

            // Run the train:

            float moveDirection = 1.0f;

            while (true)
            {
                // Move the train in the current direction until one of the end buttons is pressed:
                if (!trainReachedBottomStation.Value)
                {
                    trainMotor.Value = moveDirection;
                    trainReachedBottomStation.WaitFor(value: true, edgeOnly: false);
                    trainMotor.Value = 0.0f;
                }

                // Change direction for the next pass:
                moveDirection = -moveDirection;

                // Wait a bit before opening the doors:
                Thread.Sleep(waitAroundDoorOperationsInMs);

                // Open the door:
                doorMotor.Value = 1.0f;
                Thread.Sleep(waitForDoorsToMoveInMs);
                doorMotor.Value = 0.0f;

                // Let people step in and out, wait a bit:
                Thread.Sleep(waitWithOpenDoorsInMs);

                // Close the door:
                doorMotor.Value = -1.0f;
                Thread.Sleep(waitForDoorsToMoveInMs);
                doorMotor.Value = 0.0f;

                // Wait a bit before the train starts again:
                Thread.Sleep(waitAroundDoorOperationsInMs);
            }
        }
Esempio n. 15
0
 public void Connect(ISingleOutput dendrite)
 {
     _dendrites.Add(dendrite);
 }
Esempio n. 16
0
        /// <summary>
        /// Runs a clock driven by a simple DC motor.
        /// </summary>
        /// <param name="motor">The motor to drive continuously.</param>
        /// <param name="minimumMotorSpeed">The minimum speed setting that causes the motor to turn. Speeds below this
        /// threshold may cause the motor to not turn at all.</param>
        /// <param name="initialSpeedGuess">A rough initial guess for a speed to try to reach the first cycle in time.
        /// </param>
        /// <param name="pulse">The input which pulses to measure the motor speed.</param>
        /// <param name="pulseDebounceMillisecondsAtFullSpeed">The time, in milliseconds, that shall be used as the
        /// debounce time for the <paramref name="pulse"/> input when the <paramref name="motor"/> runs at full speed.
        /// </param>
        /// <param name="pulseMonitor">An output to show the monitored pulse input.</param>
        /// <param name="idealSecondsPerCycle">The number of seconds for one pulse cycle which would give a perfectly
        /// accurate operation of the clock.</param>
        /// <remarks>The motor speed is constantly adapted to the measurement given by the pulse to realize the needed
        /// pulse times without cumulative errors, even if the motor changes its behaviour during the operation.
        /// </remarks>
        public static void Run(ISingleOutput motor,
                               float minimumMotorSpeed,
                               float initialSpeedGuess,
                               IBooleanInput pulse,
                               double idealSecondsPerCycle,
                               IBooleanInput runAtFullSpeedSwitch)
        {
            // Check parameters:
            if (motor == null)
            {
                throw new ArgumentNullException(nameof(motor));
            }
            if (minimumMotorSpeed <= 0f || minimumMotorSpeed >= 1f)
            {
                throw new ArgumentOutOfRangeException(nameof(minimumMotorSpeed));
            }
            if (initialSpeedGuess < minimumMotorSpeed || initialSpeedGuess > 1f)
            {
                throw new ArgumentOutOfRangeException(nameof(initialSpeedGuess));
            }
            if (pulse == null)
            {
                throw new ArgumentNullException(nameof(pulse));
            }
            if (idealSecondsPerCycle <= 0f)
            {
                throw new ArgumentOutOfRangeException(nameof(idealSecondsPerCycle));
            }


            // Run unit tests on the RunningAverageCalculator class:
            Console.WriteLine("Testing RunningAverageCalculator");
            RunningAverageCalculator.Test();
            Console.WriteLine("RunningAverageCalculator successfully tested");

            // An average calculator the motor output voltage (ranging from 0.0f to 1.0f) needed to read one cycle in
            // idealSecondsPerCycle seconds:
            var voltageForIdealCycleTime = new RunningAverageCalculator(10);

            // Add the initial guess of that voltage:
            voltageForIdealCycleTime.Add(initialSpeedGuess);

            // Give a short full speed pulse to the motor to get it surely running:
            motor.Value = 1.0f;
            System.Threading.Thread.Sleep(10);

            // Let the motor run until the pulse changes from false to true to initialize the position to a pulse
            // boundary:
            Console.WriteLine("Initializing to pulse position");
            motor.Value = initialSpeedGuess;
            pulse.WaitFor(true, true);

            // This is our starting point:
            var clockStartTime = DateTime.UtcNow;

            int      n  = 0;              // The number of cycles passed
            DateTime t0 = clockStartTime; // Ideal start of the running cycle
            DateTime a0 = t0;             // Actual start of the running cycle

            Console.WriteLine("Ideal seconds per cycle = " + idealSecondsPerCycle.ToString("N4"));
            Console.WriteLine("Running the clock at initial v = " + initialSpeedGuess.ToString("N4"));

            while (true)
            {
                if (runAtFullSpeedSwitch.Value)
                {
                    Console.WriteLine("Manually adjusting clock by running at full speed");

                    // Let the motor run at full speed to adjust the clock's time on the user's request:
                    float lastSpeed = motor.Value;
                    motor.Value = 1f;
                    runAtFullSpeedSwitch.WaitFor(false);

                    // Reinitialize:
                    Console.WriteLine("Initializing to pulse position");
                    motor.Value = lastSpeed;
                    pulse.WaitFor(true, true);
                    Console.WriteLine("Pulse reached");
                    n = 0;
                    clockStartTime = DateTime.UtcNow;
                    t0             = clockStartTime;
                    a0             = t0;
                }

                // Calculate the end of the current (and the beginning of the next) cylce:
                n++;
                DateTime t1   = clockStartTime.AddSeconds(idealSecondsPerCycle * n);
                double   t1a0 = (t1 - a0).TotalSeconds;

                // Wait for the next (debounced) pulse, telling us that we reached the end of the current cycle:
                DateTime a1;          // The actual end of the current cycle.
                double   a1a0;        // a1 - a0: The number of seconds between a0 and a1.
                int      bounces = 0; // The number of bounces the pulse contacts made

                do
                {
                    pulse.WaitFor(true, true);
                    a1   = DateTime.UtcNow;
                    a1a0 = (a1 - a0).TotalSeconds;
                    bounces++;
                } // Debounce by accepting the next pulse not earlier than at 70% of the wanted time interval:
                while (a1a0 < 0.7 * t1a0);

                // We may have missed one or more pulses due to mechanical errors in pulse detection.
                // Estimate the number of real cyles, rounding by adding 0.5 and casting to int (which truncates):
                int cycles = (int)((a1 - t1).TotalSeconds * motor.Value /
                                   (voltageForIdealCycleTime.Average * idealSecondsPerCycle)
                                   + 0.5)
                             + 1;

                if (cycles > 1)
                {
                    // We lost [cycles - 1] pulses. The worm turned multiple times until we got a contact.
                    // Adjust the counted pulses and the ideal target time for that number of pulses since the last
                    // contact:
                    n  = n + cycles - 1;
                    t1 = clockStartTime.AddSeconds(idealSecondsPerCycle * n);
                }

                // Take note of the current measurement's insight:
                voltageForIdealCycleTime.Add(motor.Value * a1a0 / (idealSecondsPerCycle * cycles));

                // Calculate the motor voltage needed to reach the next cycle pulse right in time t1 and
                // set the motor voltage to this value, taking the lower and upper bounds into account:

                DateTime t2 = clockStartTime.AddSeconds(idealSecondsPerCycle * (n + 1));

                motor.Value =
                    Math.Max(minimumMotorSpeed,
                             Math.Min(1.0f,
                                      (float)(voltageForIdealCycleTime.Average * idealSecondsPerCycle
                                              / (t2 - a1).TotalSeconds)));

                // Report to debugger:
                double diff = (a1 - t1).TotalSeconds;
                // Math.Abs(double) is not implemented on Netduiono 3:
                double absDiff = diff < 0.0 ? -diff : diff;

                Console.WriteLine(
                    "n = " + n.ToString("N0").PadLeft(8) +
                    " | bounces = " + bounces.ToString().PadLeft(3) +
                    " | cycles = " + cycles.ToString().PadLeft(2) +
                    " | vi = " + voltageForIdealCycleTime.Average.ToString("N4").PadLeft(6) +
                    " | t1 = " + t1.ToString("HH:mm:ss") +
                    " | a1 = " + a1.ToString("HH:mm:ss") +
                    " | " + (diff == 0.0 ? "exactly in time           " :
                             ((diff < 0.0 ? "early by " : " late by ") + absDiff.ToString("N4").PadLeft(7) + "s (" +
                              (absDiff * 100.0 / t1a0).ToString("N2").PadLeft(5) + "%)")) +
                    " | v = " + motor.Value.ToString("N4"));

                // The current cycle gets the passed one:
                t0 = t1;
                a0 = a1;
            }
        }
        /// <summary>
        /// Runs a "Turmbergbahn" train, that is, 2 trains hanging on a single steel wire driven by a motor, running on
        /// the same rails using a "Abt'sche Weiche".
        /// </summary>
        /// <param name="trainMotor">The motor driving both trains at once. +1.0 is output for the direction so that
        /// train 1 drives upwards and train 2 drives downwards, -1.0 vice versa.</param>
        /// <param name="train1ReachedBottomStation">Signals true when train 1 reached the bottom station (and thus
        /// train 2 reached the top station).</param>
        /// <param name="train2ReachedBottomStation">Signals true when train 2 reached the bottom station (and thus
        /// train 1 reached the top station).</param>
        /// <param name="doorMotor">The motor driving all doors on both trains at once. +1.0 is output for opening,
        /// -1.0 for closing.</param>
        /// <param name="redLight">True shall light up a red traffic light when people shall not enter or leave the
        /// train.</param>
        /// <param name="greenLight">True shall light up a green traffic light when people may enter or leave the
        /// train.</param>
        /// <param name="waitForDoorsToMoveInMs">The time, in milliseconds, to wait for the
        /// <paramref name="doorMotor"/> to have operated all doors reliably.</param>
        /// <param name="waitWithOpenDoorsInMs">The time, in milliseconds, that the doors shall remain open.</param>
        /// <param name="waitAroundDoorOperationsInMs">The time, in milliseconds, to wait after the train stopped and
        /// before opening the door, and after the doors were closed again before the train starts.</param>
        public static void Run(ISingleOutput trainMotor,
                               IBooleanInput train1ReachedBottomStation,
                               IBooleanInput train2ReachedBottomStation,
                               ISingleOutput doorMotor,
                               IBooleanOutput redLight,
                               IBooleanOutput greenLight,
                               int waitForDoorsToMoveInMs,
                               int waitWithOpenDoorsInMs,
                               int waitAroundDoorOperationsInMs)
        {
            // Check arguments:

            if (trainMotor == null)
            {
                throw new ArgumentNullException(nameof(trainMotor));
            }
            if (train1ReachedBottomStation == null)
            {
                throw new ArgumentNullException(nameof(train1ReachedBottomStation));
            }
            if (train2ReachedBottomStation == null)
            {
                throw new ArgumentNullException(nameof(train2ReachedBottomStation));
            }
            if (doorMotor == null)
            {
                throw new ArgumentNullException(nameof(doorMotor));
            }
            if (redLight == null)
            {
                throw new ArgumentNullException(nameof(redLight));
            }
            if (greenLight == null)
            {
                throw new ArgumentNullException(nameof(greenLight));
            }
            if (waitForDoorsToMoveInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitForDoorsToMoveInMs));
            }
            if (waitWithOpenDoorsInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitWithOpenDoorsInMs));
            }
            if (waitAroundDoorOperationsInMs < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(waitAroundDoorOperationsInMs));
            }

            // Run the train:

            bool moveDirection      = false;
            var  trainReachedBottom = new BooleanOrInput(train1ReachedBottomStation, train2ReachedBottomStation);

            while (true)
            {
                // Initialize lamps:
                redLight.Value   = true;
                greenLight.Value = false;

                // Move the train in the current direction until one of the end buttons is pressed:
                if (!(train1ReachedBottomStation.Value || train2ReachedBottomStation.Value))
                {
                    trainMotor.Value = moveDirection ? 1.0f : -1.0f;
                    trainReachedBottom.WaitFor(value: true, edgeOnly: false);
                    trainMotor.Value = 0.0f;
                }
                moveDirection = !moveDirection;

                // Wait a bit before opening the doors:
                Thread.Sleep(waitAroundDoorOperationsInMs);

                // Open the door:
                doorMotor.Value = 1.0f;
                Thread.Sleep(waitForDoorsToMoveInMs);
                doorMotor.Value = 0.0f;

                // Let people step in and out, wait a bit:
                redLight.Value   = false;
                greenLight.Value = true;
                Thread.Sleep(waitWithOpenDoorsInMs);
                redLight.Value   = true;
                greenLight.Value = false;

                // Close the door:
                doorMotor.Value = -1.0f;
                Thread.Sleep(waitForDoorsToMoveInMs);
                doorMotor.Value = 0.0f;

                // Wait a bit before the train starts again:
                Thread.Sleep(waitAroundDoorOperationsInMs);
            }
        }
Esempio n. 18
0
 public void SetConnection(ISingleOutput input)
 {
     Input = input;
 }