This is the story of the first version of Mr. Merf…
First things first – shopping!
The most important part is the microcontroller. I chose the Cortex M4 that comes on the Tiva-C Series LaunchPad by Texas Instruments.
In detail: Tiva C Series TM4C123G LaunchPad evaluation board EK-TM4C123GXL with the TM4C123GH6PMI microcontroller.
This is an evaluation board that comes with all sorts of goodies with it, and mainly it has a USB connection (power and ICDI) that allows easy burning of the program in chip and debugging.
Other equipment that I ordered from across the web:
- Ultrasonic sensor, using the HC-SR04
- Breadboard Power Supply Module
- Jumper wires (F-to-F and F-to-M)
- H-Bridge L293D for the motor(s)
- Some colorful LEDs (helps in debugging)
- Resistors 1K and 10K. Just in case…
- A power supply
- Battery case
- Motor – Tamiya 70093 single motor
Next, downloading the software. As the datasheet of the evaluation board advised, I downloaded the TI Code Composer Studio (CCS) from the TI website, and it turned out to be familiar territory because it is built upon the Eclipse IDE.
For burning the binaries to the Tiva-C launchpad I used the LM Flash programmer, and PuTTy client for communication via UART.
I used the TivaWare for C Driver library, as also recommended by the boards’ datasheet and it is easy to download from the “Resources” section of the CCS.
And now, for the coding part…
The coding was divided into a few independent steps, which allowed me to tests each separately before combining them into one program:
- Using the UART utility
- Building the ultrasonic driver
- Building the motors driver
- Learning to use FreeRTOS tasks
- Building the controller module
- Combining everything together
The TivaWare-C comes with a convenient driver lib, and also a bunch of useful utilities. I used the UART utility for the UART0 peripherals which are alreading connected to the ICDI USB connector, allowing the using the UARTPrintf function, which is kinda like the c printf function, to print data to the screen of my PC using a PuTTy client.
The core of Mr. Merf is measuring distances. He need to know how far he is from different objects for him not to bump into them. Obviously.
Mr. Merf is using his ultrasonic eyes to gaze into the world and know what is in front of him.
For this I built an ultrasonic driver, which sends a trigger signal and then waits for the echo to come back. As the echo is received, time needs to be measured to know how much time had passed since the echo was first received. This allows me to calculate the distance Mr. Merf is seeing.
But here is a pickle: I can’t know when the echo will start to come back, nor do i know for how long will it continue…. Interrupts to the rescue!
The microcontroller is communicating with the ultrasonic component via 2 GPIO pins. One for sending the trigger, and the other for receiving the echo .
So to measure the time length of the echo, I defined an interrupt (the Cortex M4 allows a GPIO edge-triggered interrupts to be defined on rising, falling, or both)on both the falling and and the rising edge of the GPIO pin which is connected to the echo pin of the ultrasonic (the Cortex M4 allows a GPIO edge-triggered interrupts to be defined on rising, falling, or both). In the interrupt I start a timer upon the rising edge, and stop the timer upon the falling edge. And there you go! I now have the length of the echo received. From here it’s a matter of a simple calculation to know the distance Mr. Merf is sensing.
For a microcontroller to work with a motor, and rotate it clockwise and anti-clockwise directions, we need an H-bridge.
“An H bridge is an electronic circuit that enables a voltage to be applied across a load in either direction. These circuits are often used in robotics and other applications to allow DC motors to run forwards or backwards.”
This fellow was harder to connect to the breadboard than the ultrasonic (which only has 4 pins: VCC, ground, trig and echo), because it needs 2 VCC, 4 grounds connections and 3 GPIO pins for operation one motor. Talking about needy!
To make a motor rotate at different speeds (and directions) we need to connect it to the H-bridge and supply the H-bridge with 3 inputs:
- Enable pin should receive a logic 1 for the H-bridge to be enabled
- 2 PWM inputs: one receiving a signal and the other is 0, or the other way around, for rotation in the opposite direction.
So the motor driver receives velocity as an inputs and “translates” it to a PWM duty cycle given to the H-bridge input pins in the following matter:
- Velocity 0 means stop working, disable both PWMs and send 0 on the enable pin.
- Positive velocity is one rotation direction
- Negative velocity is the opposite rotation direction
- The value of the velocity is the percentage of duty cycle
Only problem is: how can I know it works? I don’t have an oscilloscope to test the signals.
But I do have LEDs! It’s not the most precise way test the PWM signals but it’s better than nothing.
I connected 2 LEDs each corresponds to another PWM, and I could see them dimming in and out when the duty cycle of the PWM changed.
In the video you can see the two different LEDs representing the two walking directions: green is going forward, yellow is going back:
The TivaWare-C driver library includes FreeRTOS files that you can embed in you program for the benefit of synchronization.
The use on an OS in the this project will allow running the ultrasonic driver asynchronously, not blocking the motor and the controller modules from doing their jobs while waiting for the echo interrupt to occur.
This is also good for future additions to the Mr. Merf project: additional sensors and motors may be added, controller may become more complicated.
So the way to use use the scheduler of the FreeRTOS is to define tasks. Each task runs separately and the context switch occurs on each SysTick. Upon a context switch the scheduler chooses another task from the unblocked queue if it’s priority is equal or higher than the priority of the task currently performing.
After struggling with this for a while, I’ve been able to run two separate tasks that do nothing other than count the number times each one was run by the OS.
Now I knew how to create and run tasks. So the next time I create the tasks needed by my program I know I’ll have less to worry about.
The brains behind it all!
The main functionality of the controller is to get the distance measured by ultrasonic driver, and decide on the velocity to set to the motor module.
For now the controller is pretty straightforward. It only has 3 options to choose from:
- Go forward
- Go backward
This is implemented using a state machine with the following switching conditions:
It is also important to notice that motors should be treated nicely. And being the gentle creature that they are, you should not change the voltage they are receiving abruptly. Therefore a transient is needed to change the PWM duty cycle (the velocity) from moving the motor in one direction to the other or to bring it to a full stop.
Combining everything together
By this point I had almost everything I need. All it needed was some wrapping up.
As I mentioned, I wanted all my program to run with the FreeRTOS scheduler, and for that all the functions that need to be performed should be wrapped in the task form.
The controller task and the motor task only call the corresponding already existing functions.
I decided to add some additional code to the ultrasonic task to make the distance it calculates more reliable. While I was playing around with the ultrasonic driver I noticed that it gave some unsteady outputs when the object in front of it moved fast. To smoothen the outputs and make them less affected by these spikes, I included a buffer. It’s a cyclic buffer (new data overwrites the oldest) of 5 (for now) measurements, and the distance reported by the driver is the median value of those 5.
One last step: the tasks need to pass data to one another via 2 parameters: distance and velocity.
To get the tasks to pass this data, a getter and a setter were added. The ultrasonic module has a Get function, so it can present its calculations to the world. The motor module has a Set function, that an external task can write the required velocity to.
And that’s it!
A first version of Mr. Merf is ready to go (and not bump into stuff).
You can find all the code of this version on my Git account:
- Adding another motor so that Mr. Merf can also turn, and just walk back and forth.
- Adding a sound playing component so he can also have some vocal response to the world
Some useful and inspiring links: