In the previous post I pointed out some of the key things
about the hardware components and software techniques that I used to construct
the robot. I this post I hope to give more insight into the software
perspective of the design.(I assume you have read the previous article and the
links I provided . )
In this project my main concern was on to the software side
since most of the hardware I used was either simple or they are already on a
working phase (like Arduino and the chassis.)Anyway before you write your
software it’s important to realise what sort of functionality you are expecting
from the robot and break it down to simpler objectives. In my case the
functionality of the robot can be brake down into several steps.
- Moving the robot to forward, backward, left and right.
- Detect an obstacle in the path.
- React to the obstacle by turning to a different direction.
- Continuing moving along the new direction until it encounters another obstacle.
To achieve the above tasks I used a simple program which is
written using Arduino IDE. Here is a simple flowchart which summaries what the
program does. The 15cm boundary is an arbitrary value, you can use any value
which is in the sensor’s detection range. but I recommend small values since
the sensor is not very accurate in long distances. Initialise is the process of
feeding the program and the controller about the necessary settings like the
I/O pins used the constants, Interrupts etc.. I’ll explain this when I get to
the actual program. The delay function which I used in the program does very
important task and I would like to explain the importance of that. It’s a fact
that mechanical systems are always slower than electronic systems when responding.
So there will be a delay when you send an electrical signal to a mechanical
system to do something and actually starting to do that thing. It won’t
complete that command instantly .So a delay is needed between two commands to
complete each. Otherwise your system will act in unpredictable ways. You should
keep this in mind when programming since it’s not straightforward. It’s one of
the most important thing s I learned in my uni. You can use any amount of delay
time .with some trial and error you can easily find the most suitable delay
time.
Initialise
As I mentioned above initialisations prepares the system and
the program for the execution. It basically consists of declaring the I/O pins,
variables and interrupts. there is a
separate function called Setup() to
initialise the system. Outside this you can declare the functions you are going
use and any #define statements. I
have used timer interrupts to trigger the sensor every 50ms and take a distance
measurement. So I strongly recommend you to read the article about the
interrupts or you can just copy the code of mine. It’s a must to know how to
tackle interrupts in embedded systems , otherwise your programs are not going
to be function efficiently. If you want to change the trigger time all you have
to do is to change the value of OCR1A
to a value you desire within it’s range. Besides this you have to include two
libraries which handle interrupts in setup().
Figure1-Flow chart |
Moving the robot
Moving the robot in a particular direction is one
of the primary task in any robotic project .So first of all I wrote a simple
program to check the movement of the robot and to verify my hardware is working
as I expected, especially the H-bridge control circuit. To achieve this I used
5 functions that each set the pins connected to the DC motors in a particular
configuration. ( by setting these pins high or low you can control the
direction and rotation of the motors.). I declared them as void since we don’t
need that function to return anything .
Figure2-An example for control function |
This pin configuration can be unique or not but play with
your motors to figure it out. But keep in mind not to put all the pins in HIGH since it will damage the IC. It’s
always encouraged to use separate functions to carry out different tasks and
not to do everything in the main()
function. This practice is important when the program gets complex and
branched. The functionality of the main() is like the functionality of a leader
in a team. A leader is not there to do everything by himself but rather to
coordinate others to do what they are capable of. Like that by separating
different functions it gets easy when debugging and finding errors.
Besides that there are two other functions to measure the
distance and to trigger the sensor every 50 ms . When using interrupts there is
a common practice to declare the variables used in ISR to be declared as volatile. The reason for this is to
indicate to the compiler that variable can be changed a synchronically to main
since it gets updated by the ISR. if you don’t declare the variable as a
volatile type the variable might not get updated correctly .So it’s an
important aspect to remember.
Figure3-Distance measure function |
Distance value is in cm and you can change this by changing
the constant 29.1 but I think cm is a reasonable range for the robot. I used a
delay of 1ms to get some time for the
sound wave to spread out and reflect back into the sensor. I used unsinged int
as the return type of the function since a distance can only be a positive
value but recently I came to know that it’s recommended to not to use unsigned
number types in practice since it might causes some troubles if you try to do
arithmetic with that. Since I don’t do
any mathematical operation to it seems
legit to use it.
Figure4-ISR function |
This ISR function is a defined function. So all I did was to
write the content of the ISR. So when the timer interrupt is triggered it will
execute the Measure _distance() function and update the variable x which holds
the distance value.
Figure5-Configuring Timer 1 |
I highly recommend to read this article to understand the
above configuration settings .It’s really important to understand how
interrupts works in order to create good designs. If you would like to use that
configuration without any change it’s ok but if you want a different time (this
is set to trigger every 50ms) you can change the value in 0CR1A register. For example if you double the value (780*2=1560) interrupt
will trigger every 100ms.
Although this was a simple design I learned lot of
things...and above all I had a chance to put the knowledge I gained in my
studies to build something really works. That’s was a great experience for me.
There are some cons in the design that I would like to
discuss in here.
- Sometimes the robot’s behaviour gets unpredictable and it fails to spot an obstacle and gets hit. My primary suspicion was it was due to a fault in sensor since it only happened few times. and sometimes it stopped moving for no apparent reason. As s solution I changed the location of the sensor to a centre position and it improved the performance of the robot.
- According to the Figure1, when the robot detects an obstacle it only turn to right side. It’s not a very intelligent behaviour .Therefore I wrote another sketch to improve the ability to decide a direction to go when it encountered an obstacle. I’ll give you that in the next post.
You can download the complete sketch for the project and play with that around .but
I highly encourage you to write your own sketches since it will improve your
programming skills .I will give a detailed information about the improvements I
have done to the design in the next post.
Below are few photos of my robot Walt...