INTRODUCTION

Overview

Robot turtles are extremely popular and fun to work with and are used extensively in both education and hobbyist circles. While the possibilities are endless, problem solving typically falls into three distinct categories:

1) Line Following.

2) Obstacle Avoidance.

3) Maze Escape.

Proteus combines an electrical model of the turtle (motors, sensors, etc,) together with the Arduino baseboard and then presents a simple but flexible virtual world in which the turtle motion can be simulated. Control of the turtle in Visual Designer is vastly simplified by the use of high level methods in a flowchart program, while greater flexibility and complexity can be managed by writing Arduino C code directly. Regardless of the coding choice the simulation, test and debug takes place entirely inside the Proteus software before deploying to the physical turtle.

The following robot turtles are currently supported:

Funduino

Web Link

The Funduino turtle is a simple robot using an Arduino Uno baseboard alongside the motor driver board and 3 line hunter sensors. The ultrasonic range finder sits on top along with a stepper motor which allows you to swivel the sensor head. All of this is modelled in Proteus meaning that you can write your flowchart or firmware program and then test it in software.

Since the Funduino is the cheapest turtle we could find (around $50 at the time of writing) it's not surprising to find some limitations. In particular, there are no position encoders on the motor wheels and the line hunter sensors are digital.

Zumo

Web Link

The Zumo robot for Arduino is an Arduino-controllable tracked robot platform. It includes two micro metal gearmotors coupled to a pair of silicone tracks, a stainless steel bulldozer-style blade, an array of six infrared reflectance sensors for line following or edge detection, a buzzer for simple sounds and music, a 3-axis accelerometer, magnetometer, and gyro for detecting impacts and tracking orientation.

The zumo is a more advanced turtle than the Funduino and can perform far better at line following and maze escape challenges but it does not have ultrasonic range finder and therefore is not as well suited to obstacle avoidance challenges.

Virtual Environment / Obstacle Map

In order to test a written program the robot turtle needs an environment in which to operate during a simulation run. While there are many sophisticated and complex physics engines on the market, the goal of our simulation is to check and debug the firmware program and so we have kept things very simple. Our virtual world is a picture drawn in MS Paint or similar in which the following simple rules apply:

- 1 pixel is 1mm.

- Black is to be followed.

- Red is to be avoided.

- Green is a breakpoint and will pause your program !

From Left to Right : Line Following example, Obstacle Avoidance example and Line Following with Obstacle example

To create and apply an environment for simulation

1) Draw the required route / obstacles in the graphics package of your choice. Remember that the scale is 1 pixel to 1 mm so drawing a 5 pixel wide line will equate to 5mm in the real world. Width of the line being followed can affect the algorithm (e,g if all the sensors are never over the line) so it's important to give this some thought.

2) Save the graphic as a PNG file into the same directory as your Proteus project.

3) Edit the turtle component on your schematic and specify the graphic you have just saved as the obstacle map.

4) Run the simulation.

Positioning the turtle in the virtual world

  • The turtle can be picked up and placed somewhere else on the map with the left mouse.
  • You can rotate the turtle by holding the CTRL key and using the left mouse.

You can specify an initial position by first pausing the simulation, then positioning as required and finally, right clicking and specifying the current position as the new start position.


Tutorial

TUTORIAL - OBSTACLE AVOIDANCE

Introduction

This tutorial shows how to set up a Visual Designer project with the Funduino turtle, program it to avoid obstacles and then test and deploy to the real hardware.

While we are using the Funduino turtle for this tutorial we could easily use the Zumo turtle and change the challenge to something like a line follower. The principles are the same for both turtles.

Project Setup

The first stage is to create the new project and add the Virtual Turtle.

1) Open the New Project Wizard from the Proteus home page and specify the project name and destination path as required.

2) Create the schematic from the default template and then create a flowchart project with the Arduino Uno.

If your license key includes Proteus PCB Design you will need to choose not to create a PCB on that page of the wizard. If your license does not include PCB design you will not see the PCB design page of the wizard.

3) Continue and exit the wizard to create your project. You should see on the Visual Designer tab that you have a skeleton flowchart with the familiar Arduino setup and loop routines while on the schematic you'll find the Arduino Uno pre-placed.

4) We now need to add the Virtual turtle to the project. We do this from the Add peripheral command in Visual Designer.

5) The next thing we need to do is create an obstacle map or virtual world for our turtle to simulate in. To do this we open MS Paint (click on START button and type in 'paint' in WIN8 or higher) or similar and draw some obstacles. The two vital points to remember are that anything red is considered an obstacle and that one pixel equals one millimeter. If we set our canvas to 2000 pixels wide by 1500 pixels that corresponds to around 2 meters by 1 1/2 meters in the real world which is plenty for an obstacle avoidance playground. After that, simply place a few red shapes inside a 'play area' to act as the obstacles and then save our as a PNG file.

If we were setting up a line-following environment we would use black lines for the course to be followed and then shrink the canvas size around the map (the world doesn't need to be much bigger than the race-course).

6) The final task is to tell Proteus which obstacle map to simulate the turtle inside. We do this by editing the Virtual Turtle on the schematic and specifying the location of the obstacle map in the resulting dialogue form.

Firmware Design

When we added the Funduino turtle to our project above we received a number of high level methods that we can use on the flowchart to control the turtle. These are discussed individually in the Visual Designer methods topic which may prove a useful reference as we work through the program. We'll also assume here that the user is familiar with the basics of flowchart design in Visual Designer - these are covered in depth in other tutorials.

You'll find the completed program in the Obstacle Avoidance sample design so if you are comfortable with the firmware design you can load the completed version (File Menu -> Open Sample, type 'obstacle avoidance', select and open) and continue to the simulation and debug section of the tutorial.

Our basic algorithm will be to continuously send out sonar bursts (ping method), to compare against previous values (test if we are stuck) and then check distance to obstacle if not stuck (test if we need to turn now). The first step is to create some working variables and initialize them in the setup routine.

Add 3 variables: LastPingValue (Float), PingValue (Float) & SamePingValueCount (Integer).

At the top of the loop routine we then want to set out ping method by dragging and dropping from the project tree and assigning the result to our pingValue variable.

The result of this is the basis of our decision making. Our first test is to see whether the value is approximately the same as the last one. If it is we'll consider ourselves to be the same distance from the obstacle. What we need then is to place a decision block, subtract the current pingvalue from the previous ping value and we'll consider a difference of less than 0.5 to mean that our distance from the obstacle is unchanged. Note that we use the fabs() math function to return an absolute floating point value.

This branches our program into two forks, one where we are considered the same distance from the obstacle and the other where we are not. As in the image below, we do this by incrementing our samevaluecount variant in one direction (YES), or resetting it in the other direction (NO). This is done by dragging and dropping assignment blocks.

In the case where we are not stuck our job is fairly simple. Without going into detail we test whether we are closer than 15cm to the obstacle and we turn right if we are or keep going forwards if we are not. A delay is used at the end to allow a little driving time before the next iteration of the loop.

See Also:

Sonar Head Methods

Motor Drive Methods

In the case where we may be stuck we need to test whether we have registered the same distance from an obstacle many times and, if so, we will reverse for a little bit and then turn right for a little bit before rejoining the main loop at the bottom. This is shown below.

As said earlier, the completed code can be found in the sample in the 'Avoid Obstacle' sample design in the Visual Designer section.

Simulation and Debug

Having written our program we can compile via the Build Project command or the icon at the top of Visual Designer. Progress will be shown on the output window at the bottom of the editing window and we should eventually see a compiled successfully message.

Pressing the play button on the animation control panel will then start the simulation. You will see a popup window hosting the obstacle map that we created in the setup and a little turtle driving around inside it. The purple cone shows the range and scope of the sonar and the turtle behaviour is dictated by the program we have just written. For example, if we stop the simulation and change the distance test from 15cm to 5cm and then re-run the simulation you will see that the turtle is getting very close to obstacles before turning and will actually crash when approaching at certain angles.

We can pause the simulation at any time via the pause button on the animation control panel

Setting Breakpoints

If we need to we can set breakpoints in several different ways :

1) Via the right click context menu on one of the flowchart blocks.

2) By drawing in green on the obstacle map.

3) By setting up a condition on a watch window item.

Regardless of how the breakpoint is triggered, the reason that we set it is so that we can investigate the behaviour of the turtle more closely at that point. With Proteus, we are in the unique position that we can control time because the turtle is simulating under our control. This means for example that we can step through the code and the turtle will behave exactly as it would have were there no debugging in place (motors won't lose momentum etc.).

Single Stepping

We can step through the code for our turtle program at multiple levels:

1) At flowchart level by right clicking and setting a breakpoint on the flowchart block.

2) At source code level by first stopping the simulation and then selection the debug generated code command from the project tree.

Make sure you use the Debug Generated Code command and not the Convert to Source Project command here. This will switch your project from flowchart to source code but it is not a reversible operation.

3) At machine code level by selecting the disassembly command from the context menu.

In either case the single step commands can be found on the debug menu or via the icon strip at the right hand side of the main window.

You can also use the shortcut keys F10 for step over and F11 for step into.

See Also:

Debugging (Flowchart)

Debugging (Source Code)

Changing the Virtual Environment

One of the neatest things about virtual turtle simulation is just how easy and fast it is to test your program against challenges of different sizes and complexity. All you have to do is change the picture and then enter the name in the properties of the component. Here's a few line following examples

Programming the Physical Turtle

Proteus includes built in support for the common AVRDUDE programmer so that you can program the real hardware directly from the Proteus software.

This process is discussed in full in the Visual Designer help documentation linked below.

See Also:

Programming the Physical Hardware


VISUAL DESIGNER COMMAND REFERENCE

Introduction

When working in Visual Designer, a lot of the complexity of driving the turtle is provided by several high level methods that abstracts much of the electronics complexity, leaving the user to focus on the control algorithms. Since each turtle is made up of different pieces the driver methods in Visual Designer for each are also different. These are discussed below.

Advanced users can simply convert their project to a source code project via the context menu command on the project tree and then write their programs in Arduino C.

Once a program is switched to be a source code project from a flowchart project you cannot switch back.

This may have some advantages as users can access the on board peripherals (e.g. gyro, accelerometer) at the register level but will undoubtedly be more challenging. At the end of the day, the Proteus simulation is of the real hardware however which means that users can develop their programs in whatever way they want. In particular, it means that 3rd party libraries and source code examples on the internet can be added, used and tested in a Proteus code project.

Funduino Turtle

Control of the turtle falls into three categories :

  • Using the line hunter sensors to detect position relative to a line..
  • Using the sonar head to detect obstacles.
  • Driving the two DC motors attached to the wheels..

Line Hunter Control

There are three sensors underneath the Funduino turtle. These provide a digital response to the circuit based on whether they detect the line or not. In Visual Designer we query these sensors with a single decision block called the sensor function. You use the sensor function by dragging and dropping directly from the peripheral in the project tree as shown below:

We then need to edit the decision to test the sensors based on a set of conditions we wish to be true. There are three parameters corresponding to the left, center and right sensors and for each one we can test as follows:

1 : Must be TRUE.

0 : Must be FALSE.

-1 : Don't care.

Examples

If we want to test that all 3 sensors are over the line we would set all three parameters to 1.

All three sensors can see the line

When this decision is true you know that the turtle is fully over the line and you may choose to attempt some damping or correction if the turtle is wobbling.

If we want to check when we need to make a sharp turn right then we are looking at the case when only the right hand sensor is picking up the line.

Only the right hand sensor sees the line

If we want to simply drive forwards then testing that the middle sensor is over the line is likely sufficient, provided we do so after other relevant conditions have been tested.

Sonar Head Control

The ultrasonic sonar sends out short bursts (pings) to detect obstacles and is mounted on a rotatable unit. This allows users to first position the sonar head and then check for obstacles inside a certain range. There are three methods and a sensor function for the sonar head.

Sensor (Sonar) Function

The sensor function is a decision block that allows you to query the peripheral and it is used by dragging and dropping from the peripheral itself in the Project Tree. In the case of the Sonar Head the decision block takes two arguments for distance and head angle. It returns true if an object is detected within the specified distance at the given head angle. The example below would return TRUE if an obstacle was within 50cm on the left of the turtle.

setAngle() Method

The setAngle() method allows you to position the sonar head. For most applications this will be added to the setup routine with a value of 0 (start by looking straight ahead) and then if required through program execution.

setRange() Method

The setRange() method allows you to specify the maximum range in which you want to detect obstacles. This is significant as it determines the time-frame in which the firmware will consider the reply to a ping to count as a reflection from an obstacle. You would normally set this (as small as possible) inside the setup routine and then adjust as required in the program.

ping() Method

The ping() method fires a sonar burst, converts time to response into distance in cm and returns either that value or -1 if nothing is detected. After placement, the user must edit the method call and assign the return value to a variable.

This variable must be a FLOAT variable otherwise it will not appear in the 'Results' drop down list.

Motor Drive Control

The Drive methods give control over the left and right wheels of the motor. The user is presented with a series of simple control methods as follows.

Drive() Method

The drive method allows you to specify the wheel(s) to control, the direction of travel and the speed. The latter is a value from 0 -> 255 and represents the duty cycle of the PWM drive signal. For example, you might set up full speed ahead as both wheels forwards at around speed 200.

Forwards() Method

With the forwards() method the direction of travel is explicit and so all that is needed is the speed value.

Backwards() Method

As with the forwards() method, all that is needed is the speed at which to reverse.

Turn() Method

The turn() method simplifies the turning of the turtle by allowing you to specify a speed of turn. Negative values turn left while positive values turn right and the magnitude of the value is the speed of turn. In practise, this will execute a turn by turning one wheel forwards and the other backwards at the specified speed. It can therefore be thought of as a sharp turn where a soft turn involves stopping one wheel and turning the other.

The same effect can be achieved with greater precision by using the drive() command twice and controlling speed of wheels independently.

Stop() Method

The stop() method immediately stops drive of both wheels.

Zumo Turtle

Control of the Zumo turtle in Visual Designer falls into three basic categories :

  • Using the line hunter sensors to detect position relative to a line.
  • Using the gyro and compass to position or orientation the turtle.
  • Driving the two motors attached to the tracks.

Line Follower Control

The Zumo comes with a mounted array of six IR reflectance sensors that allows the Zumo to detect contrasts in reflectivity directly beneath its blade, which can be used for following lines or detecting edges. Each reflectance sensor consists of an IR emitter coupled with a phototransistor that responds based on how much emitter light is reflected back to it. Unlike the Funduino therefore, the Zumo is well suited to Proportional Integral Derivative (PID) control algorithms when line following.

readLinePos() method

- Takes no parameters

- Returns an integer between 0 and 6000 indicating the position of the line underneath the six IR sensors.

This method first reads the calibrated value from each of the six sensors into an array. Values per sensor range from 0 to 1000 where and are a measure of the reflectance in abstract units, with higher values corresponding to lower reflectance (e.g. a black surface or a void). An estimated position of the robot with respect to the line is then calculated used a weighted average of the sensor values multiplied by 1000. This means that a return value of 0 means that the line is directly under sensor 0, a return value of 1000 indicates that the line is directly below sensor 1 and so on. Intermediate values indicate that the line is between two sensors. The formula used is :

Example:

1) Add the Zumo turtle to the Visual Designer Project.

2) Drag and drop the readLinePos() method onto the flowchart.

3) Edit the method and create an integer variable (e.g. linePos). Set the variable to store the return value from the method.

If you get a value of 0 the line is underneath the far left hand sensor, 1000 means the line is flush underneath the second sensor from the left, 2500 means that the line is right in the middle of the turtle between sensors 3 and 4 and a value of 6000 means that the line is underneath the far right sensor.

readRawValue() method

- Takes an integer parameter corresponding to the index of the IR sensor you want to read (0..5).

- Returns the raw (uncalibrated) value from the specified sensor.

The number returned is based on the reflectance. The higher the number, the less reflectance so a black line gives a high value. The numbers are not calibrated meaning that care is required with return values as they would change under different conditions in the real world.

Example:

1) Drag and drop the readRawValue() method onto the flowchart.

2) Edit the method and create an integer variable (e.g. rawSensorValue). Set the variable to store the return value from the method..

3) Set the index parameter to specify which sensor you want to query. 0 is the left hand sensor, 5 is the right hand sensor.

Compass Control

The Zumo includes an integrated LSM303D chip which can be controlled by the following Visual Designer methods:

readMagneticField() method

- Takes three floating point parameters (void readMagneticField (float *magX, float *magY, float *magZ))

- Returns the X,Y,Z components of the magnetic field in units of Gauss.

This method passes in pointers to three floating point variables and the internal routine then populates them with the X,Y and Z components of the magnetic field. Note that the compass is widely inaccurate in relative and absolute terms. I.e. the vector is offset from the origin and North is impossible to determine without calibration.

In the read device the compass gets a lot of interference from the motors, batteries, PCB, and its surroundings, so it is not generally useful for precision navigation. However, having been calibrated it can be used for rough orientation measuring in many environments.

Example:

1) Drag and drop the method onto the flowchart.

2) Edit the method and create three new variables (e.g. magX, magY, magZ)

3) Enter the three variables in to the Results field separated by a comma. This passes the three variables as parameters to the method.

calibrateHeading() method

- Takes no parameters

- Returns no values

This function uses the drive method to spin the Zumo on the spot and take multiple magnetic readings. It takes the minimum and maximum X and Y magnetic values found and uses these to calculate the centre. It stops spinning when no new min or max values are set over a period of 500ms. Before calling this function it assumes the Zumo is facing North. Thus is uses the first magnetic reading to work out the angle of the vector that points to North.

readHeading() method

- Takes no parameters

- Returns a float representing the heading.

This function requires calibrateHeading() to have been called. If it hasn't then -1.0 is returned. Otherwise the heading angle in degrees limited to [-180.0, +180.0] is returned (0 is North).

Example:

1) Drag and drop the calibrateHeading() method onto the flowchart. This is best done at the very beginning where the Zumo can be pointed north so the setup routine makes sense.

2) Drag and drop the readHeading() method anywhere after the calibration routine.

3) Edit the readHeading() method and create a variable of type float (e.g. heading) to receive the function return.

A value of 0 means the Zumo is pointing north, a value of 180 means South, a value of -90 means West and so on.

Gyro Control

The Zumo (V1.2) includes an integrated L3GD20H 3-axis gyroscope that can be used to track rotation and, together with the LSM303D effectively provides an inertial measurement unit that programs can use. The Visual Designer wraps some of this functionality in two high level methods:

readAngularAcc() method

- Takes three floating point parameters (void readAngularAcc(float *angX, float *angY, float *angZ))

- Returns the X,Y,Z components angular acceleration in units of degrees per second.

This function returns the angular acceleration of the Zumo in three dimensions. Note however, that due to the 2D nature of the simulation environment, only the angZ parameter will be non-zero.

Example:

1) Drag and drop the method onto the flowchart.

2) Edit the method and create three new variables (e.g. angX, angY, angZ)

3) Enter the three variables in to the Results field separated by a comma. This actually passes pointers to the three variables into the method which will then return the relevant values.

readLinearAcc() method

- Takes three floating point parameters (void readLinearAcc (float *linX, float *linY, float *linZ))

- Returns the X,Y,Z components angular acceleration in units of G.

This function returns the linear acceleration in three dimensions.

The actual measurement of linear acceleration is on the LSM303 device whereas the angular acceleration is read from the L3GD20H device. Linear acceleration is a tricky one to measure in a simulation environment as it happens over such a short amount of time. The following is an explanation of the implementation:

The physics modelling does not simulate acceleration - when a the turtle is driven it sets the speed instantaneously. The reason for this is that the turtle and Zumo get up to speed so quickly there was any point in modelling it. However, this is no good if you're measuring linear acceleration. So acceleration has been modelled by looking at the change in velocity from one (simulation) frame to the next and limiting the change to a maximum of 1G for driven acceleration and 10G for collisions. Obviously, 1G accelerations occur over more frames than 10G accelerations and therefore are more successful to catch when polling the device for changes.

In practice, we assume the linear acceleration may be used in a tight loop to test against a collision with an obstacle. We welcome feedback on this - tell us what you are doing and if our implementation is lacking.

Motors Drive Control

The Zumo contains two integrated micro metal gearmotors with a DRV8835 dual motor driver to control them. The following methods are used in Visual Designer to control this hardware.

drive() method

- Takes three parameters (which wheel, which direction and what speed).

- Has no return value.

This is the workhorse method to move the Zumo turtle. It allows you to drive one or both of the wheels in a direction and speed of your choice.

Example:

1) Drag and drop the drive method onto the flowchart

2) Edit the method and specify the wheel and direction to drive.

3) Specify the speed at which you want to drive the wheel. This is a value between 0 and 255 where 255 represents full speed.

The range 0..255 are used because they represent a byte and at a lower level the motor is driven electronically by altering the duty cycle of a PWM signal (using the Arduino analogWrite() method).

forwards() method

- Takes one parameter for speed.

- Has no return value.

With the forwards() method the direction of travel is explicit and so all that is needed is the speed value.

backwards() method

- Takes one parameter for speed.

- Has no return value.

As with the forwards method except driving the turtle straight backwards at the specified speed.

turn() method

- Takes one parameter for speed.

- Has no return value.

The turn command allows the Zumo to turn either clockwise or anti-clockwise at a given speed. The range of the speed parameter is -255..255 where :

-255 -> 0 : turn anti-clockwise by driving right wheel forwards and left wheel backwards.

0->255 : turn clockwise by driving left wheel forwards and right wheel backwards.

Example:

1) Drag and drop the method onto the flowchart.

2) Edit the method and set the speed value between 0 and 255. Prefix with a minus sign if you want to turn anti-clockwise.

turnDegrees() method

- Takes two integer parameters, one for the number of degrees to turn and the second for the speed of turn.

- Has no return value.

The turnDegrees() method allows you to control the amount of turn programmatically. You specify the number of degrees that you want to rotate (0..360) and the speed at which you wish to do so (-255...255).

Internally, this method uses the gyro, reads the angular acceleration in Z and then calculates the time needed to turn the specified number of degrees. It follows that, while fairly accurate, it will be an approximation.

Example:

1) Drag and drop the method onto the flowchart.

2) Edit the method and set the speed value between 0 and 255. Prefix with a minus sign if you want to turn anti-clockwise.

3) Set the number of degrees to turn.

stop() method

- Takes no parameters

- Has no return value

This method will stop the motor drive and bring the turtle to a halt.


MECHANICAL FORCES

It is important to understand that a Proteus simulation of the Virtual Turtle, while electrically accurate, is not a physics aware simulation. The motor control of the turtle is open loop and therefore the amount of distance travelled in a period of time is not deterministic. All sorts of physical effects such as inertia, momentum, friction, load/slope and battery power can have significant impact on distance travelled in the real device. In no way therefore should you rely on a timed value in the programming of the device unless you are confident that the real world conditions are not going to change.

In the Zumo turtle you can query the distance travelled via the gyro which helps enormously with writing the firmware but you still cannot determine the distance travelled over a period of time in advance.

For example, the turtle may travel 20 cm on the table but 10cm on carpet, it may lose 20% power as the batteries run down and may not start moving at all if the duty cycle of the PWM doesn't provide enough power to overcome inertia.

Similarly, there may be significant differences in behaviour with line sensing depending on the lighting conditions and the contrast of the line against the background.