Friday, February 24, 2012

UART

UART – Universal Asynchronous Receiver and Transmitter

1.0 Introduction
The Universal Asynchronous Receiver/Transmitter (UART) controller is the key component of the serial communications subsystem of a computer. UART is also a common integrated feature in most microcontrollers. The UART takes bytes of data and transmits the individual bits in a sequential fashion. At the destination, a second UART re-assembles the bits into complete bytes. Serial transmission of digital information (bits) through a single wire or other medium is much more cost effective than parallel transmission through multiple wires. Communication can be "full duplex" (both send and receive at the same time) or "half duplex" (devices take turns transmitting and receiving).

2.0 The Asynchronous Receiving and Transmitting Protocol
Asynchronous transmission allows data to be transmitted without the sender having to send a clock signal to the receiver. In this case, the sender and receiver must agree on timing parameters (Baud Rate) prior transmission and special bits are added to each word to synchronize the sending and receiving units. In asynchronous transmission, the sender sends a Start bit, 5 to 8 data bits (LSB first), an optional Parity bit, and then 1, 1.5 or 2 Stop bits.
When a word is passed to the UART for asynchronous transmissions, the Start bit is added at beginning of the word. The Start bit is used to inform the receiver that a word of data is about to be send, thereby forcing the clock in the receiver to be in sync with the clock in the transmitter. It is important to note that the frequency drift between these two clocks must not exceed 10%. In other words, both the transmitter and receiver must have identical baud rate.
After the Start bit, the individual bits of the word of data are sent, beginning with the Least Significant Bit (LSB). When data is fully transmitted, an optional parity bit is sent to the transmitter. This bit is usually used by receiver to perform simple error checking. Lastly, Stop bit will be sent to indicate the end of transmission.
When the receiver has received all of the bits in the data word, it may check for the Parity Bits (both sender and receiver must agree on whether a Parity Bit is to be used), and then the receiver searches for a Stop Bit. If the Stop Bit does not appear when it is supposed to, the UART considers the entire word to be garbled and will report a Framing Error to the host processor when the data word is read. Common reason for the occurrence of Framing Error is that the sender and receiver clocks were not running at the same speed, or that the signal was interrupted.
UART Basic UART packet format: 1 Start bit, 8 data bits, 1 Parity bit and 1 Stop bit
Every operation of the UART hardware is controlled by a clock signal which runs at much faster rate than the baud rate. For example, the popular 16450 UART has an internal clock that runs 16 times faster than the baud rate. This allows the UART receiver to sample the incoming data with granularity of 1/16 the baud-rate period and has greater immunity towards baud rate error.
The receiver detects the Start bit by detecting the voltage transition from logic 1 to logic 0 on the transmission line. In the case of 16450 UART, once the Start bit is detected, the next data bit’s "center" can be assured to be 24 ticks minus 2 (worse case synchronizer uncertainty) later. From then on, every next data bit center is 16 clock ticks later.
uart receiver Data sampling point by the UART receiver
Transmitting and receiving UARTs must be set at the same baud rate, character length, parity, and stop bits for proper operation. The typical format for serial ports used with PC connected to modems is 1 Start bit, 8 data bits, no Parity and 1 Stop bit.

3.0 The Physical Layer Standards
So far, we have discussed the software protocol of the UART. How about the physical layer standards? There are actually quite a number of different standards that utilizes similar protocol. For instances, TTL level UART, RS-232, RS-422, RS-485 and etc. We will only discuss about TTL level UART and RS-232 in this article.

3.1 TTL level UART
Most microcontrollers with UART uses TTL (Transistor-transistor Logic) level UART. It is the simplest form of UART. Both logic 1 and 0 are represented by 5V and 0V respectively.

Logic
Voltage
Low
0V
High
5V
Voltage level for TTL level UART
The TTL level UART is commonly used in the communications between microcontrollers and ICs. Only 2 wires are required for the full duplex communications as illustrated in the picture below.
Between devices
 UART Communication Between 2 devices

3.2 RS-232
RS-232 (Recommended Standard 232) is a standard for serial binary data signals connecting between a Data Terminal Equipment (DTE) and a Data Communication Equipment (DCE). It is commonly used in computer serial ports. One of the significant differences between TTL level UART and RS-232 is the voltage level. Valid signals in RS-232 are ±3 to – ±15V, and signals near 0V is not a valid RS-232 level.
Logic
Voltage
Low
+3 to +15V
High
-3 to -15V
Voltage level for RS-232
722px-Rs232_oscilloscope_trace.svg RS-232 voltage level for data 0x4B with 1 start bit, 8 data bits and 1 stop bit
Besides voltage level, the RS-232 also has a few extra pins specifically designed for the communication between PC and modem. The pinouts of the DB-9 and their functions are shown below.
pinouts.serial Pinouts of a serial port
Name
Pin
Description
Transmitted Data (TxD)
3
Serial data output
Received Data (RxD)
2
Serial data input
Request to Send (RTS)
7
This line informs the DCE (Modem) that the DTE (PC) is ready to exchange data
Clear to Send (CTS)
8
This line indicates that the DCE is ready to exchange data
Data Terminal Ready (DTR)
4
Asserted by DTE to indicate that it is ready to be connected
Data Set Ready (DSR)
6
Asserted by DCE to indicate the DCE is powered on and is ready to receive commands or data for transmission from the DTE
Data Carrier Detect (DCD)
1
Asserted by DCE when a connection has been established with remote equipment
Ring Indicator (RI)
9
Asserted by DCE when it detects a ring signal from the telephone line
Pinouts and description of a serial port

4.0 Interfacing between TTL level UART and RS-232
From previous discussions, we know that microcontrollers make use of TTL level UART while the PC serial port uses RS-232. Since both standards uses similar software protocol, both of them are able to communicate via UART. However, because of the differences in voltage level and polarity, we will need a level shifter to interface the TTL level UART with the RS-232. Nowadays, this can be easily done with the commonly available IC such as the MAX232 from Maxim.
RS232-UART Example of interfacing microcontroller to PC serial port

5.0 Summary
In short, UART is the simplest form of communication between microcontroller and PC. However, due to the mushrooming growth of technology, serial port is slowly being replaced by other means of communication port. Nevertheless, serial communication is still possible even without a physical serial port on your PC. For example, the USB can be treated as a serial port after the signal from microcontroller is converted using the USB to RS-232 converter. In order to gain more understanding on this converter, feel free to refer to the USB to UART converter (UC00A) from Cytron as it is a readily available device that provides communication between UART and USB via the USB to RS-232 converter. If you have any inquiry, please do come to our technical forum to discuss :)
UC00A - 1 USB to UART converter (UC00A) from Cytron.

Conventional Com
Conventional way of interfacing microcontroller to PC via serial port

Via RS232 Converter Interfacing microcontroller to PC via USB to RS-232 Converter


Via UC00A Interfacing microcontroller to PC via USB to UART Converter (UC00A)

How servo motor Works

How RC Servo Works?

Since many students and hobbyists are using RC servo in their projects, let’s take a look at the RC servo (servos for short). The purpose of this information is to give an overview of how servos operate and how to communicate with them.

What is Servos? 
Radio Control (RC) hobby servos are small actuators designed for remotely operating model vehicles such as cars, airplanes, and boats. Nowadays, servos are becoming more popular in robotics, creating humanoid robot, biologically inspired robot, robotic arm and etc. This is because its size is small when taken into consideration the built-in circuitry. Moreover, its ability to rotate and maintain at certain position or angle according to control pulses from a single signal wire also make servo motor popular in robot building. Inside a typical servo, it contains a small motor and gearbox to do the work, a potentiometer to measure the position of the output gear, and an electronic circuit that controls the motor to make the output gear move to the desired position. This is the “servo system” which will be elaborated in the next section. A servo has three wires; for power (+5V), ground and the signal wire. Since all these components are packaged in a compact, low-cost unit, servos are great actuators for robots.

Servo System 
Servos are controlled by sending them a pulse of variable width. As long as the signal pulse exists on the signal line, the servo will maintain the angular position of the shaft after it has rotated to that position. As the signal pulse changes, the angular position of the shaft will change. This works because of the servo system which makes the servo motor so famous against other actuator. In practical terms, servo means that you can set and forget, and it will adjusts itself during continued operation through feedback.

A servo motor consists of several main parts; the motor and gearbox, a position sensor, an error amplifier and motor driver and a circuit to decode the requested position. Photo below contains a block diagram of a typical servo motor unit.
Block Diagram of a typical RC Servo motor

The radio control receiver system (or other controller) generates a pulse of varying length approximately every 20 milliseconds. The pulse is normally between 1 and 2 milliseconds long. The length of the pulse is used by the servo to determine the position it should rotate to. The control pulse is fed to a pulse width to voltage converter. This circuit charges a capacitor at a constant rate while the pulse is high. When the pulse goes low the charge on the capacitor is fed to the output via a suitable buffer amplifier. This essentially produces a voltage related to the length of the applied pulse.
The circuit is tuned to produce a useful voltage over a 1ms to 2ms period. The output voltage is buffered and so does not decay significantly between control pulses so the length of time between pulses is not critical. The current rotational position of the servo motor output shaft is read by a sensor. This is normally a potentiometer (variable resistor) which produces a voltage that is related to the absolute angle of the output shaft.
The potentiometer then feeds its current value into the Error Amplifier which compares the current position with the commanded position from the pulse width to  a voltage converter.
The error amplifier is an operational amplifier with negative feedback. It will always try to minimize the difference between the inverting (negative) and non-inverting (positive) inputs by driving its output in the correct direction. The output of the error amplifier is either a negative or positive voltage representing the difference between its inputs. The greater the difference, the greater the voltage. The error amplifier output is used to drive the motor. If it is positive the motor will turn in one direction and if it is negative, it will turn to another direction. This allows the error amplifier to reduce the difference between its inputs (thus closing the negative feedback loop) and so makes the servo goes to the commanded position.

Servo Command 
Servos are controlled by sending them a pulse of variable width. The signal wire is used to send this pulse. The parameters for this pulse are that it has a minimum pulse, a maximum pulse, and a repetition rate. Given the rotation constraints of the servo, neutral is defined to be the position where the servo has exactly the same amount of potential rotation in the clockwise direction as it does in the anti-clockwise direction. It is important to note that different servos will have different constraints on their rotation but they all have a neutral position, and that position is always around 1.5 milliseconds (ms).

Continuous Pulses to RC servo
The angle is determined by the duration of a pulse that is applied to the signal wire. This is called Pulse Width Modulation. The servo expects to see a pulse every 20 ms. The length of the pulse will determine how far the motor turns. For example, a 1.5 ms pulse will make the motor turns to a 90 degree position (neutral position).
When these servos are commanded to move, they will move to the position and hold that position. If an external force pushes against the servo while the servo is holding a position, the servo will resist from moving out of that position. The maximum amount of force the servo can exert is the torque rating of the servo. Servos will not hold their position forever though; the position pulse must be repeated to instruct the servo to stay in position.
When a pulse is sent to a servo that is less than 1.5 ms the servo rotates to a position and holds its output shaft some number of degrees anti-clockwise from the neutral point. When the pulse is wider than 1.5 ms the opposite occurs. The minimal width and the maximum width of pulse that will command the servo to turn to a valid position are functions of each servo. Different brands, and even different servos of the same brand, will have different maximum and minimum. Generally the minimum pulse will be about 1 ms wide (some servos iare 0.5ms) and the maximum pulse will be 2 ms wide (some servo are 2.5ms).

Position of RC servo with the signal
Another parameter that varies from servo to servo is the turn rate. This is the time it takes for the servo to change from one position to another. The worst case turning time is when the servo is holding at the minimum rotation and it is commanded to go to maximum rotation. This can take several seconds on very high torque servos.


Controlling a servo motor with Microcontroller
Before writing a program to control the servo, we must first get ready the circuit. As mentioned before, servo has 3 wires; each wire should be connected as shown in the sample schematic below.

Sample circuit to control RC servo
In order to control the servo motor, we must be able to generate a pulse approximately every 20ms although the actual time between pulses is not critical. The pulse width however must be accurate to ensure that we can accurately set the position of the servo. There are a few methods in writing the signal pulse for servo.

Delay Routine
This method is the easiest and the simplest way to control the servo. It is suitable for beginners who are just about to learn the servo. The algorithm is easy; first, the output pin of servo is set to high, and then waits for the time you want the servo to rotate, for example, wait for 1.5ms to let the servo be at the neutral position. After 1.5ms, output pin of servo is set to low for 20ms-1.5ms which is 18.5ms so that the total period is 20ms. Repeat the step to get the continuous pulse. After a while, if you intend to rotate the servo to other position for example 180 degree, then you should repeat the step with the delay 2ms (depends on servo spec) after setting the servo pin to high and delay 18ms after the servo pin goes low.
                                                 
Sample code of controlling RC servo using delay
The servo will continuously rotate from 90 degree to 180 degree and vice versa according to the program. This is only the main part of the program. The whole set of program including the delay subroutine is not provided as it only illustrates how the servo works.

PWM

The continuous signal pulse for servo can actually be regarded as PWM (Pulse Width Modulation) where the frequency is 50Hz and the duty cycle is from 5% to 10% (1ms/20ms to 2ms/20ms). Many microcontrollers are equipped with PWM generators and most people initially consider using these to generate the control signals.Unfortunately they are not vey suitable. The problem is we need a relatively accurate short pulse then a long delay; and generally you only have one or two PWM generator, as a result you only can control one or two servos unless you use switching components outside the microcontroller to share with several servos and these will complicate the hardware. The PWM generator is designed to generate an accurate pulse between 0% and 100% duty cycle, but we need something in the order of 5% to 10% duty cycle (1ms/20ms to 2ms/20ms). If a typical PWM generator is 8 or 10 bits, then we can only use a small fraction of the bits to generate the pulse width we need and so we loose a lot of accuracy and the resolution would become worst. 

Timers 

Another way of controlling servo is by using timer interrupts. This way is more beneficial as you need not waste time waiting for the delay routine. The timer is configured so that you have plenty of accuracy over the 1 to 2 millisecond pulse time. You only need to set the timer to interrupt for the time you want, and then drive the servo pin either to high or low at the suitable interrupt’s time routine. For example, first you drive the servo pin to high and configure the timer to interrupt at the next 1ms. When the interrupt is executed at 1ms, you drive the servo pin to low and configure again for the timer to interrupt at next 19ms in order to get a complete 20ms period which most servos required. Repeating this cycle will generate a continuous pulse for servo. By doing this, you save a lot of time! While waiting, you can do other thing like processing your input. This method makes your project more effective. In order to control more servos, you can run a timer at a faster rate and do a single servo at a time, followed by the next and the next etc. Most of the servo controller projects use this approach

We hope this article will help you to understand a servo motor. Have fun!

HACKING ATX Power Supply

Hacking ATX Power Supply?

OK, before going further, I need to inform you that we do not take responsibility on your safety and guarantee anything as this is hacking and it deal with AC power source. You will need to take your own risk and be careful with what you are doing.



Oh, you wanted a power supply that can give you 5A of 12V source? But most of AC to DC adapter is rated at 2A or less only, higher current output will cost you a lot. Normally you might go for switching power supply like this:
Switching_Power_Supply
Here is an alternative. For armature hobbyist, they will hack the computer desktop power supply. Yup, it is actually a switching power supply dedicated for computer motherboard. You can buy it from computer shop, I am pretty sure they have it on rack. We are going to utilize it as the power source for our project and development. ATX power supply, come with high current output and stable voltage. It has 3.3V, 5V, 12V and –12V (you might not use it). As you might have notice, 12V and 5V is commonly use by embedded electronics to power microcontroller, stepper motor, DC motor, sensor, magnetic lock, you name it. Let me leave the current rating at the back. Now if you go to Wikipedia and search for ATX, which you will reach here, it actually explained quite comprehensive pin-outs and features of this power supply. Because most motherboard will have standard connector, all ATX power supply must be compliant with this standard. You can hack it like this example:
awesomeBut you will need to figure out the wirings and get yourself proper connector, not to forget the drilling of holes to mount the connectors. Worst is you cannot use back for computer once the connecters and wires are cut and modified. Good for you that we have come out with a Breakout Board for ATX power supply, it will enable you to utilize ATX power supply in just 10 minutes of setup.
OK, get yourself these item:
1. ATX Power Supply, you should be able to grab one from computer shop. I am not sure whether Cytron have it, but by the time I write this, we do not carry any :)
2. BB-ATXRA, the breakout board for ATX power supply from Cytron.
3. You might want to get the terminal block too, or header pin? Or turn pin? Is up to you. I will show all the connection, but I use the terminal block.
4. PCB stand, or sometime called spacer. I am using 10mm PCB Stand S/S.
5. AC Power cord, most of ATX power supply does not come with one, so you need to get it separately.
6. Screw driver, I am using 4 in 1 screw driver set. You need one to open the ATX power supply casing if you want to mount the Breakout board on it.
DSCF4790
Now, test your ATX power supply first before you hack it. If there is problem at least it is still under warranty. I have two ATX power supply in my lab. One is a bit old which I took from my colleague desktop computer:). BB-ATXRA come with ready connector and other supporting components such as resistor, indicator LEDs, switch, PCB stand. Basically it is plug and play. Now, look at your ATX power supply, you will notice there are whole bunch of wires and connectors, not to worry. We are interested on only 1 set of connector. Look for connector that have either 20-pin or 24-pin. Connect it to BB-ATXRA, plug in the AC power cord to ATX power supply and ON the AC switch. Standby LED should illuminated :) indicating the ATX power supply is in standby mode. Now, activate the toggle switch on BB-ATXRA, the PWR_ON LED should illuminate indicating the power is fine.
DSCF4795
Generally there are two type of ATX power supply, the older come only with 20-pin connector. Don worry, BB-ATXRA support both 20-pin and 24-pin ATX power supply. Here you go, 20-pin ATX connector on BB-ATXRA with the switch ON. Remember, connect the 20-pin to the left side of BB-ATXRA (near to LED, away from switch).
DSCF4808
Now, you can measure the output using multimeter: Here is 3.3V output
DSCF4800
Here is the 5V output, slightly higher, but still got for microcontroller because most of the maximum voltage is 5.5V :)
DSCF4801
+12V output, again is a bit high yet it is good.
DSCF4802
Good, if you like the –12V, go a head and measure it, I am getting around –11.50V.
These measurement prove the ATX power supply and BB-ATXRA is working  :) . Let’s proceed to next step. We will need to some soldering. BB-ATXRA come without connector, you will need to decide what you want to use. The PCB support header pin, turn pin (machine pin), blue color terminal block and green terminal block, or if you like you can solder wire directly to the PCB pad. I am going to use blue terminal block and bare in mind you don have to solder all the pad :)
Example of using header pin with female jumper wire and turn pin with male jumper wire.
DSCF4829
Using Blue Terminal Block
DSCF4824
Using Green Terminal Block
DSCF4822
OK, now solder the preferable terminal to BB-ATXRA.
DSCF4838
So you are ready to use it. But I am going further as I need to make it proper. I will now drill 4 holes on ATX power supply to give proper mounting to this breakout board, don like it tangling around. Bare in mind, never short those connection on the bottom of BB-ATXRA, you will short the terminal and might damage the ATX power supply. Measure the hole location with the BB-ATXRA, mark it and drill the holes :)
DSCF4816
Open the ATX casing, this will void the warranty, do it at your own choice.
DSCF4819
Mount the BB-ATXRA PCB stand from the bottom of the casing (upper surface) and it become:
DSCF4820
OK, is getting nicer :) I like it. Now find yourself a wire which is suitable to be use. Normal wire and use the DC jack is great idea and simple.
10287-01
But I have a lot of ready wire with this terminal:
DSCF4831
I get it from the old and damage AC to DC adapter. Do take care of the terminal polarity, use mutlimeter continuity test to find out which wire is positive, the outer ring of terminal should be negative.
Screw the wire to BB-AXTRA, choose the voltage you want to use. I normally use 12V, so here you go:
DSCF4835
Power it up and enjoy using it. Now you can really have a power supply with different voltage, 3.3V, 5V and 12V. I have here powering a project from my colleague. He did it for ROBOT. Head to Toe magazine. The Battery Internal Resistance Meter.
DSCF4841
I added a proper mounting at the back of ATX power supply for the ease of carrying it.
DSCF4848
Remember, leave the other connector untouched, you can still use back the ATX power supply if you need it 1 day. If you hack it by cutting the wire and connectors, sorry, you cannot use it anymore for your desktop.
Now, what is the specification of current output from ATX power supply? I am not sure whether all ATX power supply have the same and correct specification, I am very satisfy with my one:
DSCF4851
Woh:
3.3V at 28A (Max)
5V at 31A (Max)
+12V at 18A (Max)

But do bare in mind that the BB-ATXRA cannot support those current as the PCB track width is limited. From what we test, 10A continuous is no problem, higher than 10A will be on your own risk. You can power your battery charger for lipo if you like :) Send us some photo of your ATX power supply with the breakout board on it and show us what you use for.

Saturday, February 18, 2012

PIC Tutorials & projects

PIC 16F877A Tutorials f& projects
Charaf zouhair

These tutorials demonstrate how to code simple input & output for your robot using the popular PIC 16F877A microcontroller.  They help you get your sensors & motors working.  The rest of the code is up to you!

Questions?  Visit our website: http://www.pitt.edu/~sorc/robotics/

The tutorials assume basic knowledge of programming and electronics.  If you are new to programming, you should learn the basics of C or C++.  You should also know rudimentary electronics, and how to construct simple circuits.

I got most of this information from the PIC MCU Compiler reference manual & the help of other club members.  You are welcome to edit or add new tutorials.  Please email the club if you make another tutorial.


Introduction to the PIC16F877A





How to hook up the PIC so it will run?
Materials
PIC16F877A                
Breadboard
20 Megahertz crystal oscillator
2 7-20pf capacitor
Black & red wires
>7.2 volt battery

·         For use with a higher voltage supply, you will need to use a voltage regulator to convert the higher voltage to 5v.  Typically a 7805 is used.  Look up the datasheet by searching Google “7805 voltage regulator”.
·         If you don’t know how these materials work or what they look like, look it up online.

Circuit
1.      Insert PIC on breadboard.  Refer to pin diagram above for pin numbers.  To prevent confusion, orient the PIC so the dimple on top faces the same way as the pin diagram.
2.      Connect breadboard side strips - power to power (red strips), ground to ground (black strips).  Just like the bottom 2 wires below. Those strips are now referred to as “power” & “ground”.
3.      Power to Pin 1 (Vpp) – red wire (connected via 47k Resistor in between)
4.      Power to Pin 11 (Vdd) – red wire
5.      Ground to Pin 12 (Vss) – black wire
6.      Power to Pin 32 (Vdd) – red wire
7.      Ground to Pin 31 (Vss) – black wire
8.      Crystal Oscillator to Pins 13 & 14 (OSC1, OSC2), the polarity doesn’t matter. (polarity = which of the 2 wires goes in which hole).
9.      Capacitor into power & ground – make sure the polarity is correct according to the datasheet for the capacitor.  If not it could damage the circuit.
10.   Ground to battery ground (-) – black wire.
11.  Power (red) to battery power (+) – red wire.  Or, solder that wire to a switch & run another wire from the switch to battery power, so you can switch the power on & off.

If using voltage regulator:
raw battery power wire goes into voltage regulator input
breadboard ground strip goes to battery ground
voltage regulator output wire (+5 volts) goes to breadboard power strip.
voltage regulator ground wire goes to breadboard ground strip

What do the pins mean?

The pins RB0-RB7, RC0-RC7, and RD0-RD7 are digital I/O pins.  The pins CCP1 and CCP2, which share locations with RC1 and RC2, can be used for a PWM signal (see DC Motor tutorial).  The pins AN0-AN7 are for analog I/O (see Photoresistor tutorial).  TX and RX are for debugging I/O (see Output Messages to Computer tutorial).  The remaining pins deal with power/ground, the clock signal, and programmer I/O.

A PIC is made of several “ports.” Each port is designated with a letter, RB0-RB7 are a port. RC0-RC7 and RD0-RD7 are a port as well. RA0-RA5 and RE0-RE2 are also ports, but with fewer pins. Some of these pins have special purposes, but most can be used as basic input/output pins.

For example, you can set pin RB0 to be either an input pin, or an output pin. As an input pin, the digital voltage on the pin can be read in. For example, if RB0 is connected to ground (0v), then you would read a digital 0. If RB0 was connected to power (5v), then you would read a digital 1.
On the other hand, if you wanted to set RBO as an output pin, you could choose to make RB0 either be 5v, or 0v. This can be used, for example, to turn off or on a LED, or to turn off or on a motor.

How to program the PIC?
I omit step by step details of how to program the PIC because software always changes.

As of spring 2010, the club uses software from CCS (http://www.ccsinfo.com/).  We use the PCW Compiler to write & compile programs and CCS Load and the ICD-U40 programmer to write programs to the PIC.  Always load a .hex file onto the PIC – the compiled machine language program.  The hex file should be located in the same folder as your project file.

You need to connect the ICD’s Ethernet cable pins to the appropriate pins on the PIC in order to load a program.  You also need to have the PIC running (i.e. under +5V power) when programming.
See “How do I connect the CCS ICD to my own hardware?” in the CCS FAQ, http://www.ccsinfo.com/faq.php?page=icd_connection.

Don Crouse, the 2010 president, made custom programming boards to do that.  They might still be in the lab.  You can also cut up the wires on an Ethernet cable & connect them to the appropriate pins on the breadboard.  If you don’t want to make your own device, you can buy what you need to program the PIC.

Another available programmer the club most likely had is the PicKit 2.  To program with a PicKit, connect the pin marked by the arrow on the PicKit device to the mclr pin.  Pin 2 (next to the arrow) is +5, Pin 3 is Gnd, Pin 4 is B7, Pin 5 is B6, and Pin 6 is the optional debug pin PGM (not necessary to connect).  Also, connect the PIC to power & ground (the Vdd/Vss pins). To program a PIC, connect the PIC IC to the PicKit, and a usb mini cable from the PicKit to the computer.  To use the PicKit, run the PicKit V2 program on the desktop of the PC.  The first necessary step, if the PicKit is configured to program a different pic than your own, is to select the family of the PIC.  For the 16f877A, you must select "base device" in the device options.  In order to program a hex file, it must be loaded / imported first.  Do this by going to file and importing your program's hex file.  After the file is loaded, click on the "write hex" button.  This should write your hex file and say it programmed successfully.  The program will automatically start running even with the PicKit connected unless the /MCLR checkbox is selected.

Note:  The PicKit has the capability to supply power to the pic via the USB bus.  It will automatically detect if the device is powered when trying to program.  If you want to run your PIC just from the USB, you can select the "Vdd On" checkbox.  This can supply up to 1A of current at 5V.  Make sure the voltage number next to the checkbox is set to 5 – unless your processor does not support 5V.  The PIC used in this tutorial is a 5v device.


Miscellaneous Advice
You must have the PIC wired up & be able to compile & load programs to do the other tutorials.

To run the other tutorials, follow these steps:
1. Connect circuit as described.
2. Compile the example code with whatever compiler you are using.
3. Load the program onto the PIC.
4. Turn on the power to run the program

If you don’t know how to code something, look at old PIC code on the robotics lab’s computers.  I have found that we need to solve similar programming problems year after year, especially when we are talking about sensor input & motor output.  Chances are good that somebody already wrote it.  The PIC MCU C compiler manual is a good reference too.

I recommend that you try to be neat when attaching wires & other components.  Cut your wires so that they lie flat on the breadboard, not sticking up.  Make sure the bare ends are long enough to make a solid connection with the breadboard – you don’t want a loose wire!  Be orderly when you run wires to the various sensors & motors, too.  You will have a confusing spaghetti forest when you add sensors, motors, switches, and lights.
Another good idea is to use wire colors consistently.  For example, every time you have a wire going to ground, use the same color, usually black.  That way, you can understand what it does with a glance.  This is important when you have 50+ wires on the board.  I use red for power (the + on the battery & breadboard), black for ground (the -), blue for inputs, and green for outputs.
Always double check your connections before flicking the switch.  If just one wire is in the wrong position, it could disable your circuit or burn something out.
You can build your circuit with test LEDs, to make sure it is working when you turn it on.  I have a power light directly connected to the battery to so I know when the circuit is on.  I also have an LED controlled by the PIC.  In my programs, I make the PIC turn the LED on when it starts running.  That way I know that the PIC is working correctly.
The Anode of the LED goes to the +5v rail out of the regulator.  The cathode of the LED goes to a current limiting resistor – any value between 220 and 1k is fine.  The other end of the resistor goes to Ground.  This LED should turn on at full brightness when the circuit is turned on.  If the LED does not turn on, you may have the LED in backwards.  If you know the LED is in correctly, and it does not turn on or turns on dimly when the power is turned on, TURN OFF YOUR CIRCUIT, and check your wiring.  This most likely means there is a short somewhere with your power rails.
If you have been running the robot for a while, check the power battery voltage.  If the voltage gets too low, the robot will behave strangely due to PIC doing a “brownout”.

LED Blinker
Materials
Circuit from “Introduction to the PIC16F877A”
100 Ohm resistor
LED

Circuit
1. Pin RB7 to resistor
2. Resistor to LED
3. LED to ground

Code
//all these # below set up the PIC
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000)                                                                             // Sets crystal oscillator at 20 megahertz
#use rs232(baud=9600, xmit=PIN_C6, invert) //Sets up serial port output pin & baud rate

//main program starts here
void main() {
   //Infinite program loop starts.  LED blinks forever.
   while(true){
      output_high(PIN_B7);    //send a “1” to pin RB7, making RB7 “High” at 5v
                                                                                                //this will turn on the LED hooked to RB7
      delay_ms(500);                                                   //wait half a second, delays for 500ms
      output_low(PIN_B7);     //send a “0” to pin RB7, making RB7 “Low” at 0v
      delay_ms(500);                            //wait half a second, delays for 500ms
   }
}

Notes
You can easily add more LEDs and make them flash in different patterns.
For more readable code, use
#define RED_LED   PIN_B7
#define GREEN_LED PIN_B6
output_high(RED_LED);
output_high(GREEN_LED);   

Photoresistor Input
Materials
Circuit from “Introduction to the PIC16F877A”
Photoresistor
1K ohm resistor – or whatever is appropriate for your photoresistor
Wire

Circuit – the diagram on the right
1. Breadboard power (Vcc) to 1K-ohm resistor.
2. 1K-ohm resistor to photoresistor power.
3. Photoresistor ground to breadboard ground.
4. Wire from between resistor & photoresistor to PIC pin AN0.

If R1 is the photoresistor, the voltage will increase with increasing light intensity.  If R2 is the photoresistor, the voltage will decrease with increasing light intensity.

Code for single photoresistor
//all these # below set up the PIC
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000) //crystal oscillator at 20000000 hertz
#use rs232(baud=9600, xmit=PIN_C6, invert)  //serial port output pin & baud rate

//run photoresistor signal wire to pin AN0
//connect LED/resistor to pin RB7

void main(){
   int16 photo=0; //16 bit integer, safer than using int because
                  //int is only 8 bit which might lead to overflow problems for add, multiply
                 
   setup_adc(ADC_CLOCK_INTERNAL); //configure analog to digiral converter
   setup_adc_ports(ALL_ANALOG);   //set pins AN0-AN7 to analog (can read values from 0-255 instead of just 0,1)

   while(true){ //loop forever
      set_adc_channel(0);//set the pic to read from AN0
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 0
      photo=read_adc(); //read input from pin AN0: 0<=photo<=255
     
       //turn on LED when input > 127, else turn off LED
       //Put finger over photoresistor & take it off to see LED turn on/off
       //127 may not be the actual value that separates light from dark, so try different values
      if(photo > 127){
         output_high(PIN_B7);
      }
      else{
         output_low(PIN_B7);
      }
   }
}

Code for multiple photoresistors
//all these # below set up the PIC
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000) //crystal oscillator at 20000000 hertz
#use rs232(baud=9600, xmit=PIN_C6, invert)  //serial port output pin & baud rate

//read input from 3 photoresistors
//run photoresistor signal wires to pin AN0, AN1, AN2

void main(){
   int16 photo0=0; //16 bit integer, safer than using int
                  //int is only 8 bit which might lead to overflow problems for add, multiply
   int16 photo1=0;
   int16 photo2=0;
  
   setup_adc(ADC_CLOCK_INTERNAL); //configure analog to digiral converter
   setup_adc_ports(ALL_ANALOG);   //set pins AN0-AN7 to analog (can read values from 0-255 instead of just 0,1)

   while(true){ //loop forever
      set_adc_channel(0);//set the pic to read from AN0
      delay_us(20);//delay 20 microseconds to allow PIC to switch to analog channel 0
      photo0=read_adc(); //read input from pin AN0: 0<=photo<=255
     
      set_adc_channel(1);//set the pic to read from AN1
      delay_us(20);
      photo1=read_adc();
     
      set_adc_channel(2);  //set the pic to read from AN2
      delay_us(20);
      photo2 = read_adc();
     
      //You could add 3 LEDs and turn them on if photo0/1/2 > 127
      //just as with code for single photoresistor
   }
}

Analog Input (Photoresistor, Sonar sensor, IR sensor, …)
Materials & Circuit
Depends on the device.  For example, a sonar sensor might have 3 wires: power, ground & signal.  You would connect the signal wire to one of pins AN0-AN7.  See the device’s datasheet for help.

Code
//the rest of the code is identical to code for photoresistor input, except here we call it ‘sonar’
int16 sonar = 0;
set_adc_channel(1);//set the pic to read from AN1
delay_us(20);
sonar=read_adc();

Notes
You can use the photoresistor tutorial code to read any sort of analog input device, as long as the device is designed so you can run a signal wire to the input pin(s).
Remember, only the AN0-AN7 pins allow analog input, and you have to call setup_adc functions & set_adc_channel as in photoresistor tutorial.
Roughly, PIC will read 0 volts as 0, and 5 volts as 255.


Digital Input (Switches)
Materials
Circuit from “Introduction to the PIC16F877A”
LED
Switch
1K ohm resistor
10 or 47K ohm resistor
Wire

Circuit
Pin RB7 to 1Kohm resistor. Resistor to LED. LED to ground.
Pin RD1 to 10/47Kohm resistor.  Resistor to ground.
Pin RD1 to switch.  Switch to power.

This circuit has a “pull-down resistor”.  When the switch is closed, the PIC reads 5 volts and when it is open it reads 0 volts.  If we had no pull down resistor then the pin would be in a “floating” state when the switch was open, meaning that the voltage can fluctuate.  We need to connect the pin to ground so the PIC always reads 0 when the switch is open.  If there was a wire connected to ground instead of a resistor, it would create a short that burns up the circuit.
Code
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000)             // Sets crystal oscillator at 20 megahertz
#use rs232(baud=9600, xmit=PIN_C6, invert) // serial port output & baud rate

//close switch to see LED turn on
//open switch to see LED turn off

//if the pin is low (0 volts) x = 0, or FALSE
//if the pin is high (5 volts) x = 1, or TRUE

void main() {
   int x = 0;

   while(true){
      x = input(PIN_D1);
      if(x==1){
          output_high(PIN_B7);
      }
      else{
          output_low(PIN_B7);
      }
   }
}

Output messages to computer screen
I have used 2 methods.

1. PICkit 2 Development Programmer/Debugger.  See their instructions in the program or website.

2. Serial port.  I used HyperTerminal to read text from the serial port & display on screen, but other programs can do that too.  Make sure the baud rate is 9600 bits / sec, just like in the PIC code: #use rs232(baud=9600, xmit=PIN_C6, invert)
Serial Port Steps (if using HyperTerminal)
  1. Wire serial port pin 2 to pin TX (same as RC6) on the PIC.
  2. Wire serial port pin 5 to ground.
  3. Connect serial port to computer.  Use a serial-USB adapter if computer has no serial port.
  4. Open HyperTerminal.
  5. Enter any name, select the icon that says “MCI”
  6. Connect using COM5/COM13/etc.  If there are multiple COMs: pull out the USB, reopen HyperTerminal, & see which COM has vanished.  That’s the one you want.
  7. Set bits per second = 9600.
  8. HyperTerminal is set up.  It will keep reading input until you close the program.
  9. Load code onto PIC
  10. Hit switch to turn on PIC

Code
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000)             // Sets crystal oscillator at 20 megahertz
#use rs232(baud=9600, xmit=PIN_C6, invert) //Sets up serial port output pin & baud rate

void main(){
   int x = 0;
   while(true){
      x = x + 1;

      //This is an ordinary C language printf statement that will display on the screen of your PC.
      //But, you need to open a special program to read serial port input, like HyperTerminal.
      //Make sure the baud rate of the program matches this code’s baud rate (9600 bits / second)

      printf("hello, x=%d\r\n",x); //send this text to serial port

      delay_ms(100); //wait 100 milliseconds
   }
}


Servo Motor Output
Materials
Circuit from “Introduction to the PIC16F877A”
Servo Motor (this tutorial tested on Parallax Standard Servo)
Wire

Circuit
See servo motor datasheet.  Most likely it will be
  1. Servo power wire to power
  2. Servo ground wire to ground
  3. Servo signal wire to pin RD2. (could be any I/O pin on the PIC, just change the code)


Code
#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS         //Highspeed Osc > 4mhz
#FUSES PUT        //Power Up Timer
#FUSES NOPROTECT  //Code not protected from reading
#FUSES NODEBUG    //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP      //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD      //No EE protection
#use delay(clock=20000000)             // Sets crystal oscillator at 20 megahertz
#use rs232(baud=9600, xmit=PIN_C6, invert) //Sets up serial port output pin & baud rate

//pin RD2 wired to servo
//servo connected to power, ground, and the signal wire from the PIC

//this program steps the Parallax standard servo slowly from 0 to 180 degrees,
//then rushes back to 0 degrees to restart.

//for code readability, could use #define SERVO_PIN PIN_D2 --> output_high(SERVO_PIN);

void main(){
   int16 pulse_width = 1000;
   int i;
  
   while(true){
       //send short pulse to servo indicating which angle it should move to.
       //for example, for one type of servo, 1000us=1ms indicates 0 degrees,
       //while 2000us=2ms indicates 180 degrees.
       output_high(PIN_D2);
       delay_us(pulse_width); //sending 5 volts to servo for pulse_width microseconds
       output_low(PIN_D2);
       delay_ms(20); //wait 20 milliseconds - refresh cycle of typical servos
      
       pulse_width = pulse_width + 1; //each time, servo is instructed to move a little farther
       if(pulse_width == 2001){ //if servo reached angle 180, reset: it will rush back to angle 0
         pulse_width = 1000;
       }
      
       /*
       If want servo to go to an angle & stay there, need to send the same pulse several times. (50 is good)
       If only send 1 pulse, the motor won't get all the way there, and it will stop, waiting for
       another pulse.  Example below shows how to move servo to 90 degrees.
       for(i=1;i<=50; i++){
          output_high(PIN_D2);
          delay_us(1500); //want servo to move to 90 degrees.
          output_low(PIN_D2);
          delay_ms(20);     
       }
       */
   }
}

Notes
Other servos may have different pulse width requirements.  And, they might go only 90 degrees, or up to 360 degrees.  There are also issues where servos draw too much current or waste heat, which is beyond the scope of this tutorial.

DC Motor Output
Normally, you will use an H bridge for motor control.  There are many internet articles about H bridges if you want to learn how they work.

Materials
Circuit from “Introduction to the PIC16F877A”
DC motor
H bridge chip
Wire

Circuit
Depends on the type of H bridge.  I have used an old SN754410 quadruple half-h driver to run 2 motors at once.  I also used a custom H bridge circuit board designed by club president Don Crouse.  See the data sheet.

Important: whenever you change the direction, you should set all motor signal lines to 0 (output_low).  This prevents short circuits.

Code & Notes
I will not include an entire program here, because each H bridge model has different rules for motor control.  The datasheet will tell you how to set the signal lines.

There are two major types of output signals on most H bridges.

The first signal turns the motor on or off.  It is often called the “Enable Pin”.  Whenever you want to turn the motor on, respectively off, type output_high(MOTOR_ENABLE_PIN); and output_low(MOTOR_ENABLE_PIN);

The second type are the signals indicating which direction the motor should turn, whether the motor free runs, and whether the motor brakes.  Send 0 or 1 to those control signals: output_high(MOTOR_DIRECTION_PIN_1), for example.

A simple illustration:


Direction Pin
Enable Pin
Results
0 (output_low)
1 (output_high)
One direction
1 (output_high)
1 (output_high)
Other direction
X (doesn’t matter)
0 (output_low)
Free run (slow down & stop)


Some H bridges will only let you set the motor direction.  In that case, you brake by reversing the motor direction for a short time.  Beware: the current draw can spike if you do this, and the PIC might black out.  But sometimes sudden direction reversal is OK; you will have to see for yourself.

If you have set the signals to make the motor go left, it will keep going left until you explicitly tell it to stop (or go right).

It is a good idea to write functions like “forward”, “backward”, “left”, “right”, “stop”.  That way you can just call the function & not have to worry about the details.

Below are code excerpts from motor control for SN754410 H bridge, controlling 2 motors.  Your motor control code will NOT be the same, because you will use a different H bridge or have different needs.  But it will be similar to this.

#define LEFT_CONTROL_2A  PIN_C2  //2A
#define LEFT_CONTROL_1A  PIN_C1  //1A
#define LEFT_MOTOR       PIN_D1  //1,2EN
#define RIGHT_MOTOR      PIN_D2  //3,4EN
#define RIGHT_CONTROL_4A PIN_D5  //4A
#define RIGHT_CONTROL_3A PIN_D4 //3A
int going_forward;  //current motion
int going_backward;
int going_left;
int going_right;  
int going_hard_left;
int going_hard_right;
//brake by reversing motor direction, then turn motors off
void halt(){
   if (going_forward)
      backward();
   else if (going_backward)
      forward();
   else if (going_left)
      right();
   else if (going_right)
      left();
   else if (going_hard_left)
      hard_right();
   else if (going_hard_right)
      hard_left();
   delay_ms(50); //reverse direction for 50 ms, enough to make robot stop
  //but not long enough to make it start moving in opposite direction
   resetMotorControl();   
}

void forward(){
   resetMotorControl();
   output_high(LEFT_CONTROL_1A);
   output_high(RIGHT_CONTROL_3A);
   output_high(LEFT_MOTOR);
   output_high(RIGHT_MOTOR);
   going_forward=1;  
}

void backward(){
   resetMotorControl();
   output_high(LEFT_CONTROL_2A);
   output_high(RIGHT_CONTROL_4A);
   output_high(LEFT_MOTOR);
   output_high(RIGHT_MOTOR);
   going_backward=1;
}

//run only 1 motor for gentler turn
void right(){
   resetMotorControl();
   output_high(RIGHT_CONTROL_3A);
   output_high(RIGHT_MOTOR);
   going_right=1;
}

//run only 1 motor for gentler turn
void left(){
   resetMotorControl();
   output_high(LEFT_CONTROL_1A);
   output_high(LEFT_MOTOR);
   going_left=1;
}

//run one motor forward and one backward for sharper turn
void hard_left(){
   resetMotorControl();
   output_high(LEFT_CONTROL_1A);
   output_high(RIGHT_CONTROL_4A);
   output_high(LEFT_MOTOR);
   output_high(RIGHT_MOTOR);
   going_hard_left=1;
}

//run one motor forward and one backward for sharper turn
void hard_right(){
   resetMotorControl();
   output_high(LEFT_CONTROL_2A);
   output_high(RIGHT_CONTROL_3A);
   output_high(LEFT_MOTOR);
   output_high(RIGHT_MOTOR);
   going_hard_right=1;
}

//Set all pins to H-bridge low to prevent short circuits
//Reset "current motion" flags
void resetMotorControl(){
   output_low(LEFT_MOTOR);
   output_low(RIGHT_MOTOR);
   output_low(LEFT_CONTROL_1A);
   output_low(LEFT_CONTROL_2A);
   output_low(RIGHT_CONTROL_3A);
   output_low(RIGHT_CONTROL_4A);
   going_forward=0;
   going_backward=0;
   going_left=0;
   going_right=0;
   going_hard_left = 0;
   going_hard_right = 0;
   delay_us(20);
}

Special Topic: PWM
Now you know how to run the motor at full speed.  But a situation might arise where you want half speed, or ¾ speed, etc.  In that case, you can send a PWM signal to the H bridge enable pin.  There are many internet articles about PWM if you want to learn how it works.

To use PWM in motor control, replace output_high(MOTOR_ENABLE_PIN) with set_pwm1_duty(x) .  Make sure that the “enable pin” wire goes into the PIC pin CCP1 or CCP2.  Those are the only pins that can have PWM signal.

PWM code excerpt:

   setup_timer_2(T2_DIV_BY_4,255,1);
   setup_ccp1(CCP_PWM); //set pin CCP1 as a PWM pin instead of a regular I/O pin
   setup_ccp2(CCP_PWM); //set pin CCP2 as a PWM pin instead of a regular I/O pin
   while(true){
      //if setting duty cycle (set_pwm1_duty), only give values between 0-255  
      //0 means the PWM signal is always at 0.  128 means it is 1 half the time & 0 the other half
      //leading to an averaged "1/2 power" signal.  255 means it is 1 all the time, motor full speed
      set_pwm1_duty(255);  //enable pin for motor 1: PIC pin CCP1
      set_pwm2_duty(255);  //enable pin for motor 2: PIC pin CCP2
      delay_ms(3000); //full speed for 3 seconds
      set_pwm1_duty(128);
      set_pwm2_duty(128);
      delay_ms(3000); //half speed for 3 seconds
      set_pwm1_duty(0);
      set_pwm2_duty(0);
      delay_ms(3000); //motors off for 3 seconds
   }

//Use PWM in your DC motor control code to change the speed that the robot goes forward/backward/left/right
//call forward(255); to go forward at full speed.  Call forward(128); to go forward at half speed.
void forward(int speed){
   resetMotorControl();
   output_high(LEFT_CONTROL_1A);
   output_high(RIGHT_CONTROL_3A);
   set_pwm1_duty(speed); //wire from PIC pin CCP1 to right motor enable pin
   set_pwm2_duty(speed); //wire from PIC pin CCP2 to left motor enable pin connected to
   going_forward=1;  
}

Notes
If you want to use higher voltage DC motors, or run motors at high speeds, you might have to construct a special circuit to deal with the extra current draw, heat, high voltage batteries, etc.  DC motors have their own set of issues to deal with, which is beyond the scope of this tutorial.