Posts Tagged PIC
Distance scanner using servomotor and distance sensor
In my previous post we got a servomotor doing what we want, so now it is time to put it to use! We will mount a Sharp GP2YOA distance sensor on top of the servo, so we can measure the distance to obstacles at different angles. We can then mount this sensor-servo combination on a robot to give it a good overview of the environment!

The hot glue gun!
I read a lot about robotic projects online, and I have several books about the topic. The coolest tool present in all of those is without competition the hot glue gun
.. A few months ago I was in a hobby store and came across one by accident so I bought one. Though it is not as spectacular as I had hoped for, it certainly is really handy to glue things together like lego and sensors.
First I glued a Lego piece on the sensor:

The hot glue gun, the servo and the lego
The image below shows how the component is glued to the sensor. Note the piece of cardboard to protect the electronics from the glue (though I don’t think it would hurt the electronics, I didn’t want to take the risk :p)

We will also glue a piece of Lego to the servo:


Jop, it's a bit messy
Now we can just plug the sensor Lego piece into the servo Lego piece, et voilà!

This already looks a bit like a robot..
The code
The hard bits are already done in past projects:
So now it is just a matter of putting the two together.. I’ve put the code in a file called scanner.c. The scanStep() function will move the sensor one step (in this example 2°) and measure the distance. It will then send the current angle and distance value on the COM port using the format D,[angle],[distance].
#include "scanner.h" #define SCAN_RESOLUTION 2 //measure distance every 2° short servoDir = 0; //0 = clockwise / 1=ccw int distances[180/SCAN_RESOLUTION+1]; /** * Moves the servo from left to right and back (one step per call) **/ void moveServo() { static short servoAngle = 90; short oldAngle = servoAngle; if (servoDir == 0) { //clockwise servoAngle+=SCAN_RESOLUTION; if (servoAngle>=180) { servoDir = 1; //servoAngle = 0; } } else if (servoDir == 1) { //counterclockwise servoAngle-=SCAN_RESOLUTION; if (servoAngle<=0) { servoDir = 0; } } setServoAngle(servoAngle); //give servo some time to reach goal angle if (oldAngle>servoAngle) { Wait_Ms(20*(oldAngle-servoAngle)); } else { Wait_Ms(20*(servoAngle-oldAngle)); } } void scanStep() { int distance = 0; int angle = 0; moveServo(); //move servo 5° further angle = getServoAngle(); distance = readLightSensor(0); //read distance at this angle distances[angle/SCAN_RESOLUTION+1] = distance; fprintf (_H_USART, "D,%i,%i\n",angle,distances[angle/SCAN_RESOLUTION+1]); }
Now we want to plot these values in Matlab. This is done using the following code. First we open the COM port and wait for data to arrive. We then put the data in an array B, where the position in B determines the angle the measurement was made at. We then plot these values so our plot resembles the directions the measurements where made at.
function [B] = sensorPlot2()
COMPORT = 4;
SCAN_RESOLUTION = 2; %make sure this matches SCAN_RESOLUTION in embedded code!
%open com port
s2 = serial(['COM' num2str(COMPORT)],'BaudRate',19200);
fopen(s2);
s2.ReadAsyncMode = 'continuous';
%open plot window
colordef none
h=figure('Color',[0.3 0.3 0.3]);
%init values
quit=0;
paused=0;
B = zeros(180/SCAN_RESOLUTION+1,1);
theAngles = (1:length(B))*SCAN_RESOLUTION*pi/180; %we will plot values on these angles
try
while 1
while ~s2.BytesAvailable %wait for samples to become available
pause(0.02);
end
if s2.BytesAvailable
try
res1 = dataFromResult(fscanf(s2)); %read the angle and distance value into res1 = [angle, distanceValue]
res = res1(2); resAngle = res1(1);
catch
res=[];
display('something went wrong!');
end
samplesRead = size(res,1);
if samplesRead>0
indexB = resAngle/SCAN_RESOLUTION+1;
if indexB>0 && indexB<=180/SCAN_RESOLUTION+1
B(round(indexB)) = res;
plotVals = [(1000-B).*cos(theAngles') (1000-B).*sin(theAngles')];
plot(plotVals(:,1),plotVals(:,2),'-.');
hold on;
plot(plotVals(round(indexB),1),plotVals(round(indexB),2),'-gO');
hold off;
xlim([-1000 1000]); ylim([-100 1000]);
pause(0.000002); %so the plot is updated
end
end
end
end
catch ME1
ME1.message,ME1.stack,ME1.cause,fclose(s2);delete(s2);
end
try
fclose(s2);delete(s2);clear s2
end
colordef white;
%% converts the result to a numeric row(kabraeck)
function [ data ] = dataFromResult( result )
remain = result;
index=1;
tokens=[];
while (~isempty(remain))
[token,remain] = strtok(remain, ',');
if (index>1)
tokens(index-1)=strread(token);
end
index=index+1;
end
data = tokens;
end
end
The image below shows an example plot Matlab generates:

The green dot indicates the current measurement
You can see that there is an obstacle on the left of the robot.
Below are two videos that are perhaps more illustrative:
Code download
You can download the complete code here. This is an Eclipse project (see my other article on how to use Eclipse for PIC development), but you can import the .c and .h files into MPlab if you like. Note that this project assumes to be loaded onto the PIC with an USB bootloader (see this article for details)!
Add comment May 9, 2009
PIC servocontroller (in C)
In this article I’ll explain how to control a simple servo motor from a PIC18F4455 microcontroller. I am using a real cheap servo (an ES-30, see Conrad site), but it should be enough for hobby (read: robot) purposes.
Servo Controller
A DC motor is controlled using a DC voltage, but a servo motor requires some more work as it is controlled using pulses. By varying the width of a pulse you can set the angle the servo motor has to turn to. A servo motor can usually turn from -90 degrees to +90 degrees, but my ES-30 seems to be limited to -70 to +70 degrees or so..
Connections
The servo motor has three connections: ground (black), supply voltage (red) and the connection for the input pulses (usually yellow). We will connect the black wire to ground, the red one to our PIC supply voltage (5V) and the yellow wire to the D3 output (PORTDbits.RD3). So D3 will be the PIC output pin that controls the servo.

Pulses
The servo expects a pulse every 20ms. The width of this pulse varies in the range 1.0 – 2.2ms, this range could be different with your specific servo so consult the datasheet (or just try some values)! A pulse width of 1.0ms sets the servo to the far left, a pulse of 2.2ms to the far right, and everything in between should map on an angle somewhere in between.
Timing with the PIC uC
We are going to use interrupts to ensure our pulses appear every 20ms. A timer interrupt happens when the timer register overflows. The timer register (can be configured as 8bit or 16bit) is increased on every clock tick. If the prescaler is set it happens less than every clock tick. A spreadsheet with my calculations is available at http://spreadsheets.google.com/pub?key=p9YPS93eEHH3W7dx5fxQEMQ&output=xls, you can see the interrupt rate for various settings of the prescaler value.
You can enable the interrupts like this:
OpenTimer0(TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_1_4); //enable TMR0, 16bit, CLK0 src, low-to-high trans, prescale on, prescale 1:4
So your servo initialization will look like this:
void startServo(void) { //initialize TIMER0 + enable interrupts
TRISD = 0; //D is output
PORTD = 0;
INTCONbits.RBIF = 0;
INTCONbits.TMR0IE = 0;
RCONbits.IPEN = 0;
OpenTimer0(TIMER_INT_ON & T0_SOURCE_INT & T0_16BIT & T0_PS_1_4); //enable TMR0, 16bit, CLK0 src, low-to-high trans, prescale on, prescale 1:4
INTCONbits.GIE = 1; //enable global interrupts
INTCONbits.PEIE = 1; // enable peripheral interrupts
}
Define the interrupt function like this:
#pragma interruptlow timerFtie
void
timerFtie(void) {
if (INTCONbits.TMR0IF) { //interrupt timer 0
INTCONbits.TMR0IF = 0; //interrupt flag off
servoInterrupt();
}
}
Now we only need to define what will happen inside the servoInterrup() function, i.e. the function that is called every time TIMER0 overflows. We will set D3 to the correct value (1 or 0) depending on whether the pulse is starting or ending. We will also initialize TMR0H and TMR0L to values so that the next overflow appears when a pulse needs to start/stop. This is explained in the following note:

This results in the following code:
void servoInterrupt(void) { //called on overflow of TIMER0
//create pulse (begin or end of pulse)
PORTDbits.RD3 = (pulseOn == 1);
//set new TIMER0 value
if (pulseOn == 1) {
pulseOn = 0;
TMR0H = 0xFF & (pulseOnLoad >> 8);
TMR0L = 0xFF & pulseOnLoad ;
} else {
pulseOn = 1;
TMR0H = 0xFF & (pulseOffLoad >> 8);
TMR0L = 0xFF & pulseOffLoad;
}
}
PulseOnLoad and PulseOffLoad are set according to the servo angle:
void setServoAngle(short angle) { //set new servo value (called from external code)
short loadTimer0BeginPulse = 0;
short loadTimer0EndPulse = 0;
short usPulse;
short timerCount; // [2727,6363] =~ [900,2100]*3
servoAngle = angle;
usPulse = MIN_PULSE_DURATION + angle*((MAX_PULSE_DURATION-MIN_PULSE_DURATION)/180);
timerCount = usPulse * 3; //0.33us = 1/3 us per tick
pulseOnLoad = 65534 - timerCount+2;
pulseOffLoad = 5538 + timerCount +2;
}
Code download
You can download the complete code here. This is an Eclipse project (see my other article on how to use Eclipse for PIC development), but you can import the .c and .h files into MPlab if you like. Note that this project assumes to be loaded onto the PIC with an USB bootloader (see this article for details)!
References
- This site gives a very thorough introduction to using a servo with a PIC12F675, though all code is not freely available. My logic is also a bit different: I don’t wait inside the interrupt routine untill the end of the pulse but I set it low using a second interrupt.
- http://www.mcmanis.com/chuck/robotics/projects/servo.html gives another introduction to using the servo with a PIC, the code is in assembler.
- The PIC datasheet, chapter about TIMER0.
1 comment May 2, 2009
Poor man’s virtualization (a rich experience!)
As computers are becoming more and more powerful, a mere laptop is able to virtualize complete computer systems. With technology like VMWare and Sun’s Virtualbox one can create so-called virtual machines that have an entirely different setup (hardware / operating system) than the host system. As I am finding myself using virtualization more and more, I decided to write an article about it. I won’t be giving an in depth overview of all available technologies and setup tricks, but an overview of how I am using it today. Furthermore, this article will only focus on freely available virtualization software.
A microcontroller development station (Virtualbox)
When looking for a free solution, Virtualbox is the obvious choice as it is available as open source software (GNU GPL) . Just download it from their site (it is available for a myriad of host systems: Win/Linux/Mac/Solaris) and install it to your computer.

I have recently formated my laptop and I am intending to keep it clean and uncluttered for a while. That’s why I decided to put all software and tools needed for my microcontroller activities in a dedicated virtual machine.
The setup:
The host system is my personal laptop I bought a year ago (core 2 duo 2GHz, 2GB RAM, Windows Vista). The guest operating system is a Windows XP machine. I chose XP because it runs faster than Vista and I didn’t need any of the Vista features. Make sure you install the Virtualbox guest tools on your guest system for optimal performance.
The bright side:
- No polluting of my host environment by all the software needed for my PIC (that’s the microcontroller) programming, as it is contained in the virtual machine: compiler, two IDE’s (Eclipse and MPLAB), programming tools, …
- All my projects and documentation (datasheets, user guides, …) are available in the virtual machine.
- I can backup the virtual machine so the software setup and my projects are safe.
- When I have to format my host environment again, I won’t have to reinstall all the microcontroller software and find my projects back. I’ll just have to reinstall Virtualbox and put the virtual machine back.
- I only have time in my weekends for this microcontroller hobby. At the end of my weekend I just save the state of my virtual machine (I just leave all windows open) and at the beginning of the next weekend I can pick up exactly where I left off!
- I usually work with a dual monitor setup (laptop screen + external monitor). It is possible to put the Virtual machine on one monitor and on the other monitor just work in the host operating system.
- A shared folder allows to share files between the host and guest system.
- My host is a Vista machine, but it could as well have been a Linux OS, thus giving a solution to hardcore Linux users wanting to program PICs (the Microchip compiler is not available on Linux).
The dark side:
- As everything is virtualized, things tend to run a tad slower. I don’t find this annoying while developing (it doesn’t require a fast PC), but you wouldn’t want to run games in a virtual machine!
- For the actual programming of a PIC microcontroller, I use a USB device. It is possible to forward the USB device to the virtual machine so it is recognized over there, but I found this to be rather buggy in Virtualbox (it crashed a few times). So for the actual programming I still use the host system.
Conclusion:
Virtualbox is really, really cool software. I almost can’t believe something like this is just available as open source software. It is ideal for quickly testing some new software / platform or for separating a certain environment from the rest of your system (as I did for my microcontroller environment).
A research platform (VMWare server)
At work we are constantly testing new setups and trying out new technologies. We also have some powerfull servers, but we prefer to do our tests in a vacuum environment (not influenced by other installed components we might not have thought about). That’s why we decided to put VMWare on our server and run our little test setups inside Virtual Machines.
![]()
VMWare offers a lot of products, most of which are paying solutions. They do however offer a free player and a free server virtualization product: VMware Server. The player can be used to run an existing virtual machine on your desktop machine. Vmware Server is a very powerfull solution for creating / managing / running virtual machines on the server. Creating virtual machines is done in a browser application which is really handy. By installing the VMware console plugin one can remotely take over the screen of a virtual machine and run it as you would run a local virtual machine.
The setup:
The actual installation is described over here by my colleague. We installed VMware Server on a Linux host system (2 quad cores and 32GB RAM) [sidenote: I think VMWare Server can only be installed on a Linux host]. Once installed you can open up Firefox on your client computer and point it to port 8333 of your host computer. You should see a login screen. I advise you to use Firefox2 Portable because the console plugin doesn’t work too good with Firefox3. Below are some screenshots of the browser application:

Overview of the available virtual machines and details of one of them

Creating a new virtual machine

Remotely taking over a virtual machine
More setup goodness:
I’m not going into details about the actual setup but I’ll give some pointers to what is possible:
- Configure the dhcp to asssign static IP adresses to your virtual machines. Put an apache http server on your host machine and use proxypass / proxypassreverse / virtualhost to forward a browser to a virtual machine. I.e., we can point the client browser to a url like http://hudson.dunamis, our client host file says that hudson.dunamis is found at the IP adress of our host system so our call is forwarded to the host. The apache http server on the host system has a configuration that says that hudson.dunamis is to be forwarded to the local IP of the virtual machine to a certain port. So the client is immediately forwarded to the virtual machine, as if it is connected to the actual network.
[sidenote: you could also use the bridged network setup of VMware for this, but this wasn't possible in our setup] - In this way you can also forward your ssh access: checkout jedi.
The bright side:
- Once set up, it becomes very easy to create new machines. By copying the vmdk (=virtual harddrive) of another machine you can skip the installation of the operating system and focus on what you really want to test.
- The different machines can access each other via the network so complex setups are possible.
- It is possible to copy and paste virtual machines. E.g. you can also create virtual machines locally using VMware Desktop (this is a paying solution) and copy them later to the server. You can also grab a machine from the server and play it locally using VMware player.
- You can make a snapshot (or just copy) virtual machines so you can return to a certain state later.
The dark side:
- Because we have to work with the NAT networking setup, it is sometimes difficult to get things running that have to communicate with machines outside the virtual domain..
Conclusion:
This is ideal for a research environment where you have to test all sorts of different setups. Creating and deleting virtual machines is really easy and succesful setups can be copied so you can always return to them.
Add comment April 24, 2009
Serial com-port communication with autoIt
This weekend I found out how to read from / write to a com port with autoIt code. I created a file with some functions that read/write single characters or lines. To communicate with a com port, I use the CreateFile function from Kernel32.dll.
Continue Reading 5 comments December 7, 2008
PIC18F4455 USB Bootloader
This week I’ve put the USB Bootloader on my PIC experimental board. A bootloader allows you to program the PIC uC without a programmer. More info about using the bootloader can be found on this site. This post addresses some problems I had with the bootloader.
Continue Reading 2 comments November 29, 2008
Scope with PIC microcontroller and Matlab
After many trials I recently succeeded in using the serial connection for communication between my PIC experimental board (based on a PIC18F4455) and my laptop. Turned out I was configuring my UART wrong, but now it works. I’m very happy about this because it is very useful for debugging my robot controller. I wrote a script in Matlab to read out the sensorvalues from the COM port and plot them in some sort of scope-window. The result looks pretty cool!

Continue Reading 34 comments June 23, 2008