博客首页 | 排行榜 |

设计我最赞的博客

个人档案
博文分类
仿人类远程控制-I(Dynamic Animatronic Remote (Part 1))  2008-09-08 12:23
Build a Custom Controller with a Color LCD

Peter built a custom controller that enables him to remotely control his animatronic systems. Each piece of hardware is controlled by a separate computer program. The remote polls his laptop and builds menus that show and control the state of each program.

Every year, I put on an elaborate Halloween show in my front yard (see Photo 1)。 Being electronically minded,my fully automated show includes a talking skeleton and crow, sound effects, and more. (In Circuit Cellar Issue 188, 2006, I described the animatronic controller I built for operating and controlling the props.) My system uses a laptop to coordinate the show,and it talks to several distributed microcontrollers via an RS-485 serial link. A custom packet format and messages enable PC programs to control the distributed hardware. It works great once it‘s dialed in, but getting it dialed in can be difficult.


Last Halloween, I experienced some problems. The show wasn't working properly and I was going nuts trying to fix it. I found myself running maniacally back and forth from my house to the yard. Why? The computer used to control the show was inside and the hardware was outside. Plus, because I had darkened and covered my windows to make the house look spooky,I couldn‘t see or hear what was going on outside. Thus, trying to set the appropriate levels for sound and lighting was a nightmare.

Prior to last year's show, I had been thinking about building a remote control that would enable me to modify the running show from outside by plugging into the same RS-485 network that controls everything. However, I knew building such a system would be tricky. One of the hallmarks of the Halloween control system is that there is not one monolithic program running on the computer that controls everything. Instead, individual programs run independently that conform to the rules of my Halloween serial network. This enables them to send and receive packets,control hardware nodes, and play sound files as needed. Thus, while considering my options, it became obvious that building a "hard-wired" remote control to handle the show wouldn't work. I knew I needed to be able to add and subtract programs at any time, so designing a remote dedicated to a specific program(or programs) would mean I‘d have to constantly modify the firmware to keep it in sync with the ever-changing computer software.

I recently designed a dynamic remote control that meets all of my requirements (see Photo 2)。 The remote can connect to the network,control programs on the computer,and handle new programs. It can poll the computer, find running programs,poll the PC again after program selection,and then build menus on the fly to show program status and enable modifications.


In this article, I'll describe how I designed the custom controller with its color LCD. Next month, I‘ll cover the software and menu code.

DYNAMIC SYSTEM
I wanted to design a dynamic system. Years ago, Apple created a specification called Publish/Subscribe. I always liked the sound of that because it seemed clear what was going on just by the name. I co-opted the name and created a Publish/Subscribe system that integrates into my Halloween serial network.

When I started this project, I figured that I could bang out the design in a few weeks, especially because I was leveraging so much software that was already written. Right. It took me more like three months. It was trickier than I thought for a number of reasons.

My original plan was to support only a few GUI elements on the PC,such as the scrollbar, checkbox, and combo box. I also decided at the beginning that the menu system displayed on the remote would have a limited depth and hierarchy. My initial plan was to have a top-level menu that enables me to tell the remote to find programs running on the PC and then click down a level to see them. It would look something like what you see in Figure 1a.


That changed. Once I got the initial system up and running, I realized that I needed to support a few more GUI elements. I also realized that I wanted to have a submenu of parameters. This way, I figured, I would be able to group things more logically. I decided that a single submenu down would be sufficient to let me group together various elements. I thought this would be relatively simple to implement because the specifications were limited (see Figure 1b)。That also changed. Again, once I got the basic two-level system up and running, I quickly realized how useful it would be to have a much deeper and more flexible menu system. I wanted the flexibility to lay out any menu system I pictured in my head. Tests with some fake prototype PC programs showed me that I would need to expand the number of GUI elements supported. So, I plunged into the third rewrite of the menu system.

Some engineers would see this as"feature creep." I disagree with this assessment because the original problem was that I thought I could get away with something that was simple to program, when in reality, I needed something that was simple to use. Forcing all of the controls onto a single scrolling menu page would mean a lot of scrolling up and down when looking for parameters to modify. There is often an inverse relationship between ease of use and ease of programming. This was just another example of this paradox.

DESIGNING THE REMOTE
One of the first tangible things I did was mock-up the remote using CodeGear‘s Delphi (see Photo 3)。 The interface builder in Delphi is simple to use. (There are others, but I prefer Delphi.) It enables me to play "whatif"games quickly. My goal was to figure out what the remote‘s front panel was going to look like. I knew that it would have an LCD. I also knew it would have buttons. The questions were: How many buttons, and what would they do? Would I need a full 10- key keypad? What about an Enter key notifying the remote about a chosen value?


After some experimentation, I came up with the design shown in Photo 2. The remote has an LCD at the top and three buttons arranged vertically below it. The buttons are labeled Back, Menu, and Value (from top to bottom)。 What isn‘t shown is that the actual remote also features a scroll wheel on the side. It's implemented as a knob attached to a rotary encoder. Ironically, some time after I finalized this design, my wife gave me an Apple iPod nano. I realized after playing with it that the Apple designers used a similar concept. It‘s always nice to know you're in good company.

No aspect of the interface was random. I put the scroll wheel on one side and the buttons on the other. So, I don‘t have to choose between the buttons or the scroll wheel. I can work both at the same time. The buttons are arranged vertically so I can reach them by simply moving my thumb without shifting my grip. As for moving through the menu, I descend down and ascend out of it. Thus, the Back button is at the top so I"ascend" to return. The middle button is the Menu button, which lets me descend down to deeper menus. The physical relationship between these two buttons suggests the up/down nature of traversing the menu hierarchy.

The Value button at the bottom enables me to modify parameter values. The button is implemented as a shift style key because it modifies the behavior of the scroll wheel. If the key is up, the scroll wheel moves a highlight up and down the menu to let you know which line is active. If you hold the Value key when you're located on a parameter, moving the scroll wheel modifies the parameter‘s value. To keep the remote simple, I didn't include Enter and Cancel keys. This isn‘t a fighting video game, so elaborate key combinations are not the order of the day. I wanted a an easy-touse,clean, simple, elegant design. I succeeded.

THE DISPLAY
I have been using LCDs in my projects for years; however, they've always been black and white character displays. For this project, I upped the ante. I used a graphical color LCD.

Prior to starting this project, I‘d seen some reasonably priced LCDs advertised in magazines and on the Internet. How hard could it be to find the right one? It was hard-well,at least harder than I thought it would be. The problem with many advertisements is that the fine print tells you that the great price is available only if you're buying 1,000 or more units. There are a lot of interesting,inexpensive surplus LCDs for sale on the Internet. The problem,however, is that you get only an LCD. In some cases, they come with PCBs with LCD driver chipsets. That‘s a move in the right direction,but it still requires you to locate the chipset's datasheet, figure out how to program it, and then write code from scratch just to do things like draw a straight line. You can see why black and white character LCDs are so appealing.

Fortunately, I discovered Display3000,an Internet LCD vendor located in Germany. While the name may sound like something from an infomercial,the web site promised a good product at a good price. Specifically, I got a 2.1″ diagonal, 16-bit color LCD with a backlight. The display came with a small carrier board that did all of the required level shifting, enabling me to send data signals from 2.5 to 15 V and power the backlight with anything from 5 to 18 V. It also came with source code in both BASIC and C,which implemented a driver that included support for lines, circles, rectangles,bitmaps, and fonts. It was driven via a SPI, so it didn‘t take too many I/O lines. It cost me about $100 with shipping.

I was pleased when the LCD arrived. In addition to the full driver, I got a super-simple driver that implements the SPI as a few bit-banged I/O lines and displays only a yellow background with a blue line in the center. It really helps to have something dead easy to help get the display up and running on your platform. In my case, I was using a Zilog Z8 Encore. The C code from Display3000 was specifically written for the Atmel processor line. After using Google to figure out what some of the Atmelspecific macros were doing, I was able to get the simple driver up and running in a short amount of time.

The display was kind of slow due to the bit banging, but it enabled me to have a framework that I knew worked. From there, I switched it over to using the Z8 hardware SPI. When that was working, I took the SPI-specific code (software and hardware versions) and swapped them into the full driver code. I then got the software SPI version of the full driver working and finally switched it over to the hardware SPI. It was a nice, logical progression that took me from simple to full-blown over a couple of sessions of work without getting me too frustrated in the process.

Once I knew how to control the Display3000 LCD, I decided to create a serial backpack for it (see Figure 2)。Rather than have the LCD attached directly to the project via the SPI lines, I wanted a separate processor to run it via high-level commands sent over a UART. A big part of my reason for doing this was that I knew the menu system of the remote was going to require a lot of RAM, and the display system for the LCD would require the same. By splitting it into two separate projects, I got the full complement of RAM for each project because each had its own Z8 running it.


Before I got the color LCD, I borrowed an old Scott Edwards Electronics serial black-and-white graphical LCD from my friend Jon Williams. I used it for early prototyping. It was a 128 × 64 pixel display that also implemented a 4 × 16 text font and ran at 9,600 bps. It didn‘t take long to get it up and running. I decided early on to isolate the details of the LCD commands from the overall remote project by creating an LCD abstraction library. The idea was to have the remote call the library for doing things like clearing the display,setting a cursor position, writing text, and more. The library would take care of the LCD-specific commands needed to implement numerous functions. It would enable me to swap in a different LCD by simply taking the existing library and modifying it to speak whatever native commands the new LCD required.

This abstraction layer turned out to work beautifully. Once I had the Display3000 serial backpack code working, I took the LCD abstraction library for the Scott Edwards LCD and, in literally 10 min., converted it to use the commands needed for my Display3000 LCD serial backpack. There was more work required after that to add features (such as setting colors, something the black and white display didn't need), but it was cool to have the color LCD showing the menus for the remote in such a short amount of time.

THE MAIN BOARD
While I was waiting for the LCD to arrive from Germany, I used the Scott Edwards display and forged ahead with my main project board. A month earlier,I had created a simple demonstration PCB for the 64K series of Zilog Z8 Encore chips. (The chips are a perfect fit for most of my projects because they have a lot of RAM by embedded standards.) I used a Z8F421, which has 48 KB of flash EEPROM and 4 KB of RAM (see Photos 4a and 4b)。 Most similar controllers from other companies tend to have only 2 KB of RAM. Because this project involved a lot of serial communication (multiple RAM ring buffers) and a dynamic menu system (the menus were created in RAM), I needed as much RAM as possible.


It‘s a bonus that Zilog offers development kits at amazing prices ($50)。 The development kit I used comes with a serial or USB programmer/debugger,along with a full-blown IDE and C compiler. Unlike many other companies,the Zilog compiler doesn't become feature-limited after a certain number of days. It offers free upgrades,and Zilog has upgraded the IDE and compiler multiple times over the years. This is not a dead-end product.

After getting the code working and stable on my demonstration board, I created a new hardware design just for the remote. I found an extremely cool-looking case from OKW Enclosures(www.okwenclosures.com), and I wanted a board that was custom fit to it. I decided to go for broke and use the surface-mount version of the Z8, even though it also comes in PLCC and DIP packages. The Z8 runs on 3.3 V, so there is a simple 3.3-V linear regulator, along with the Z8F421, an 18.432-MHz oscillator, a Maxim Integrated Products MAX3491 RS-485 transceiver, various I/O connectors,and the push buttons for the interface. The main schematic for the remote is shown in Figure 3. The RS- 485 circuit for the remote is shown in Figure 4.

Figure 3-This is the top-level schematic for the remote.



Like most of the boards I lay out, I put in some "future proofing." Even though I needed only a single column of three buttons, I put a matching column on the other side of the PCB in case I want more buttons. I also added a 2 × 8 0.100″ center header that carries the I/O pins for port E. It takes a little extra time to route these devices on the PCB, but they come in extremely handy after the PCB is fabricated and you want to add a new feature.

One element of this PCB made it slightly tricky. I checked and found out that there wasn‘t a lot of room between the PCB and the top of the OKW case. While there was plenty of space for the switches and ICs, things like jumpers or bulky connectors could get dicey. So, I decided to lay out the board with the switches and power LED on top and all of the other components on the bottom. Routing got a little weird. I had to keep reminding myself that even though two package outlines crossed each other, it wasn't a problem because they were on opposite sides of the board.

I/O CODE
I wrote my own serial library to run on the Z8. It understood how to send and receive the packets used in my Halloween network long ago. With some basic modification, I also created a text-specific serial library. The first bit of truly new code was written to support the scroll wheel. I perform quadrature decoding of the encoder using two I/O lines and a hardware timer running at 30 kHz. Whenever the timer generated an interrupt, the interrupt handler reads the state of the encoder, merges it with the state of the encoder from the previous interrupt shifted to the left two bit positions, and feeds that into a look-up table. The look-up table and code to use it look like Listing 1.


The look-up table and the timer effectively oversample the encoder output. They also determine not only which way the encoder is turning,but also if the transition from the previous state to the current state is legal or bogus. This eliminates any problems that occur if the encoder stops with the disk partially covering the optical sensor. This can create a condition where the clock toggles high/low, making it seem as though the encoder is moving when it‘s simply the electronics being unable to settle on a logic state. Similar problems occur with contact bounce on a mechanical encoder. Any time this happens, the look-up table will simply return zero. Thus,the encoder position variable doesn't show a change in position. A nice plus is that every clock edge generates a pulse, multiplying the resolution of the encoder four times.

After that was working, I wrote the code to handle the debouncing of the three button inputs. With the input side of the hardware and software working, I started tackling the remote code-specifically, the menu system needed for this project. I did some research on the Internet and in Circuit Cellar. Aubrey Kagan wrote an excellent article about implementing a menu system for projects using embedded processors and LCDs ("Hierarchical Menus in Embedded Systems," Circuit Cellar 160, 2003)。 His system was designed to be a general-purpose menu system where the menus were hard-coded into the source code. While I needed some menus embedded in the source,I knew most of my menus would be generated on the fly from information sent by the PC to the remote. I gleaned a number of useful points from his article. But ultimately, I implemented a different system written from scratch that had different goals in mind.

Finally, the foundation for this project is finished. My hardware is up and running, and I can read the scroll wheel and buttons. I also have a basic strategy for my menu code. Next month, we‘ll walk through the land of software. I will tie everything together and explain how the menu code actually works. I'll also describe the design decisions I made while I was trying to create a flexible and dynamic menu system.

Author's note: For videos and additional photos of the show in action, go to my
web site: www.socalhalloween.com

Peter Montgomery (servoanimation@socalhalloween.com) spent 12 years working as a visual effects supervisor on films such as Mortal Kombat and Ace Ventura: When Nature Calls before becoming a director. He has directed dozens of commercials and
made the transition to episodic television with The Disney Channel's Lizzie McGuire. Self-taught in both programming and digital hardware design, Peter uses his super powers only for good, not evil.

PROJECT FILES
To download code, go to ftp://ftp.circuitcellar.com/pub/Circuit_Cellar/2008/218.

SOURCES
Delphi IDE
CodeGear
www.codegear.com

D012 Display module
Display3000
www.display3000.com/html/english.html

Custom panel
Front Panel Express
www.frontpanelexpress.com

Z8F4821 Microcontroller
Zilog, Inc.
www.zilog.com
类别:数据采集 |
上一篇:飞行控制(Flight Control) | 下一篇:模拟与数字碰撞在哪(Where Analog And Digital Collide)
以下网友评论只代表其个人观点,不代表本网站的观点或立场