Summary of Project
Utilizing at ATmega328P as well as an RS-485 Transceiver Chip as the brains, I’m building a handheld device to generate valid DMX512 serial signals for testing theater equipment on the fly without the need for setting up and manning a full lighting board. This is the first significant project I am building on perfboard and while to me it looks kind of messy, I’ve actually received a lot of praise for it, surprisingly, it is however incomplete, been too busy to put the remaining connections in and the firmware is definitely not ready yet. Soon!
Type of Project
Build a handheld device with a keypad, LCD, internal batteries and XLR 5 pin male connections that can generate standard DMX512 signals. This device will be able to connect straight up to standard digital theater dimmers such as those made by Electronic Theatre Controls (ETC) for quick diagnostics and testing. The device will accept basic commands mimicked after ETCs Lighting Board commands so that multiple channels may be tested at a time.
The DMX512 protocol is a very simple protocol based around standard asynchronous serial. It is hard-coded to run at 250kbit/s, and has a frame consisting of 1 start bit, 8 data bits, 2 stop bits and no parity. This can be easily emulated by a UART with a sufficient clock speed, which is made only slightly difficult because it operates outside the standard speed range. The other difficult part is the long Mark-After-Break (MAB) required to start the frame. It seems necessary to manually drive the I/O lines to generate this indicator before enabling the UART drive the signal pin. Finally, the device uses RS-485 Differential Signaling, but this is easily handled by a specific transceiver chip, or even some logic gates. Once the frame has been started, 513 bytes follow, the first byte identifying the type of packet, the next 512 bytes correspond to the 512 DMX channels. This takes about 23 ms to accomplish.
This project is powered by an ATmega328P microcontroller, in a 28-pin DIP (Dual in-line package) form factor. I’m using the internal RC oscillator at 2MHz, since that is the lowest frequency that can generate the required data rate of 250kbit/s specified in the DMX512 Protocol. This may change later once I see if there’s a problem with clock drift and dimmers responding. Currently I’m using the controller in a 5V configuration, I may switch to something lower later when I’m running on batteries, but for now this works out just fine.
For a display I’ve dug in to my bin of random parts and come up with a 16×2 Character LCD, standard parallel interface to an HD44780 clone, with a green backlight, black text. Pretty basic. For the breadboard prototype I used a different LCD that was already wired up, but I intend to use that for a different project as its got a cool ice blue backlight and white text, and it fits the other project better. Nothing special here, the LCD is wired up in 4-bit mode, and I dug out some old firmware I’ve written to drive it. It’s also running on five volts and so far I’m just going to have the backlight powered when the device is turned on.
For this project I’m using a MAX481 RS-422/RS-485 Transceiver IC from Maxim Semiconductor. This device takes on transmit input and generates two transmit outputs (1 transmitter) and takes 2 receive inputs and generates 1 receive output (1 receiver). RS-485 is a balanced connection, so you’re sending the data bit, as well as its inverse, across two wires, with a third carrying ground. This scheme allows much longer data runs as a considerably higher voltage drop is acceptable before data integrity is compromised. This chip simply takes my TTL serial signal in, and generates an RS-485 compatible signal on the output, for sending the signal to the dimmers. I did not use the receiver for this project.
For user input I picked up a cheap 4×4 keypad from Futurlec (here, I used the black 4×4 one currently on the bottom) and wired it up to some ribbon cable with a nice IDC female header on the end. This is a basic array of pushbuttons, and it’s interfaced with a simple matrix scan routine. Essentially, the buttons close connections between rows and columns, 4 pins for each. I connect the 4 row pins to four inputs on the microcontroller, which has internal pull-up resistors, so those inputs read as a 1 when not being driven high or low. The 4 column pins are connected to output pins on the controller, which are driven low one at a time, in a timer controlled sequence. Any column not driven low is driven high. As a result at any given moment the wires going to the column pins are set so three are driven high, ones pulled low. When a button is pressed and the corresponding column pin is driven low, the row output, now electrically connected to the column input, is pulled low. An interrupt is called on the controller by the falling edge on the input. By checking the currently active column (which stops cycling as long as a button is held) against the row that is being held low, the key can be determined.
The firmware has a few specific jobs to accomplish:
- Scan the keypad for button presses using the matrix scanning routine, recognize when a button is pressed, this must be prioritized.
- When button is pressed, it needs to handle it as soon as the processor is available.
- Initialize and control the character LCD, it needs to handle this as soon as the processor is available.
- Generate the Mark-After-Break and DMX packet, this is prioritized but lower than the keypad scan, DMX512 has a wide tolerance for latency.
With these goals in mind, the firmware uses a combination of interrupts and polled systems to make sure the keypad scan and data sending is done when it needs to be. The keypad scan routine uses a timer interrupt to rotate the column being driven low among the four using a simple state machine. On the other end an interrupt detects if any of the row signals experience a falling edge. That interrupt uses a look-up table to push a known character on to a buffer, and holds the scan routine until the button is released.
The LCD code is a simple group of functions based around sprintf() that is used to take format strings and variables and create null-terminated strings. Once these strings are created, they are looped through and each character is transferred to the LCD one at a time using the 4 bit data bus and the 2 control lines. These functions also include a function to initialize the display. This posed some problems because initializing the display from a cold start (defaults to 8 bit mode) after power was removed is different then initializing it from a warm start (already set to 4 bit mode) after only the microcontroller was reset/unpowered. I got around this by blasting the display with init commands to forcibly reset the display to 8 bit mode, before running a standard initialization for 8 bit to 4 bit mode. This has no effect on a display in 8 bit mode, and sets a display in 4 bit mode to 8 bit mode. This guarantees a known starting point and allows the initialization to work without having to power-cycle the LCD. This wasn’t really important, but it made debugging faster because I could just re-flash the chip and let it reset.
The code to generate the DMX packet is done, its simply based around the UART transmit complete interrupt. When the Mark-After-Break is generated, a byte will be sent after, from then on, the interrupt will then load the next channel in to the transmit register until the first 511 channels have been sent, at which point a flag will be cleared to disable the interrupt, and the last channel loaded in to the transmit register. The main loop will poll status flags to decide if and when to send the next packet, initiated by the Mark-After-Break function that will, as mentioned earlier, set off the self-running UART.
Hardware – Design
I drew up a formal schematic for this, but I seem to have lost the file, I whipped this up real fast, it’s a little messy, but it’ll do for now. I’ll do a better one with busses and such later on.
Hardware – Breadboard Prototype
Once I had the basic design down (see above) I soldered up the ribbon wires for the peripherals and grabbed a breadboard. Here you just see the LCD (currently disconnected, but its connections are under it), the Keypad and the AVR. I’m not using the level converter yet in this design, I trust it works so I more concerned with serial output. Also, this is where I debugged the matrix scan routine. I used this platform to get all the bits and pieces to talk together, I’m using a USB Serial breakout board called the BBUSB, from Smiley Micros, just to provide power. The AVR-ISP programmer I’m using isn’t connected to this board (used it for something else before I took the photo) but it was connected in the same manner as the display and keypad.
Hardware – Perfboard Prototype
With all the peripherals working, I decided to go ahead and start building the first semi-permanent prototype. It is not yet complete due to a very busy schedule, soon though! Right now it has the sockets for the microcontroller, and the level converter IC, as well as the 2×8 header for the LCD. The connections are in place for power and communication, as well as a current limiting resistor for the LCD backlight, and a 120 ohm load resistor for the driver IC, recommended in it’s datasheet.
Relevant Blog Posts
I really dislike Perfboard – 2/2/2010
Another page up! – 2/10/2010