Search
The AVR based USB Touchscreen Mouse
USB AVR Touch Screen from Sparkfun on Vimeo. IntroductionWe have been selling the PSP and Nintendo DS touchscreens for a while now and it is about time we do something cool that uses them. A LCD touchscreen project first comes to mind, but I really wanted to do something different. Ryan, one of the other SparkFun engineers was working on the AVR Stick, which uses open source firmware available from Objective Development called V-USB to implement the USB 1.1 standard on an AVR. Basically, you can turn an AVR, like an ATMega168 into a HID (Human Interface Device), that when plugged into a USB port will act like a mouse or keyboard. A touchscreen mouse sounded oh too perfect. Here are the materials I used to implement the USB touchscreen mouse:
You might be wondering why I didn't use the AVR Stick. Well, there simply were not 4 open IO pins. Touchscreen The PSP touchscreen is a 4 wire analog resistive touchscreen. This means by touching the screen at one point, a resistance between each edge is formed for both the x and y axises. As you move your finger or stylus across the screen the resistance changes between opposing sides of each axis. By applying a voltage across each axis, a changing resistance results in a changing voltage. Thus a simple ADC on a microcontroller can be used to find x and y positions. Here is a great document that explains it a little better. The four pins control 4 buss bars located around the peripheral of the touchscreen. In order to read either an x or a y position, two opposing bars need to be powered and a third orthogonal bar is used to measure the divided voltage. ![]() This configuration means that the voltage, ground, and sense bar need to be continually switched in order to quickly read x and y positions. Here is how I hooked up the touchscreen to my ATMega168: ![]() In my code I will need to switch between the x and y pin assignments in order to quickly read the x and y positions. Hardware The hardware for the touchscreen was a simple direct connection to 4 IO pins, 2 of them needing to be ADCs. Power to the screen can be supplied by an output pin being pulled high to 5V and another output pin being pulled low to ground. The hardware used to turn my ATMega168 into a HID device was simple. All I needed were a few resistors connected to two interrupt pins on the ATMega168. The only requirement is that the D+ pin needs to be connected to the INT0 pin. More information is available from Objective Development. Here is a piece of my schematic: ![]() Here is the complete setup: ![]() Code The first thing I needed to do was to make sure I could get reliable x and y position from the touchscreen before messing with the USB stuff. Here is my project source code for just reading out the ADC values for the touchscreen. Basically, I needed two ADC readings, one for x and one for y. However, I can't just set one pin permanently to one ADC, the pins will need to be constantly changing (refer to the chart above). I made a function for each coordinate that changes the pin assignments and takes an ADC reading. void read_x(void) { DDRC = 0b00010010; // Output on PC4(5V) and PC1(GND), Input on PC4(ADC) sbi(PORTC, 4); //pull PC4 to 5V cbi(PORTC, 1); //pull PC1 to GND _delay_ms(1); //wait for screen to initialize ADMUX = (1 << MUX1); //ADC2 ADCSRA = (1 << ADEN)|(1 << ADSC)|(1< while(ADCSRA & (1 << ADSC)); l = ADCL; h = ADCH & 0x03; h = h << 8; h = h + l; } Now, I can just print the global variable h for the ADC value. The delay after the port assignments is important. I found that without the delay, the ADC value was not consistent, there were aberrant values present. Since we are powering one of the bus bars on the touchscreen with 5V and then quickly switching it to an ADC input, I imagine that I wasn't waiting long enough for the capacitance in the screen to "charge". The 1 ms delay did the trick. Now that I know the touchscreen hardware is working, I can now look into using these values to compute mouse movements using the USB libraries. The USB libraries for AVRs can be found on Object Development's download page. What you get is all of the information you need to implement USB on an AVR: USB libraries, example circuits, example source code, and pretty good documentation. Sure enough, there is some basic example code for a USB Mouse. The example is even configured for the same architecture that I was planning to use (target device, CPU clock, and fuse values), so I didn't need to change anything in the makefile. Although, I did want to use my Atmel mkII programmer with AVRstudio, but I wasn't about to go sifting through the makefile. The example uses avrdude and stkxxx compatible programmers and since SparkFun sells three of those programmers, why not just use one of them. Note: If you happen to want to use a different AVR at a different speed, then you will need to adjust the makefile. However, not all clock speeds will work. Be sure to use a USB compatible speed for your clock and set the correct fuse bits. More info on what clock speeds are allowed can be found in the usbconfig.h header file. After you have your USB hardware setup on your AVR, plug in your programmer, open a command prompt to your firmware directory, follow the make commands in the makefile (be sure to set your fuses!! Information on fuse settings can be found in the makefile), and presto, your AVR is now a USB Mouse. The example code makes the mouse cursor move in a circle by computing the mouse movements internally in the main.c file. This is nice and fun, especially if you are wanting to play a trick on your co-worker. We had some fun and plugged the tiny AVR Stick with the USB Mouse example into an unsuspecting staff member's computer; ahh good times. :) So how do I get the ADC values of the touchscreen into movements of the mouse? The main.c code uses member dx of the structure reportbuffer as a value for speed in the x direction (same for y). Basically, all I need to do is load a signed 8 bit value into reportbuffer.dx and that will move the mouse cursor at some speed. To sum it up, all my code really does is: 1) Enable a timer to read the ADCs at a set interval 2) Fill a small buffer for the ADC values 3) 6) Load that value into reportbuffer.dx There was a relatively large problem I ran into after step 3. The ADC value is an unsigned 10 bit number when I load it into the variables h and h1. When I do my comparisons, conditionals, and calculations to clean up the mouse movements, I have to use signed or unsigned 8 bit, 16 bit, or long values. This creates a huge problem since doing any operation between different sized binary values results in non-sense values. Overall, I needed to turn the unsigned 10 bit ADC into a unsigned 8 bit value. With some clever bit shifting I got the value I needed (I would think there is a better way to do this). Here is the shift: Another issue I came across was debugging. The printf interrupts conflicted with the USB interrupts, therefore I couldn't print values for integers I needed to debug (like the xshifted variable). What I did was debug using my serial code with out the USB libraries. This was really time consuming, but it did help a bit. Here is a video of how it works when using the back of a pen as a stylus (my finger worked OK, but a stylus was much better). USB AVR Touch Screen from Sparkfun on Vimeo. -Aaron |
||||||||
Feeds
Currency
Display prices in
Feedback
If you would like to tell us more, you can fill out our form if you need some psycho-suggestive questions. Go to the form.










The schematic is uses the ATMega168-AU
to use with Arduino: use Digital Pin 4 for D- and Digital Pin 3 for D+
Have fun
works pretty fine, but you can increase the accuracy of the touch pad if you middle 10 to 100 ADC values for each channel =)
I tested AVR USB ... or how it is called now ... and it quite unstable and therefore I don't recommend it for larger applications.
Greets^^
here is my setup http://wtfmoogle.com/arduino/DSCN4993.JPG
here is the little usb board i made
http://wtfmoogle.com/arduino/usbthingbrd.png
looked into it and it is digital pin 4 for D- and pin 2 for D+
only difference i see is i used 86 ohm resistors instead of 68? that couldn't be that much of a problem could it?
I don't have the touch screen yet but i plan on using 2 potentiometers to test it out.
uploaded the .hex with avr dude...
what am i doing wrong?
http://vusb.wikidot.com/hardware
They use either a reduced voltage, two diodes, or a level conversion (two Zener diodes) to work with the USB spec.
Why can you run everything with 5V?
Thanks, Lars
I _had_ to make an account to respond to this, because it might save a ton of frustration.
It's true that you can build this circuit out of spec and it might work, but that can be dicey. I built something similar (attiny45 and v-usb) and I found that without the voltage regulation, only 1/3 of the computers I tried it on could recognize it as a usb device.
It is absolutely worth it to slap on a few diodes to bring the voltage down to the 3.3-3.6 range to improve your chances for compatibility.
I've been looking at this for a few weeks now, and I'm gonna buy the stuff to build it, but I already have the Ardunio usb w/proto-sheild. Do I have to buy the new controller?
Then once that was done if this could be talked to with a connection as a library for wiring then keypresses output could go to a c program.
This would be a great higher speed data logger than a serial port connection I think.
Yes, you can check out more details here:
http://code.rancidbacon.com/ProjectLogArduinoUSB
I adapted the V-USB code to work with the Arduino.
--Philip;
what happens when there is no pressure on the screen? Does it skip to gnd or +v, or does it float? I don't want my ADC reading arbitrary values when I take my finger off. Thanks!