热度 17
2016-4-29 17:59
2496 次阅读|
0 个评论
Our Caveman Diorama is going to boast a Time Portal, thereby explaining my presence in the scene. Cardboard prototype of Time Portal (Source: Max Maxfield Mike Mittlebeeler) Well, we've finally gotten around to powering up our 2.8" display from Adafruit and, as usual, there are a few "ups and downs" to ponder. With regard to the display itself, this is a TFT LCD touchscreen on a breakout board with a Micro-SD card socket mounted on the back (we're not planning on using the touchscreen capability). We're currently driving this using an Arduino Uno, but we'll be swapping over to an Arduino Nano when we come to deploy this little scamp in the cave. As always, Adafruit supplies great support in the form of wiring diagrams and instructions, libraries, and example sketches. The display itself can be driven using a variety of techniques, including a fast 8-bit parallel interface and a slower SPI interface. In our case, we wish to display a series of BMP files that will be stored on a Micro-SD card plugged into the back of the breakout board. The idea is to alternate between a Stargate mirror effect image and hundreds, perhaps thousands, of random images showing things like alien landscapes, post-apocalyptic scenes, and weird, wonderful, and beautiful visions of the past, present, and future (as you can see, we don’t believe in limiting ourselves). For some reason, Adafruit only supports the display of BMPs using the SPI interface, which is slower than the 8-bit interface approach. Since observers will be looking downwards towards the Time Portal in the diorama, this means that we want the SPI interface and any associated wires to be on the bottom of the display so as to be minimally visually intrusive. Based on this, the first question we had was "Which way up will the images be displayed?" If the images were to appear upside down, for example, then we would have to pre-invert them on our host computer before copying them over to the Micro-SD card. Thus, we started out by creating a small 40 x 80 pixel image with different color blocks in diagonally opposite corners and displaying it at X-Y location on the display. Happily, this image appeared in the desired location and orientation as illustrated below. (Source: Max Maxfield Mike Mittlebeeler) We had originally envisaged the portal as appearing to be levitating above the floor of the cave. If you look at the image above, however, you will observe a black border around the actual image. This is quite narrow at the sides and the top, but it's pretty significant at the bottom of the display. This dictates the minimum width of the door frame at the bottom. I was just on the phone to my chum, Adam Carlson (a.k.a. AerospaceEngineer). Adam is creating the 3D printed door frame for the portal. If we made the entire frame as wide as it needs to be at the bottom, then it would be overwhelmingly out of proportion to the actual display area. Thus, we are now thinking of mounting the portal on a small pedestal standing on the floor of the cave with integral steps coming down from the display, thereby disguising the size of the bottom lintel. Adam will be throwing some preliminary sketches together over the weekend and we'll take things from there. The next step was to see how fast the images can be displayed, so we loaded two full-size (240 wide x 320 high) images onto the card. The first was a Stargate mirror image; the second was of the back of a man sitting on a chair viewing a post-apocalyptic vista as illustrated below. (Source: Max Maxfield Mike Mittlebeeler) We then tweaked the example sketch from Adafruit so as to alternate back and forth between these two images with a one second pause between each reload. The result is shown in this video . As an aside, Adafruit's libraries require us to use 24-bit color BMPs, which means each image consumes 3 x 240 x 320 = 259,200 bytes. Since there are 1,048,576 bytes in a megabyte (MB), this means we can store four images per megabyte. I predate the days of 3.5" floppy disks that could store only 1.44 MB of data, so my knee-jerk reaction was to ruminate on the fact that I would have been able to store only five of our (uncompressed) BMPs on a single floppy. How times have changed. Looking at this another way, since we can store four images per megabyte, this equates to 4,000 images per gigabyte, which should be more than enough for our needs. So I trotted down to my local Staples store looking for a 1 GB Micro-SD card, only to discover that the smallest card they offer stores 16 GB (I think it cost around $10). This means we can store 64,000 BMPs on our Micro-SD card, which should keep us busy for a while (LOL). It's not-so-long-ago that 16 GB would have been an almost unimaginable quantity, and the fact the Micro-SD card is about the same size as my fingernail makes things even more surreal, but we digress... We had originally hoped to be able to have the default Stargate mirror image somehow "rippling" on the screen. We had also hoped to be able to perform some sort of crossover-fade effect from the mirror image to the scene images, and vice versa. As you can see in the above video, however, it actually takes about four seconds to present each new image onto the display. This occurs as a slow "wipe" starting at the top of the display and working its way to the bottom. The image below shows the "Man on Chair" image (top) in the process of being "wiped" over the "Stargate Mirror" image (bottom). (Source: Max Maxfield Mike Mittlebeeler) On the one hand, we can certainly live with this; on the other hand, it would nice if we could do it better (e.g., smoother, faster, more interesting transitions). This is where you come in. We've reached the limit of our programming skills. This time-portal-stuff.zip file contains the two 240 x 320 BMPs we've been playing with, the Adafruit_GFX (graphics) library, the Adafruit_ILI9341 (display) library, and the Time_Portal_01 sketch, which is based on Adafruit's SPI BMP display example sketch. In the case of the rippling mirror effect, could we achieve this by drawing expanding circles using the graphics library rather than by displaying BMP images? Alternatively could we start off by displaying the BMP, and then "tweak" individual pixels using the graphics library to provide some sort of visual interest? Any suggestions here would be very much appreciated. Furthermore, in the case of transitioning to a new BMP image, is there anything we can do to speed things up? Looking at Adafruit's sketch, it seems that there's a lot of error-checking to make sure the BMP files are of the right size and format and suchlike. Since we know our BMPs are all going to be guaranteed to be 240 x 320 x 24-bits, and they will all be generated in exactly the same way from Paint.net, can we strip out a lot of this error checking and -- if we do so -- will this speed things up? It may be that we are fundamentally speed-limited by the fact that the Arduino Uno (and Arduino Nano) has only 2 KB of SRAM. As we've already discussed, each of our BMPs is 3 x 240 x 320 = 259,200 bytes in size. This means that we have to bounce back and forth streaming small groups of pixels from the Micro-SD card and writing these pixels to the display. If we do have this fundamental limit, it may be that we can still achieve a more interesting image-to-image transition effect. We don’t know how BMP files represent their data, but let's visualize it as being something like the following: (Source: Max Maxfield Mike Mittlebeeler) It would be nice if we could read out pixel data from any specified location from the BMP file and write that data to any specified location on the display. However, our understanding is that we can do the latter, but not the former. That is, we think that when we open the file on the Micro-SD card and start reading pixel data, this data is presented to us (something like) in the order , , ... , , , , ... , ... , . But what if we created a simple pre-processor program on the PC that could take our original BMP file, "shuffle" its contents in some way, and generate a modified BMP file as output? (Source: Max Maxfield Mike Mittlebeeler) If our sketch running on the Arduino "knows" that the data will be presented in this way, it could read Row 0 from the file and write it to Row 159 on the display, read Row 1 from the file and write it to Row 160 on the display, and so forth. This would mean that the new image would "wipe" over the old image starting from the center and working outwards, which -- we think -- would offer a much better effect. Maybe we could go even more sophisticated than this -- starting at the center of the display and working outwards in all dimensions. What do you think? Is this possible and -- if so -- can you help us to achieve it?