This is my project submission for the Crossover Code Challenge by NXP. It is an example rover
platform that can be controlled using your smartphone – from anywhere in the world.
You also get a live video feed to help you navigate and it also uses an ultrasonic sensor
along with a stepper motor to map the surroundings. This video is going to be very different from
my regular videos but many of you might want to work as an electronics or embedded systems
engineer in a professional environment and in that case, you would use microcontrollers
similar to this one and you will have to use a similar development IDE to write code for
it. Before we look at the project in detail, let’s talk about the challenge and the microcontroller
platform that is being used.
The challenge was extremely simple – you had to use the i.MX RT1010 development board
and write useful code for it. If you are not familiar with the products from NXP then i.MX
is one of their 32-bit and 64-bit ARM processor range. Within that, you have the RT series
which is the range for their current microcontroller offerings. The RT1010 is just one of their
microcontrollers. As you can see, you have several other microcontroller families going
up to 1GHz and which also support things like display interfaces, camera interfaces, high
performance RAM and so on.
In comparison, the RT1010 runs at 500MHz and is much simpler but it is still far ahead
from most other microcontrollers that are commonly used. The best part is that it costs
less than a dollar at volumes. It also uses an 80 pin LQFP package which greatly simplifies
the PCB design. I will not talk about all the features as you can view this page for
more information.
The board itself is pretty simple, you have the main microcontroller and since it does
not have internal program memory, we also have an external flash chip to store the program.
The microcontroller requires a single 3.3V power supply so we do have on-board voltage
regulation. Apart from that, we have Arduino shield compatible header pins, an onboard
audio codec which allows you to obtain audio samples from the on-board microphone and also
play sound through the headphone jack. The board also has the footprint for an additional
audio IC along with a motion sensor, but these are not populated can hence cannot be used.
Finally, we have the on-board debugger section which is extremely useful when working with
these types of microcontrollers.
Here’s what the prototype looks like, I will take it apart later on in the video and
you will get a closer look at everything, but for now – we have the development board
here, along with a custom protoboard that houses the motor drivers, logic level conversion,
WiFi module and voltage regulator. I’m obviously using two geared DC motors for the drive along
with a castor wheel. For mapping, I am using an off the shelf ultrasonic sensor that is
attached to a slip ring. In order to map the surroundings, we need to rotate the ultrasonic
sensor, however, we do not want to twist the wires and that is why we use a slip ring.
The ultrasonic sensor works at 5V while the board can only accept 3.3V and this means
that we need to carry out some voltage level shifting. The trigger pin is an input to the
ultrasonic module which means that we could directly connect a 3.3V signal to it and that
is what I am doing. The echo pin is an output which needs to be converted to 3.3V.
You could use a voltage level shifter like this one but I decided to keep it simple by
using 3 10K resistors which act as a voltage divider. When 5V is present at the input,
the output will be 3.3V which is perfect for our needs.
A stepper motor is used for precise control over the rotation and I’ve 3D printed some
gears to link the two. These 3D printed parts were obtained from thingiverse and they did
not exactly fit the parts I was using so I held them in place using hot glue. Finally,
we have the ESP32-CAM board that captures the video feed. This is a standalone board
and it only uses power from the main board.
Here’s a block representation of the entire project. Since the RT1010 does not have wireless
connectivity, I am using a WeMos D1 mini board to enable remote control. The motor drivers
are custom boards that use the DRV8847 motor drivers from Texas Instruments. I will share
the schematics in the written post, if you would like to replicate this. I am powering
it all using a 9V battery but you can obviously upgrade this to a LiPo for extended battery
life. Everything else is pretty simple on the hardware side so let’s take a look at
the code before we test it.
Just as you would use the Arduino IDE to write code for an Arduino board, you would use the
MCUXpresso IDE write code for this board as it is the recommend tool. This is what it
looks like and it might be familiar to some of you as it is based on Eclipse which itself
is a very popular tool. If you have only worked with Arduinos then what I am about to show
you will look very complicated, but it is actually not that difficult and in fact there
are several tools to help you.
When you write code using an Arduino IDE, you are using a high-level language that was
designed to make it extremely easy for you to write code.
Take this code for example, we simply blink the onboard LED every second.
This code can run on an Arduino Nano, Uno, Leonardo or pretty much any other board because
somebody else has already written the libraries which take care of things for you. These libraries
will determine which settings have to enabled and so on. While this makes it extremely easy
for you write code, you give up something that is very important when you work in a
professional environment, and that is efficiency. If you want to get the maximum performance
from a board like this, then you will have to work at much lower level and write almost
all the libraries from scratch. Yes, it is not going to be as easy as working with an
Arduino but you can definitely have a lot more control over every single thing which
means that you can get a lot of performance as well. Somebody else could port all the
Arduino libraries over to this board but in my opinion, you would not be doing justice
as you will most likely not be able to maximize the capabilities of this board.
Take a look at this code, all that it is doing is blinking the onboard LED every second.
It is quite a lot when compared to the Arduino and that is because you have to set everything
including the internal clocks, configure the pin state and so on. Thank fully, manufacturers
provide example code to get started with almost all the peripherals. The software development
kit also comprises of several libraries that can be used to simplify the process. The thing
I like the most is this outline tab that lists important information about the file that
is currently open. You can then click the function that interest you to view more details
and learn how to use it. You can also view the low-level implementation of the same.
One more thing that is useful to note is that you can visually configure the pins by using
the pin config tool. You can select the different pins based on the peripheral and then set
the properties down here. Once done, you can click this option to generate the code and
configure the pins for you. You can also do the same for the internal clock signals and
this makes things much easier.
This is what the code for the project looks like. I like to create separate libraries
for each specific purpose so that’s the reason why I have several source files here.
This is the main file that calls all the different functions. We will look at the individual
files first and we will then look at this main file. First, we have the debug files
and this is nothing but driver for the serial port. It handles receiving and sending data
over the debug port which shows up as a COM port when you plug in the board. I created
two circular buffers – one for receiving and another for transmitting. Everything is
interrupt driven which makes it a bit efficient. Next we have the millis library which is similar
to the Arduino millis function. It simply returns the time, in milliseconds since the
board was powered ON. We then have the motor driver library which initializes 4 PWM pins
and takes care of the different navigation functions. The logic is extremely similar
to the motor driver library that we created in a previous video for the rover platform.
We then have the SR04 library which is written for the ultrasonic sensor module. We then
have the stepper library that is used to control the stepper motor. I have implemented a low-level
stepper driver that is similar to that used in the Arduino stepper library. Finally, we
have the timer library which is responsible for the delay functions as well as time keeping
functions that are used to determine the pulse width of the signal that is received by the
ultrasonic sensor. We have covered this in an earlier video and the pulse width represents
the distance between the ultrasonic sensor and the object in front of it.
There are three main things that are happening at any given point in time. We have the navigation,
mapping and video feed. I am using the Blynk APP to control the rover and view the video
feed along with mapping data. Let’s start by talking about navigation:
I decided to use a joystick for navigation to keeps things simple.
The XY position of the joystick is sent to the WeMos D1 mini board which then converts
this into the final action. I decided to map it to the different actions as shown on screen
and I used 3 GPIO pins to represent these actions. The NXP main board reads these GPIO
pins and them sets the correct PWM values for each of the conditions. And that is what
this Motor_UpdateState function does. It simply obtains the state of the GPIO pins and then
sets the appropriate PWM values. I have also defined several pre-processor directives to
help make changes. Here we have the GPIO state to final PWM action mapping along with the
PWM duty cycle values.
The video feed is actually the simplest as we are directly using the ESP32-CAM board.
We’ve looked at this in a previous video and all we’re doing is creating an MJPEG
stream that is then displayed in the APP.
When it comes to the mapping function, we need to do three things. We need to rotate
the stepper motor, trigger the ultrasonic sensor so that it sends the ultrasonic pulses
and finally, we need to wait to receive the echo signal before we can rotate the stepper
again and repeat the process. This is what the Mapping_Update function does. The distance
value is then finally sent over the WeMos D1 board and it is displayed on this virtual
terminal. This data can then be used to plot a map of the surroundings.
I have connected the data from the debug serial port to the WeMos D1 mini board so that we
can view the data within the app.
We have to call the initialization functions for each of these peripherals so that they
are set up correctly. Since I have used an interrupt driven serial port, I also need
to call the refresh function which simply enables the transmit interrupt if there is
pending data that needs to be sent out on the port.
One thing to keep in mind is that I only had a standard stepper motor with me which can
do a max rotation of about 15RPM at 5V which is suitable for this demonstration given that
I am also using 3D printed gears. You might want to use a different stepper to increase
the mapping speed and perhaps use bearings to make it smoother.
Please check the written post for the reference diagrams, code for both the RT1010 board as
well as the WiFi boards. I will quickly take it apart so that you can get a better view
of how it was put together.
These are the custom motor driver boards along with the WeMos D1 mini. I am then going to
free the add-on board from all the wires so that you can view the bottom section. It is
not my finest work but it certainly got the job done. We can then remove the ESP32-CAM
board by carefully releasing it from the hot glue. We can then carefully remove the additional
glue to free up the 3D printed add-on. I had used some double-sided glue to hold down the
stepper motor. As you can see, one half of the slip ring is glued in place while the
other is free to rotate. Since the mounts that I used were not of the same size, I used
some hot glue to hold it together. I do not think I will be able to salvage the slip ring
as the wires are pretty delicate and will most likely break. Finally, we are left with
the DC motors and the development board.
And there you have it, the very first video on this channel where I use a Cortex-M7 microcontroller
to do something useful. I do hope you liked this video and that you learnt something from
it. We will continue with our regular videos so do subscribe to stay updated if you haven’t
already. Thank you for watching and I will see you in the next one!