Tuesday, June 23, 2015
Monday, May 09, 2011
For a long time, I have been trying to find the cheapest and easiest way to control electronic devices wirelessly using a computer. It can open up a lot of possibilities. For example, you could build a radio controlled relay board, and control it from your computer. You could even control the board with a "small" computer such as an Arduino (or any microcontroller for that matter). If your Arduino has an Ethernet shield, you could use it as a Web server and control your relay board from anywhere in the world (as long as you have access to the Internet of course). There are many things that you could do without creating a mess with wires. I am mainly interested in this because I need a computer controlled wireless robot. A little background -
I have been working on a project at the Mobile Robotics Lab of IISc (Indian Institute of Science), Bangalore, in which I have to design a vision based obstacle avoidance algorithm for robots. What does that mean? Well, I basically have to design a robot that uses nothing but a small camera to identify obstacles in its path. Since image processing and computer vision stuff is usually quite CPU intensive, it is difficult to implement this code on a small robot. Small microcontrollers can't handle that stuff. So, the solution I came up with involves a wireless camera that transmits video to a nearby "big" computer. This big computer runs all the dirty computer vision codes, identifies the obstacles, and then somehow tells the robot how to avoid them. This is where wireless communication comes in.
To create a wireless link, you could rip the guts of a cheap RC car and use its transmitter and receiver to control your robot. That's one technique. I did something similar a few years ago . This time, I wanted to do things a little more elegantly, without destroying an RC car. I found this really inexpensive RF transmitter/receiver pair at a local electronics shop in Bangalore:
They cost only 200 INR (about 4 USD)...both transmitter and receiver. What a steal!
You can also find these online at Sparkfun:
Transmitter - http://www.sparkfun.com/products/8945
Receiver - http://www.sparkfun.com/products/8948
They cost a little more on Sparkfun, but they're still inexpensive. The ones on Sparkfun operate at 315 Mhz, but the ones I have, operate at 434 Mhz (like this one). I don't think that would make any difference in how you connect them.
To use these cheap RF modules, you could either connect them directly to your microcontroller/computer, or connect them with the help of parallel - serial encoder/decoder ICs.
I used the HT12E (parallel to serial encoder) and the HT12D (serial to parallel decoder) ICs. The HT12E is a 12 bit parallel to serial encoder. Of those 12 bits, 8 bits are the address code, and the remaining 4 bits are data. To send a signal, the address bits on the transmitter and receiver should be the same. It's like a password. You can use a single RF transmitter to control different RF receivers (at the same frequency) by configuring the address bits appropriately. All receivers would have to be set to different addresses. With 8 bits, you can create a total of 256 combinations.
Here's what the serial data coming out of the encoder looks like, in an oscilloscope:
If you look closely, you'll notice that there are 13 peaks (instead of 12). I'm not sure what the first bit is for. (Probably a parity bit?) The 8 bits coming after the first bit make the address, and the last four make the data being sent. You connect your microcontroller's (or computer's) parallel output to the 4 input channels on the encoder. With 4 bits, you can create 16 unique commands. That is enough for my purpose.
For more on how to use these ICs with the Tx/Rx, check out this excellent article - http://www.botskool.com/tutorials/electronics/general-electronics/building-rf-remote-control
Here's a flowchart of my system:
I've connected an Arduino to my computer which acts as an interface between the encoder and my computer. Here's the Arduino that I'm using:
It's a ModernDevice BBB Arduino Clone that I received from my friend Tom Boyd. I've been hooked to it ever since I got it! You should definitely get an Arduino if you don't already have one. It's the perfect tool for the programmer who enjoys playing with electronics. And it's also very easy and fun to use!
Tom has some excellent tutorials on electronics and programming on his website that keeps inspiring me! Check out some of his awesome Arduino projects - http://sheepdogguidecools.com/arduino/ahttoc.htm.
The robot I am using is a Microbric Viper robot that I received from Microbric a few years ago. The Microbric Viper comes with an IR module which can be used to communicate with a computer wirelessly. Although I've used it in the past, it's kind of difficult to set up because infrared communication requires line-of-sight. Moreover, the range is quite limited.
I'm not going to get into the details of connecting the encoders/decoders with the RF modules because it is already covered in detail in the article I mentioned earlier. I am however, going to share some difficulties I have faced in using these RF modules.
When I was testing the receiver on a breadboard, I was powering it with an AC to DC adapter. The voltage was fine, but the decoder did not work at all. Why? When I was debugging the circuit with an oscilloscope, I realized that the signal at the encoder side was fine, with 13 distinct peaks. However, when I checked the data at the receiver side, I realized that there was some sort of noise, and the peaks were not distinct. The address bits were too close together and sometimes even merging together. Since the address bits on the decoder side did not match with this noisy data, it rejected it. I figured that this noise could be caused by radio interference noise from the AC to DC adapter. So, I removed it and powered each of them (Tx and Rx) with two AA batteries.
The other thing I noticed is that if you connect the third pin of the RF receiver (which is either marked as "Data" or "CE") to the data-IN pin of the decoder , the circuit won't work. Leave it unconnected.
I'm using a 1/4 wave monopole antenna (6.8 inches) with the RF modules. It's just a single core wire. The range I get is amazing. I think I get about 100-120 ft (through walls), and 1000+ ft outside (line-of-sight)! More than enough for my purpose. When I test it outside, it just keeps working no matter how far I go. So, I don't really know its limit yet!
The Arduino communicates with my computer through a USB to Serial cable. If I want to make the robot move forward, I would send the character '1' to the Arduino. It would recognize this as a command and forward it to the transmitter. I can send four commands to the Arduino - '1', '2', '3' and '4'. On receiving these characters, it sets the appropriate data bits on the encoder and transmits the signal.
On Windows, I use a C# application to send these commands to the Arduino. On Linux, I just use the terminal. My Arduino shows up as /dev/ttyUSB0. To send the command '1', I write...
echo -n "1" > /dev/ttyUSB0
This makes the robot move forward. For a more interactive session, you can use the screen command:
screen /dev/ttyUSB0 9600
More on this here - http://www.arduino.cc/playground/Interfacing/LinuxTTY
And finally, the thing you were probably waiting for...a video! -
I hope you enjoyed this post. My next step would be to put a wireless camera on this robot and test my obstacle avoidance algorithm. Wish me luck.
I hope the information I've shared helps you build your own radio controlled electronic devices and robots!
So what did you think? I'd love to hear your feedback in the section below.
Posted by Ashish Derhgawen at 8:30 PM
Saturday, February 13, 2010
Here's what I've been working on for the last couple of weeks:
This is a USB interface board I've built around a PIC 18f4550 microcontroller from Microchip. As many of you probably know, I've used my computer's parallel port to connect many things to my computer. However, most laptops don't have parallel ports these days, so I needed a way to connect things without a parallel port. This board does exactly that (and actually much, much more). I found a really nice tutorial on building this board here - http://eegeek.net/content/view/13/32/
You can make your C#, VB, C++ programs communicate with the chip using the open-source MCHPFSUSB Framework from Microchip, or the Window's HID drivers. The framework comes with lots of samples to get you started.
I've put a bootloader on the chip for the sake of convenience. With a bootloader, you don't have to take the chip off the board and put it in a separate programmer for programming. I have to sometimes re-program the chip every 10-15 minutes during development (especially when there's a hard to find bug), and the bootloader really makes it easy.
No project is compete until you record a video! So here's one:
Please excuse the background noise in the video. There was some construction work going on while I was recording this. Anyway, I'm using the board to control some LEDs, a servo, and reading the value of a potentiometer. Controlling the servo was the trickiest part because servo's are sensitive to timing. They expect to receive a pulse every 20 ms, and the duration of the pulse determines how much they will turn. The length of the pulse usually varies between 1-2 ms. Setting up the timers on the chip to work properly was a bit challenging, but I finally got it working. This sound card based oscilloscope really helped! - http://www.zeitnitz.de/Christian/scope_en.
Hope you enjoyed this post. I will be using this board in future projects. Keep checking!
Posted by Ashish Derhgawen at 11:19 AM
Friday, January 29, 2010
I've always felt the need to have a small screen on my computer to show some "extra" information which I don't usually want on my screen all the time. By extra information I mean - news headlines, RSS feeds from my favorite blogs, weather updates, CPU usage information, new e-mail notifications, etc. So, to fulfill this humble need of mine, I bought a small (16x2 character) LCD screen for Rs.90 (approximately USD $2). Very inexpensive!:
(I've received an e-mail from TK Boyd! He's the man who inspired me to connect all sorts of things to my computer!)
This LCD is based on the popular Hitachi HD44780 controller. You can find lots of information about how to communicate with this LCD on the Internet. I connected it to my computer's parallel port and fixed it to my computer's case:
I created this panel by drilling holes into the case, and adding two switches (for the LCD and backlight), and a pot for contrast adjustment. The LCD is powered by 5V from the SMPS.
Here is the pinout for the LCD:
DB0-DB7 is the data bus.
'E' is the enable line. This is used to indicate the start of a transmission of a data byte to the LCD controller. When we start a transmission, this line is brought high. When transmission is complete, this line is brought low.
'RS' is the register select line. This line indicates to the LCD controller whether the data byte is to be treated as a command or as text data to be displayed on the screen. If it is high, the data sent to the LCD displayed on the screen. If it is low, the data is treated as a command.
'R/W' is the read/write line. If it is low, information can be written to the LCD controller. If it is high, data can be read from the LCD. I've kept it permanently low in my circuit.
Here's a screenshot from the HD44780's datasheet (click on the image to enlarge it):
- Make 'RS' and 'R/W' low ('R/W' is always low in my circuit).
- Set 'E' high to indicate the start of the command.
- Make DB7-DB0 equal to binary "00000001" (decimal: 1). This is the clear display command.
- Make 'E' low again to execute the command (which in this case would clear the display).
I'm using Inpout32 to access my parallel port. Another point I should mention here is that the 'E' pin on my LCD is connected to C0 on my parallel port and 'RS' is connected to C2. A weird thing I noticed about C0 is that you have to send "1" to it to make it low (and vice versa). This is why I'm sending "1" in the last line of the the code. I have no idea why this is happening. Have any clues?
To write characters on the LCD, you just have to send the ASCII code of the character to the LCD:
Creating custom characters:
Most characters on the LCD (I think there are a total of 248) are stored in what's called a CGROM. This is an acronym for "Character Generator Read Only Memory". Characters inside this memory location are pre-defined, and cannot be changed. So how do we create our own characters if we can't change anything here? Well, there's a 64-byte hunk of RAM called CGRAM in the LCD, and it is write-able! Characters on an LCD can be up to 8 pixels high, and 5 pixels wide. Each row consumes 1 byte of memory. Since there are 8 rows, one character takes up 8 bytes. So, a total of 8 custom characters can be defined in 64 bytes. Here's the pixel map of a bell pattern I created:
I have written the decimal and hex values for each row. To store this custom character in the CGRAM, I would have to go to the CGRAM address (see the "Set CGRAM address" command in the datasheet) and write these values. The address of the first byte of the first character is 64 (hex: 0x40). How in the world did I get that value? Well if you look at the command for setting the CGRAM address in the datasheet, it says we have to set DB6 to "1". The rest of the bits, DB0-DB5, determine the CGRAM address. If we were to set DB0 to DB5 "0", we would be able to set the first first byte of the first character. The complete command would be binary "1000000" (DB6-DB0). This is equal to 64 in decimal. Similarly, the address of the first bye of the second character would be 64 + 8 = 72 (remember each character consumes 8 bytes).
Here's a code sample to draw this bell character on the LCD:
I need to do some explaining here! Well, first we define the bytes for the bell character in an array. Then we set the CGRAM address to 64 (first byte of the first custom character). Then we write the values in the array to the CGRAM in the for-loop. Notice that we don't have to set the CGRAM address every time we have to go to a different byte (65,66,67 etc). The LCD controller auto increments the CGRAM address everytime we write a byte. To display this newly created character, we first have to switch back from the CGRAM to the display area. We do this by setting the DDRAM address to 128 (first character of the first line). 129 would be the second character, and so on. The second line starts at DDRAM address 192. We display the custom character by displaying ASCII code "0". ASCII codes 0 through 7 are for custom characters. They normally serve as control codes for marking the beginning of a serial transmission, but since these have no meaning to an LCD module, the designers reserved them for CGRAM characters. It took me a long time to figure that out!
I find it convenient to create custom characters on a sheet of graph paper before I begin coding:
A note on creating animations:
You can create animation by rapidly printing custom characters. If you have a custom character on your LCD, and you modify it's bytes by going to the CGRAM, the character will change. In fact, all occurrences of that character will change. Here's another cool thing. You can create more frames for your animation than the eight character limit. This is because you can load new bit patterns from your computer without having to store it in the LCD's memory. Neat!
This post is getting long, so I'll end my discourse here. :) My LCD project is a WIP right now. I'm still adding more features. Anyway, I hope you find this post helpful in your projects. Have fun!
How to control a HD44780-based Character-LCD
Defining Custom Characters
Creating custom characters tutorial
CodeProject article on controlling LCDs using C#
Posted by Ashish Derhgawen at 12:12 AM