ebook img

Touch Screen Shield for Arduino UNO PDF

67 Pages·2012·1.7 MB·English
by  
Save to my drive
Quick download
Download
Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.

Preview Touch Screen Shield for Arduino UNO

Touch Screen Shield for Arduino UNO By Justin | November 8, 2013 132 Comments Features: · 2.4″ diagonal LCD TFT display · Bright, 4 white-LED backlight, on by default but you can connect the transistor to a digital pin for backlight control · Colorful, 18-bit 262,000 different shades · 4-wire resistive touchscreen · 240×320 resolution · spfd5408 controller with built in video RAM buffer · 8 bit digital interface, plus 4 control lines · Uses digital pins 5-13 and analog 0-3. That means you can use digital pins 2, 3 and analog 4 and 5. Pin 12 is available if not using the micro SD · 5V compatible, use with 3.3V or 5V logic · Onboard 3.3V @ 300mA LDO regulator Speci�cations: Size: 71*52*7mm Weight: about 31g Libraries Included (Kind of) The shield came packed with one of those tiny CD ROM discs with a few different RAR files on it. The one with “arduino-UNO” in the name seemed like the most likely candidate, so I opened it up and started poking around. After some trial and error, including finding the correct library, changing library names, altering include file references, etc., I managed to get something on the screen. I made many small tweaks to the LCD library to make my life a little easier (see below), but the many references to Adafruit in the code led me to give their web site a look. There I found a library for a 2.8″ touch screen that looks very similar to this one. I’m not sure the code in their libraries will work without modification, but they may be worth taking a look at. Picture Quality I didn’t have very high expectations in terms of picture quality, so I wasn’t disappointed. Overall, I would rate it as good enough for the average hobby project. While you won’t be floored by the rich colors, in the context of price and features, it’s more than sufficient. Compare the original image below to the 16-bit screen representation to its right. While the picture of the LCD screen doesn’t really do it justice, it should give you an idea of what you’ll see. The first thing that will likely draw your attention about the screen image is the very noticeable banding. This becomes less apparent with line drawings using a simpler color palette, but it is very visible when viewing bitmaps or filling the screen with a solid color. SD Card Slot The shield comes equipped with a micro SD card slot, which I really had no real intention of using when I bought it. My curiosity quickly took over, however, and I tried The shield comes equipped with a micro SD card slot, which I really had no real intention of using when I bought it. My curiosity quickly took over, however, and I tried to run some of the sample code. Unfortunately, I didn’t meet with any success during my initial attempts to get it working and threw in the towel completely after pushing a bit too hard on the card as I inserted it, breaking the connector off the board. The next day, I decided to give it another go, so I got out my soldering iron and did my best to reattach the connector, despite the miniature nature of the surface mount pins. I made sure to get plenty of solder on the four legs to keep it firmly attached to the board, then did a less than stellar job of getting a bit of solder on the tiny pins. I took a quick glance with a magnifying glass, and it didn’t appear that I had left any shorted pins, so I tried the sample code again. Much to my surprise, it worked, and before long I was looking at my own bitmap images on my Arduino screen. Using the Shield General I’m still not sure exactly what driver chip my LCD is using. The libraries included with the unit expand into a directory called “arduino-9320”. I originally took this to mean that it used the ILI9320 chip and started working from the data sheet I found here to expand functionality as needed. However, some of the sample code does a driver check before proceeding, as follows: 1 // find the TFT display ? 2 uint16_t identifier = tft.readRegister(0x0); 3 if (identifier == 0x9325) { 4 Serial.println("Found ILI9325"); 5 } else if (identifier == 0x9328) { 6 Serial.println("Found ILI9328"); 7 } else { 7 } else { 8 Serial.print("Unknown driver chip "); 9 Serial.println(identifier, HEX); 10 while (1); 11 } According to the ILI9320 data sheet, register 0x0 will return 0x9320. On my board, I get a reading of 0xC505. I haven’t run into anything that hasn’t worked thus far, so I haven’t done any further research. Disabling the check is good enough for what I’m doing at this point. I have made some modifications to the library included with the board, and I’ll include my files below. It wasn’t until after I’d started monkeying with things and noticing references to Adafruit in the code, that I realized there may be better options already out there. Whether or not they work with this screen is something I have yet to determine. Adafruit libraries here: http://learn.adafruit.com/2-8-tft-touch-shield/overview Displaying Graphics The TFT library includes functions for drawing lines, rectangles, rounded rectangles, circles and triangles, all of which can be filled or outlined. There is example code that cycles through various screen patterns using each. After I got the SD card reader working, I spent some time concentrating on loading bitmaps. The sample code that comes with the library has a few examples that load 24-bit bitmap files from the SD card and display them on the screen in various rotations. These samples didn’t work correctly until I modified the code to use the setPixel method, which resulted in a very slow display time but worked in all screen rotations. The writeData method that was originally being invoked simply writes to the display’s graphics memory, which is a good thing for speed. However, this method was not taking screen rotation into account. Studying the data sheet, I found that “GRAM Access Direction” can be altered such that after a writeData call, the next write address will be properly calculated based on the current rotation. With that information, I modified the setRotation method to also change the GRAM access direction. This new setRotation method fixed the bitmap sample code to some extent and sped things up considerably. Unfortunately, it was still taking 2.8 seconds to load and display a 320×200 24-bit bitmap. It was time to get serious. The firs thing I did was switch away from the 24-bit bitmap format. The display uses a 16-bit RGB format (R5G6B5), so it makes more sense to do that transformation somewhere other than the Arduino if you’re just worried about getting it onto the screen as quickly as possible. Furthermore, the standard Windows bitmap file is stored in a bottom-up format, which adds a little complexity to the direct write method. So, I wrote a little utility to convert my bitmap files to a 16-bit, top-down format that could be directly loaded into the LCD’s GRAM. You can find that utility here. Moving to the 16-bit format had a huge impact on performance, though I didn’t think to take any timings in this state, as I wasn’t quite done. My next step was to simplify loading by getting rid of the position calculations required for bitmaps that didn’t extend the entire width of the screen. The data sheet provides details about creating a window within the screen, which you can specify the dimensions of. Combining this window setting with the GRAM access direction settings mentioned above, it is possible to just send the pixel information in bulk and allow the LCD driver chip handle the wrapping. The end result is fast, loading and displaying a 320×240 scooter image in 1.3 seconds and the smaller picture over the top in 129 milliseconds. I’ve since been experimenting with the sdfatlib library for SD card access, and the results have improved even further, bringing load/display time to 1.048 seconds. I was looking more for a smaller footprint, but I’ll take the the speed as well. Arduino Code 1 void displayBitmap(int x, int y) ? 2 { 3 uint16_t bx, ex, by, ey; 4 uint32_t time = millis(); 5 6 // Raw pixel data starts at position 8 7 bmpFile.seek(8); 8 9 // Save the current viewport settings and set 10 tft.getViewport(&bx, &ex, &by, &ey); 11 tft.setViewport(x, y, x + bmpWidth - 1, y + bmpHeight - 1); 12 tft.goTo(x, y); 13 14 // Bulk write data to LCD, loadBitmapData is a callback to refill buffer 15 int bytesRead = loadBitmapData(NULL); 16 tft.bulkWrite( (uint16_t *) picBuffer, bytesRead, loadBitmapData, NULL); 17 18 // Leave the viewport like we found it 19 tft.setViewport(bx, ex, by, ey); 20 21 Serial.print("Total time: "); 22 Serial.println(millis() - time, DEC); 23 24 } TFT Driver Code Addition 1 // Writes 16-bit data in bulk, using callback to get more ? 2 void TFTLCD::bulkWrite(uint16_t *data, uint16_t bufferSize, uint16_t (*getNextValues)(void *), void *userData) 3 { 4 *portOutputRegister(csport) &= ~cspin; 5 *portOutputRegister(cdport) |= cdpin; 6 *portOutputRegister(rdport) |= rdpin; 6 *portOutputRegister(rdport) |= rdpin; 7 *portOutputRegister(wrport) |= wrpin; 8 9 setWriteDir(); 10 while( bufferSize ) 11 { 12 for(uint16_t i=0; i < bufferSize; i++) 13 { 14 writeData_unsafe(data[i]); 15 } 16 bufferSize = getNextValues(userData); 17 } 18 *portOutputRegister(csport) |= cspin; 19 } Touch Screen The display and touch screen features were what I was really looking for from this LCD, though I became somewhat sidetracked by the bitmap examples. The touch screen example software ran pretty much without a hitch from the beginning using the pin settings for the shield. Essentially, you get two coordinates (X and Y) back from the screen, plus a Z, which indicates the pressure being applied. Those coordinates coincide with the LCD’s default rotation, which is with the Arduino’s USB plug on top in this case, so you’ll have to adjust those for yourself. 1 #include "TouchScreen.h" ? 2 3 // These are the pins for the shield! 4 #define YP A1 // must be an analog pin, use "An" notation! 5 #define XM A2 // must be an analog pin, use "An" notation! 6 #define YM 7 // can be a digital pin 7 #define XP 6 // can be a digital pin 8 9 #define MINPRESSURE 10 10 #define MAXPRESSURE 1000 11 12 // For better pressure precision, we need to know the resistance 13 // between X+ and X- Use any multimeter to read it 14 // For the one we're using, its 300 ohms across the X plate 15 TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300); The one potential area for trouble is the fact that the touch screen shares pins with the LCD. So, if you invoke methods from the touch screen library, then make calls to the LCD library, you may get unexpected results, as the touch screen library doesn’t always leave things in the right state, and the LCD library doesn’t put them in the right state before it does its work. The newer Adafruit libraries may account for this better than the ones I’m using, but I’ve worked around it for now. At this point, I’ve done a little bit of experimentation with the touch screen, mainly in the form of a numeric input form, as shown below. I’ve tried to do some coordinate calibration based on actual readings, but it seems like I get some occasional outlying values that throw a wrench in things. So, I’ve pretty much stuck with the default values from the sample code and haven’t had any problems getting very reliable finger positions. the default values from the sample code and haven’t had any problems getting very reliable finger positions. A question was brought up in the comments regarding debouncing the touchscreen input to avoid getting repeat presses. Trying to reliably detect when a user presses and removes a finger from the screen in all cases has proven to be more difficult than I thought. This is the code I’ve written so far, which does a decent job of registering intentional finger presses with minimal duplication. When I have more time, I’ll see if I can improve it a bit. 1 Point getPressPosition() ? 2 { 3 4 Point p, q; 5 int upCount = 0; 6 7 // Wait for screen press 8 do 9 { 10 q = ts.getPoint(); 11 delay(10); 12 } while( q.z < MINPRESSURE || q.z > MAXPRESSURE ); 13 14 // Save initial touch point 15 p.x = q.x; p.y = q.y; p.z = q.z; 16 17 // Wait for finger to come up 18 do 19 { 20 q = ts.getPoint(); 21 if ( q.z < MINPRESSURE || q.z > MAXPRESSURE ) 22 { 23 upCount++; 24 } 25 else 26 { 27 upCount = 0; 28 p.x = q.x; p.y = q.y; p.z = q.z; 28 p.x = q.x; p.y = q.y; p.z = q.z; 29 } 30 31 delay(10); // Try varying this delay 32 33 } while( upCount < 10 ); // and this count for different results. 34 35 p.x = map(p.x, tsMinX, tsMaxX, 0, 239); 36 p.y = map(p.y, tsMinY, tsMaxY, 0, 319); 37 38 // I've been focused on rotation 3, with the USB connector on the right-hand side 39 // so, you'll have to add your own code here. 40 switch( ROTATION ) 41 { 42 case 3: 43 swap(p.x, p.y); 44 p.x = (320 - p.x); 45 break; 46 } 47 48 // Clean up pin modes for LCD 49 pinMode(XM, OUTPUT); 50 digitalWrite(XM, LOW); 51 pinMode(YP, OUTPUT); 52 digitalWrite(YP, HIGH); 53 pinMode(YM, OUTPUT); 54 digitalWrite(YM, LOW); 55 pinMode(XP, OUTPUT); 56 digitalWrite(XP, HIGH); 57 58 return p; 59 } SD Card As I mentioned, the SD card wasn’t something I was necessarily looking for from this shield, but it has proven to be a blessing. It works with the standard Arduino SD library, and I’ve also tried the sdfatlib with great results. The cable select should be set to pin 10, and after that, you’re ready to go. There is an example called “listfiles” that spits out a directory listing, which is great for both testing that the card works, and as a reminder that you’re limited abbreviated file names that turn a name like “BURG_BLUE.BMP” into “BURG_B~1.BMP”. Source Code I have attached the TFTLCD libraries with the modifications I’ve made for rotation and positioning reliability as well as the bulk data load function I’m using for displaying bitmaps. Sample sketches are also included and should work with this LCD without modification. There seem to be variants of this shield that look the same or similar but function differently. Many users have had issues with reversed text and coordinate flipping using the same library I originally provided. In the comments, Mike McCauley added a link to a patched version of the library that may fix reverse coordinate issues. I have now added his patch into my library to avoid further confusion. Click here to download: TFTLCD.zip If your coordinates appear to be reversed, uncomment either or both of the lines below in TFTLCD.cpp and try again. 1 //#define INVERT_X ? 2 //#define INVERT_Y Thank you to everyone who has participated in the comments and helped �nd solutions to make this board useable for everyone. Update – June 26, 2014 I was able to get this screen working as a shield with an Arduino Mega 2650 as well. I posted an article with an updated source file. Until I get some feedback, I’ll consider it experimental. The article is here.       You may also like:

Description:
Touch Screen Shield for Arduino UNO. Features: · 2.4″ diagonal LCD TFT display. · Bright, 4 white-LED backlight, on by default but you can connect
See more

The list of books you might like

Most books are stored in the elastic cloud where traffic is expensive. For this reason, we have a limit on daily download.