3

How to toggle a motor on/off with a touch sensor

Color counting machine with a touch sensor

Starting with a simple challenge involving a touch sensor and a motor, this learning sequence shows how to turn a motor on and off with a touch sensor using flow control structures that include:

  • waits
  • switches
  • loops
  • flags
  • the master/slave design pattern.

In addition, it also shows how to a range of programing techniques, including:

  • variables
  • user blocks arguments
  • arrays and how to operate with them.

Through this learning sequence, students will gain a deeper understanding of how to:

  • use a touch sensor to control a motor
  • add more conditions and control the flow of the program using different programing techniques and their implications when using Wait, Switch, or Loop blocks
  • synchronize different programming flow sequences, using variables and the master/slave design pattern
  • use loops that need to run at different rates and the use of variables and timers to control these loops
  • use and operate with arrays
  • display messages and control the status light of the brick screen.

Exercise 1: Turn a motor ON with touch sensor

The touch sensor is the simplest sensor in the LEGO Mindstorms platform. It gives a true value if it is pressed and false if it is not. In addition, you can configure the touch sensor to give a true value if it has been bumped, that is if the sensor has been pressed and then released.

How could you program a motor to start when a touch sensor is pressed?
The simplest way is to use a Wait block configured to use a touch sensor as shown in the following image.

Wait until the touch sensor is pressed then start a motor.

What are the limitations of this program?
As intended, the motor will only start after the touch sensor is pressed. It will, however, only run for one rotation.

What if you want to make the motor continue running?
Some students might say that you only need to configure the Motor block to turn the motor “on” instead of “on for rotations”. If you try this, you will see that the motor doesn’t even start. Why? Because the program ends after the Motor block and when a program ends, all motors are turned off.

How do you have to modify the program to make the motor run forever?
One option is to put the Motor block inside a Loop set to “Unlimited”. For example:

Wait until the touch sensor is pressed then run a motor forever.
When will the motor stop in the previous program?
Either when you stop it manually or when the brick runs out of battery.

Exercise 2: Turn a motor on and off with a touch sensor

Some students might realise that after waiting for the touch sensor to start the motor, you can wait again to stop it, because the actions are sequential. For example:

Wait until the touch sensor is pressed to run a motor and wait again to stop it.

After the first time the touch sensor is pressed, the motor will start and the program will wait until the sensor is pressed again to stop it.

But does this program work?
Sometimes it works, but not consistently.

Why not?
The program runs so fast that while you are still pressing the touch sensor it will move through the second Wait block and therefore stop the motor. As a result, you need to press and release the touch sensor extremely quickly (or be very lucky) to make the code work.

How can we solve this problem?
We need to configure the Wait block to use the “Bumped” setting:

Wait until the touch sensor is bumped to run a motor and wait again to stop it.

What if you want to restart the motor by pressing the touch sensor again? (without having to restart the program)
The solution is to put the previous code inside an unlimited loop:

Repeatedly turn a motor on and off using a touch sensor.

At this point it might be interesting to ask the students whether we can get the same or similar results using a Switch block instead of a Wait block. It is a nice opportunity to think about the differences between these programing structures.

For example:

Turning a motor on and off using a switch block.

What are the main differences between this program and the previous one?
With this version we need to keep the touch sensor pressed in to stop the motor. In addition, the motor will start as soon as the program starts, unless the touch sensor is pressed in. Keeping the sensor pressed to stop the motor (or running it if we invert the branches of the switch) might be a requirement for some specific scenarios, but the previous solution using Wait blocks might be more convenient for simple examples.

Is there any advantage of this solution compared to the one using Wait Blocks?
This solution uses one less block and does not repeat any blocks.

Exercise 3: Turn a motor on and off using a touch switch and a loop

How can we obtain the same function as the Wait Block solution using a Switch Block?
The idea is that every time the touch sensor is bumped (i.e. pressed and released), the motor will alternate between on and off.

In the following same code, the logic variable flag alternates between true and false. Its value is then used by a Switch block to determine whether to turn a motor on or off. We use a logic variable because we only have two states (on and off), but we could use another type of variable if we had more than two states.

Turning a motor on and off with a touch sensor using a variable and a switch block.

Although this solution is more complex than the one using a sequence of two Wait blocks, it is a much more versatile approach.

It still has a significant problem though.
Imagine that you want to build a sorter machine and that you want it to show a message on the EV3 brick’s screen about the sorted item, or run specific code depending on the sorted item.

Not only does the motor need to run but also several actions might need to be executed, thus making the branch of the switch take significantly more time to complete. And if we try to stop the motor by pressing the touch sensor, we will have to wait until the branch is completed.

How can we solve this problem?
One approach is to use a master/slave design pattern architecture. (For more about this programming technique, see To light or not to light.)

In the following example, the master loop uses a logic variable flag to instruct the slave motor loop to turn the motor on or off.

Turning a motor on and off with a touch sensor using a master/slave design pattern.

Exercise 4: Turn a motor on and off using a touch sensor, and stop the program using another sensor

Let us build on the idea that the motor you are turning on and off is part of a color sorting machine. As a safety measure, you would like the motor to stop if the color sensor detects no color (i.e. there are no more items to sort). Or possibly you want the program to stop completely.

How can we make our robot wait until EITHER the touch sensor is pressed OR the color sensor doesn’t detect any color?
The answer is to create our own version of a Wait block as shown in the following program. (For more about this approach, see How to wait for one or more sensor conditions.)

Bump the touch sensor to turn the motor on, and turn it off either with another bump or the absence of color.

This program will work fine because the actions, running or stopping the motor, execute quickly, but if we need to execute longer and more time consuming program sequences, we will need a better approach.

What’s a better solution?
One approach is to modify the master loop of the master/slave design pattern solution as shown below.

Master loop – If no color is detected, set the flag to false (i.e. to stop the motor) otherwise toggle the flag if the touch sensor is bumped.

To stop the program, you could use Loop Interrupt blocks, making sure that the motor, or any part of the main program in the slave loop, is stopped first.

Another solution is to run different sequences in parallel and use variables to control the flow of the program:

A new parallel sequence stops the master and slave loops if no color is detected using the new logic variable “stop”.

You might need to add specific code in each of the “true” branches of the logic switches connected to the stop variable before exiting the master and slave loops.

Since the master loop contains several parallel sequences to control the different processes that occur at the same time, we should be very careful to avoid a race condition, as we will see in the next exercise. A race condition can occur when different parts of the master loop program try to set the slave loop variable at the same time. (For more about race conditions, see To light or not to light.)

Exercise 5: Turn a motor on and off using a touch sensor and run specific code according to various conditions

As a final exercise, and to really grasp the power of the master/slave design pattern, we will build on the last example from the previous exercise to add the following functions to our color sorting machine.

  1. Count the sorted items by color (blue, green, yellow, and red).
  2. Display the count for each color on the EV3 brick screen.
  3. Pause/unpause the machine if the touch sensor is pressed.
  4. Stop the machine if EITHER no color is detected in a reasonable amount of time OR one of the sorted colors reaches a maximum number.

Note that counting items is relatively fast, but displaying a message on the brick screen long enough for someone to read it requires more time than the other tasks. In addition, while the message is shown, the sorter machine might encounter more items and reach the maximum number of sorted items.

How can we implement these functions? Do we need to change the whole previous program or just a part of it?
We just need to change the last sequence of the previous program. We will add a new loop to that sequence called “MasterColor”.

Let us address the new functions one by one.

Exercise 5-1: Count the sorted items by color

To count each of the different colors, we need somewhere to store the information. The most efficient solution is to store the count for each color in a numeric array.

In this example, we are going to count blue, green, yellow, and red, so let us call the numeric array SortedBGYR.

We also need a variable, ArrayIndex, to store the index of the array corresponding to the color detected by the Switch block. For example:

  • Blue     => 0
  • Green  => 1
  • Yellow => 2
  • Red      => 3
Initialize the variables, reset the timer, and set the value of ArrayIndex according to the color

Notes:

  • If no color is detected, ArrayIndex is set to -1. This is also the default case. As a result, any color that is not either blue, green, yellow, or red will set ArrayIndex to -1 as well.
  • Before entering the loop, we initialise the two variables, SortedBGYR and ArrayIndex, as well as the timer.

Next, we feed the value of ArrayIndex into a Switch block.

If ArrayIndex is -1, we will check the timer and, if necessary, stop the sorter machine, display the message “EXIT”, and set the brick status light to blink red.

Case -1: If no color has been detected, exit the program

Note the use of a Switch Timer block set to 10 seconds to allow time for the next color to be detected. If no color has been detected with 10 seconds, the program is stopped. The false case is empty.

Also, note that if you store the color directly to the ArrayIndex variable, the previous case number will have to be “0” instead of “-1”. In addition the default case will have to be a number other than “0”.

If ArrayIndex is any number other than “-1” (in our example 0, 1, 2 or 3) the appropriate counter will be incremented.

Case 0 (default): Increase the count for the specified color

What will happen if a unexpected color is detected?
As mentioned before, the default case of the Color Sensor Switch (in our case “No Color”) will be called and the sorter machine will treat this case as if no item is detected. If this occurs for more than 10 seconds the program will exit.

A little bit of theory

In our example, the Color Switch has five branches, one for each color we want to count. In the EV3 Software, each color is represented internally by an integer number from 0 (no color) to 7 (black), but the user does not necessarily need to be aware of this representation because every time you need to pick a color, the interface shows a menu with all of them, as shown in the following screen capture.

The color indexes of a Switch Color block

Because our ArrayIndex variable will store the color number, is there a simpler way to set this variable?
If we want to use all seven possible colors of the Color Switch, there is no need to use a Switch block at all. Instead we could use a Color Sensor block and connect the Color output plug to the ArrayIndex variable directly, as shown below.

Solution where the Color sensor output updates the ArrayIndex variable directly

Exercise 5-2: Display the count for each color on the EV3 brick screen

The next step is to display the contents of the array on the EV3 brick screen.

One option is to create a My Block that takes the array you want to print as its input and goes through the different indexes to display them on the brick’s screen. Note that only the first Display block clears the screen.

PrintArrayBGYR: A My Block using a numeric array as an input

Add the My Block, PrintArrayBGYR, into the end of the loop.

My Block PrintArrayBGYR added to the end of the program.

This approach makes the main program much easier to read, and helps with debugging. It also means that this code can be used in different places throughout the main program. For example, we could also use it to initialize the brick screen message.

My Block PrintArrayBGYR added to the start of the program.

Exercise 5-3: Pause/unpause the machine when the touch sensor is pressed

Next, we incorporate the flag variable from Exercise 4 to pause/unpause the machine when the touch sensor is pressed.

We will add a Logic Switch block to the start of the loop to set ArrayIndex to -2 if the flag has been set to false.

If flag is false, set ArrayIndex to -2, otherwise set it as before.

We also need to add a -2 case to the final Switch block to display the PAUSE message and set the brick status light orange.

Display the PAUSE message and set the brick status light orange.

Exercise 5-4: Stop the machine

Finally, we need to stop the machine when either no color is detected or one of the sorted colors reaches a maximum number.

The example below shows a simple strategy for stopping the machine when the number of items reaches five or more.

If there are five or more items of any color, stop the machine, otherwise clear the brick screen message

If the maximum number of items has not yet been reached, the “PAUSE” message is erased and the timer is reset.

Why is it important to reset the timer?
Otherwise when no color is detected, the sorter machine will stop immediately.

The following image shows the complete sequence of the MasterColor loop sequence of the program.

Complete program sequence incorporating the MasterColor loop

The following video shows an example of a color counting machine. To increase the chance of the color sensor reading the color correctly, the slave loop has been modified so that each each item is held under the color sensor for a second.

 

To find more examples, videos, and an introduction course to Mindstorms EV3 for teachers with translations to Catalan and Spanish, visit the BOGATECH website.

The following two tabs change content below.
Josep Fargas
I have been working with LEGO Education robots for many years and have been involved in many schools and conferences. I started the BOGATECH Robotics Workshop to offer activities and support to students, education centres, and teachers. My course, "Robo-telling Stories", was selected as one of the top seven European Union finalists of the inGenious Teachers Competition. One of my main interests is to collaborate with other teachers to research how to teach curricular and non-curricular subjects more creatively.
Josep Fargas

Latest posts by Josep Fargas (see all)

Leave a Reply