• Every project needs some blinking LEDs. This one has 300!

    LEDs

    LEDs of the LED Matrix

    This 10×10 LED Matrix has 100 serially connected WS2812B LEDs which are controlled by an LPC11U24 microcontroller. The µC receives commands and image data from the PC via USB. The frame measures 400x400x35mm and is constructed from lasercut wood panels and holds without screws or glue. The grid dividers have been painted white to maximize light reflection. Initially I planned to cover the front with frosted plexiglas, but when I glued paper onto the grid during construction, the realized that it may look even better with a nice paper as the diffuser.

    The WS2812B leds came on a 2m long self-adhesive strip with 60 LEDs per meter. To mount them to the woodpanel, the strip was cut between each LED and attached to the wood. To bridge the gaps, 3 wired cable pieces were soldered to the LEDs in a serpentine layout.

    LED Matrix LEDs Closeup

    LED Matrix LEDs Closeup

    LED Matrix LEDs Closeup

    LED Matrix LEDs Closeup

    Controlling the LEDs is done via a one-wire serial protocol which is simple but has rather strict timing requirements. A one-bit is high for 0.8µs, then low for 0.45µs while the zero-bit is high for 0.45µs and then low for 0.8µs. To set the color of x LEDs, x * 3bytes are sent from the µC to the first LED in GRB order. The first LED takes the first three bytes and sets its three constant current sources accordingly. All following data is passed on to the next LED after the signal has been reshaped. This repeats for all LEDs on the line. To start over, the data line is pulled low for at least 50µs, after which the first LED is again ready to accept data.

    There are several ways to produce the required timing: If the µC is fast enough, one can just use delays of the appropriate length. If the µC is just fast enough, the delays have to be handcoded in assembler (see the Adafruit NeoPixel Library for reference). A third way uses the State Configurable Timer available in some LPC µCs (see this forum post on LPCware.com).

    My solution (adapted from this code on GitHub) uses the built-in SPI hardware of the LPC to generate the correct timing by setting the wordsize to 15bits and then transmitting

    • 111111111100000 for a one-bit
    • 111110000000000 for a zero-bit

    Image date is stored in a big array of 300 bytes and can be received by the µC via USB. Unfortunately, the maximum packet size of USB2.0 full-speed devices is 64 bytes. This means 5 packets are needed to transmit the necessary 300 bytes. I use the first byte in each packet to indicate which part of the image is contained in the following 60 bytes and then copy them to the appropriate position in the array. Additionally, a few commands to clear, refresh, fill or set individual pixels are implemented via USB control transfers (Commands are sent to Endpoint1 and image data is sent to Endpoint2.)

    LED Matrix Software

    LED Matrix Software

    LED Matrix

    LED Matrix

    On the PC side I wrote a little program in Delphi which uses libUSB-win32 to handle the USB communication. Using the program, one can paint each pixel, display 10×10 bitmaps or transmit a downsampled stream from the desktop (size and position are configurable). All image data can be gamma-corrected before transmission to ensure better color representation.

    Up until now, I concentrated on the software and used an LPCXpresso development board to test the code. Next I will design a small circuit board that can be placed inside the case of the display and make it a stand-alone unit.

    Future plans include some procedural effects generated by the µC (like plasma or fire), SD-card interface for automatic playback of images/videos and a bluetooth interface to stream image data from a PC or android phone.

    When the project has reached a point where the software is presentable, I will make it available here or in a follow-up post.

    Tags: , , , , ,

  • USB Display with different Brightness per Digit

    USB Display with different Brightness per Digit

    Last month I finally came around to order a lot of circuit boards that piled up over the last years. One of those boards was made to use some parts I just bought because they were on sale (the 16-segment LED digits) and a sample part I ordered just because I though it would be neat to have (the MAX6955).

    The MAX6955 from Maxim Integrated is an LED display driver for a combination of 7, 14 or 16-segment digits with up to 128 LEDs. The chip provides a font,  global or per-digit brightness control and two-speed blinking between two text buffers. Additionally, 32 switches in a matrix configuration can be scanned and debounced. To talk to the chip, the I²C-protocol is used.

    USB Display Software

    USB Display Software

    To control the display driver, an ATmega168 with the V-USB software USB stack is used. It is supplied with 3.3V and clocked at 12MHz (which is not possible, according to the datasheet, but works fine). Only four buttons were attached to the MAX6955 and placed on the backside of the PCB.

    At the moment, the PC-side software (which uses libUSB-win32) can send text and commands to the AVR which just passes them on to the MAX6955. In the future, I want to add a text memory on the AVR  so it can display and scroll messages independently from the PC. Maybe I will add some functions to dynamically vary the brightness of the digits to produce some cool effects.

    USB Display Backside

    USB Display PCB Backside

    I wanted the circuit board to be as small as possible, meaning it has the size of the eight 16-segment digits. All components were fitted between the pins of the display digits. To program the AVR, a card-edge ISP connector was used. To protect the circuit and to improve the contrast of the red LEDs a case was lasercut from red plexiglas.

    USB Display

    USB Display with Text

    You can download the circuit board layout (Eagle) here, the AVR firmware (C) here, and the software (Delphi) here.

    Tags: , , , , ,

  • Years of disassembling old printers and scanners yielded a lot of stepper motors which lay unused in a drawer for a long time. This was the inspiration to design a small and easy to use interface for a stepper motor. The first idea was to use the standard combination of the L293 motor controller and the L297 full bridge driver, but those chips take up a lot of space and do not provide microstepping functionality. A better option is an integrated stepper motor controller, like the Allegro A3984, which includes a microstep sequencer and the MOSFET bridge in a very small package. It can drive motors with up to 35V and 2.5A, which is enough for most small and medium stepper motors, especially those harvested from printers.

    To provide an easy interface, the motor should be controllable from the PC. This leaves an RS232 or an USB interface to connect to a microcontroller which in turn connects to the stepper motor driver. While there exists a (very good) software USB stack for the AVR microcontrollers, I chose the LPC11U24. After having worked with LPC microcontrollers at my job a lot, I was already familiar with the LPC11C24 and the lpcXpresso IDE.

    The LPC11U24 has an integrated hardware USB interface and a built-in USB bootloader which shows up as an mass storage device to the computer. Flashing a new firmware is as easy as dragging the binary file to the USB driver!

    Additional to controlling the motor via USB I wanted some methods of direct input on the motor. For that reason I added three buttons and a potentiometer on the circuit board. To connect limit or reference switches, some pinheaders are included. Three LEDs provide feedback from the LPC.
    As one motor is seldom enough to do something interesting, a way of connecting several motors together. My solution to this problem was to add a CAN-bus interface using the MCP2515 CAN controller and the MCP2551 CAN transceiver. The MCP2515 is connected to the LPC via SPI. The CAN bus and power connections (5V and motor power) are available on pin headers on each side of the PCB to make the controllers cascadeable.
    The A3984 provides an input for a reference voltage to control the motor current. An 10bit DAC (MCP4716) was added and connected to the LPC via I²C.
    The circuit board was designed to fit on the back of a NEMA17 (42x42mm) stepper motor.

    USB Stepper Motor Driver

    USB Stepper Motor Driver

    As of yet the USB communication is basically working and the motor is turning. The microstepping works quite well and the motor runs very fast and smooth. I have already implemented velocity ramping but apparently still have some calculation errors as the positioning is not exact. Software modules for reading the potentiometer and the buttons are completed, too. Sending and receiving CAN message is also working. The next step is to make the controllers talk to each other and to enable the master to discover other attached motors. After that the USB communcation has to be improved. In the end, the master should store a sequence of motion commands (maybe G-Code?) and control all attached motors.

    As a first test I used the motor to wind a coil for an electromagnet. I wrote a litte delphi program that sends commands via USB and constructed a frame from lasercut plexiglass to hold the bobbin.

    USB Stepper Motor Control Software

    USB Stepper Motor Control Software

    Coil Winding with Stepper Motor

    Coil Winding with Stepper Motor

    When the project is a little more advanced, I will publish the circuit board layout and the full source code for the firmware and the control software.

    Tags: , , , , ,

  • Just a small update on the status of the DIY CPU:

    The circuit design of the main CPU components is completed. The layout was split up in six parts :

    • ALU and Shifter
    • Index Registers
    • General Purpose Registers and Program Counter
    • Flags
    • Clock and External Bus I/O
    • Microcode Sequencer

    Each part occupies an 160x100mm circuit board. The boards are interconnected with pin headers to provide access to the internal data and address bus and to distribute the clock signal.

    DIY CPU PCB Layout

    DIY CPU PCB Layout

    Parallel to the layout the circuit was constructed in a simulation tool to test correct function. To fill the microcode storage with meaningful code, a Delphi program was written to generate the microcode sequences for the opcodes.

    DIY CPU Microcode Generator

    DIY CPU Microcode Generator

    This program was used to implement the microcode for a few basic opcodes which were then used to write a small assembler program that calculates the fifth fibonacci number (see screenshot).

    I’m currently working on some other projects to get some distance from the CPU. This helps to spot errors when looking over it a few weeks later. Then a few additional circuit boards for data I/O and storage/RAM will have to be designed.

    Tags: , , ,

  • This is the first post of a larger project, in fact, the largest of my projects so far: To build a 16bit CPU from 74HC chips. Now you may ask “Why?”, and then I might reply “Because (I think) I can!”. I just like circuits which are relatively simple in each part but rather complex as a whole. A CPU is the perfect example for a structure which is comprised of many simple parts which have to work in perfect synchronicity.

    This post is intended to give an overview over the main features and specs which will define the structure of the CPU. The implementation of each unit will be detailed in future posts.

    The following attributes are defining for the overall structure of the CPU and were either determined in advance or during the planning phase:

    • 16bit data bus
    • 16bit address bus
    • Four 16bit general purpose registers
    • Four 16bit special purpose registers
    • Each general purpose register can be accessed bytewise
    • 16bit program counter
    • Internal structure microcode controlled
    • Max. 127 microcode steps per instruction
    • Fully static design down to 0Hz
    • 16bit instructions (8bit Opcode, 8bit Parameters)
    • 8bit flag register
    • One external interrupt
    • 256 interrupt vectors
    • 64bit wide microcode instructions

    The microcode approach was chosen because of its simplicity and flexibility over a combinatorial logic design, despite being slower. If an instruction is to be added, changed or removed, this is simply a matter of reprogramming the microcode storage instead of rewiring a whole lot of chips. In the circuit, the microcode is just a number of cascaded memory chips (SRAM or EEPROM) with each data output pin wired to a control pin of one part of the CPU. Each instruction walks through a specified number of addresses, which in turn output a previously programmed sequence of data bits that control each part of the CPU to be active at precisely the right moment. For example, one data bit could be wired to the output enable of a register A and another data bit to the load enable of a different register B. If those to bits were to be active in the same clock cycle, the data from register A would by copied to register B.

    After planning all parts of the CPU with all their control inputs the number of necessary microcode bits added up to 62. The nearest multiple of 8 being 64, I used eight EEPROMs with an 8bit data interface and 16bit address bus. Their outputs will control and coordinate all other units of the CPU, each of which will get its own post:

    Overview of Internal Structure

    Overview of Internal Structure

    • Microcode storage and microcode counter with jump conditions
    • General Purpose Registers with read and write logic
    • Special Purpose Registers with read, write and counter logic
    • 16-bit ALU and 16-bit Shifter with flag calculation, input and output control
    • Flags register with read, write and set logic
    • Program counter
    • External bus interface

    At the time of writing this post, the design has been almost completed, so the specifications are unlikely to change significantly.

    Tags: , , ,

  • And now for something completely different: A little robotics project for the weekend.

    The described robot can be build entirely from model making supplies and materials from the hardware store.
    Also only very few tools are needed. A metal saw, a drill press, a vice and optionally a tap will suffice.

    From the model making store you need:

    • 3 Servos  with M3 thread in the axis  (e.g. HX12K)
    • 12 ball joints with M3 threads and 3mm holes in the sphere (e.g.  Kavan Maxi Ball links 1405)
    • about 4grams of Polycaprolactone (Sold under names like ShapeLock or Friendly Plastic)

    Form the hardware store you need:

    • 850mm of M3 threaded rod (sometimes also available for model making)
    • 27 M3 screw nuts
    • 3 M3 screws 5mm long
    • 3 M3 screws 15mm long
    • 400 mm of 10mm square hollow aluminum profile (1mm wall thickness)
    • 150x150mm metal oder wooden plate for mounting

    (To control the robot you need a microcontroller of your choice.)

    The first step is to divide the aluminium profile in three pieces of 100mm length and three pieces of 30mm length.
    Then 4 holes are drilled and tapped in each of the pieces according to the following drawings.

    Drawing of 100mm lever

    Drawing of 100mm lever

    Drawing of End Effector Part

    Drawing of End Effector Part

    Next the threaded rod is divided into six pieces of 100mm length an six pieces of 40mm length.

    The 40mm pieces are screwed in the aluminium profile, centered and secured with one M3 nut on both sides.
    Two ball joints are screwed on each 100mm pieces of threaded rod and aligned.

    The 100mm aluminum profiles are then screwed to the servoaxis with the short M3 screws. All servos should be in the same extreme position.

    Now the servos can be fixed to the groundplate. I used hot glue but you can use screws as well. The exact alignment of the servos is important.
    To get it right without much measuring I printed out the drawing of the baseplate.  Then the shape of the servos was cut out and the paper taped to the groundplate. The servos were placed at the right position and glued there.

    When the glue has hardened you can attach the ball joints to the servo levers and secure them with one nut on every side.

    Ball Joints attached to lever

    Ball Joints attached to lever

    To make the end effector you need to get the Polycaprolactam into its malleable state.

    End Effector center piece

    End Effector center piece

    Therefore it is placed in a small cup with some water and heated in the microwave or on the stove until it gets transparent.
    Then carefully pour the hot water away and get the plastic out. It should be touchable without burning your skin.
    Now shape it into a three-edged star (see image) and slide a 30mm aluminium profile over each end.
    Try to fill the profile as tight as possible and about 5mm behind the holes.

    Before the plastic has cooled down completely align the three profiles in 120 degree angles.
    When it has cooled down you can drill through the holes in the profile, put the three long M3 screws in and secure them with nuts.

    Now place the ball joints on the threaded rod pieces of the end effector and secure them, too.

    The completed end effector

    The completed end effector

    The mechanical part should now be completed.

    Isometric view of the delta robot

    Isometric view of the delta robot

    Next step is to control the servos with a microcontroller. Servos need a PWM signal with a period of 20ms and a high time from 1ms to 2ms,  depending on desired position.
    This can easily be generated with timers, which are available in almost every µC. To control multiple servos with only two timers and without using to much processing power a clever tactic is needed.

    One timer is used to generate an interrupt every 20ms / number_of_servos. On each of those interrupts one servosignal is switched on and a second timer is started. This timer is set to overflow after 1-2ms according to the desired position of the servo. When the overflow interrupt of the second timer occurs, all servosignals are switched off. This way you do not a variable to save the current servo, because only one servos is active at a time anyway. On the next interrupt of the first timer the process repeats with the next servo. The desired positions can be saved in an array.

    With this method up to 10 servos can be controlled with only two timers and very short interrupt service routines. This way there is much remaining processing power left for other calculations such as receiving and decoding commands via the UART or I²C. Maybe you can even fit the inverse kinematics into the µC.

    Servo Timing diagram

    Servo Timing diagram

    The IK formulas and some explanation can be found here.

    A simple servo controller using the described method can be downloaded here. (AVRStudio project with C-Code).
    A quick and dirty Delphi 5 Project which sends commands to the ATmega and does the IK calculations can be downloaded here. (Contains source and executable).

    And here you can see what you can get:

    Tags: , , , , ,

  • The previous version of the gravitational simulation produced rather abstract results. The lists of coordinates did not say much and the import for 3DsMax was not very handy.

    To overcome this problem I looked into openGL and found it quite easy to integrate.
    The glut-Package for DevC++ includes all necessary files and an example project.

    The whole initzalizing stuff was just copied from the example and the code from the earlier version adapted to produce the coordinates in the corrent form.

    All the objects are stored in a linked list. For each frame the list is traversed and the new coordinates displayed.

    Gravitational Simulation 3D

    Gravitational Simulation 3D

    I also added a linked list to each object that stores all past coordinates. When this list ist used to plot lines between each two adjacent points the trace of the object is displayed. Currently only the trace of 2 selected objects can be displayed at a time. Those two objects also get marked with little triangles and a 3d-crosshair. Their parameters are displayed in the upper left edge of the screen, along with some additional info. To visualize the forces, accelerations and velocities the corresponding vectors can be displayed.

    Velocity- and forcevectors displayed

    Velocity- and forcevectors displayed

    Code can be downloaded here (Executable included).

    Rotating the view is done by holding a mousbutton down and moving the cursor.

    Other commands:
    i    Toggle  Info
    x   Calculate Step
    z   Reset viewcenter to [0,0,0]
    o   Center blue object
    k   Center yellow object
    t   Toggle trace
    p  Select blue object
    L    Select yellow object

    f    Toggle force vectors
    b   Toggle acceleration vectors
    v   Toggle velocity and force vectors

    +-  Increase / decrease step size

    n   Reset world and generate 50 new objects randomly

    */  Increase / decrease gravitational constant

    5 and 0  zoom in and out

    Numblock to move viewcenter

    Tags: , , ,

  • (FYI : I am currently not posting the projects in chronological order, because I have so much stuff lying around that I did before I had the blog. So those things will show up from time to time.)

    The 4×4 LED Display was my first project with a two-layer circuitboard layout. The alignment was not 100% optimal, but sufficent. I wanted to make the board as small as possible, so the parts had to be stacked at some places. The square LED’s were painted black on the sides to keep the pixels sharp.

    4x4 LED Matrix Circuit Board (Top)

    4x4 LED Matrix Circuit Board (Top)

    The rows and columns are both controlled by a 4094 Shift&Store-register. The upper four bits control the coloumns and the lower four the rows. So for each frame 4 bytes have to be shifted in. That is done via a QBasic programm that toggles pins on the serialport. Instead it would also be possible to just send the bytes over a serialconnection, but I was to lazy to write code for that.
    To generate the patterns, one can put them together binary by hand. But I choose the easy way again and wrote a Delphi-Program to generate patternfiles, which then would be send to the display by a QBasic programm. (I test all my circuits on old DOS-PCs).

    Here is a video of the display in action. The sequence is preprogrammed…so no actual tetris yet..

    Layout and circuit are here. QBasic sourcecode is too ugly to show. How to shift data into a shiftregister should be easy for everyone who can read the datasheet.

    Tags: , , , , ,

  • I recently obtained a very old mobile phone from a friend. The battery was dead, so I dismantled it and to my surprise found a display with soldered contacts. In other mobile phones the display was connected via a conducting polymerpad, which was extremly difficult to use on selfmade circuitboards.

    Googling the name of the display brought up a site with pinout and a link to the datasheet of the driverchip.

    Using my I²C-Adapter and my I²C-Control program the testing was easy. Just look up the commands in the datasheet, put together a sequence and run it. The display works well and even the illumination is intact.

    Pinout (looking at the back of the display with the black blob to the top right):

    1. VLCD
    2. – LED1
    3. – LED2
    4. SCL
    5. VC (Contrast)
    6. VDD (+5V)
    7. SDA
    8. GND
    9. + LED 1&2 (+5V)
    10. VO

    Connect SDA, SCL, 5V supply and a 10k poti between 5V and GND and the centertap to VC and you are ready to go.

    The adress of the display is 01110100 for writing data.

    After sending the adress you first send a control byte, which determines if the following bytes are commands or characters. Sending 00000000 selects the commands. Then we set the datalength to 8bit, the number of lines to 4 and the voltage generator control to V0=VDD-0.8V by sending 00001110. The display is then switched on by sending 00001111, which also sets the cursor position and blinking. The following byte ( 00000110 ) configures the entrymode of the display to increment the adress after every written character and to freeze the display (and not shift it). Then we only have to specify in which of the four lines we want the following characters to be written. This is done by setting the DDRAM adress to one of the following values: 0x00 (1st line), 0x20 (2nd line), 0x40 (3rd line), 0x60 (4th line).

    Then you send a repeated START condition, the adress again, a controlbyte which tells the display that all following data are characters ( 01000000 ).

    Then you can send arbitrary characters. The character-table is on page 15 in the datasheet, and the commands are on pages 23 and 24.

    Clearing the display is done by sending 00000001 as a command.

    LPH7319 controlled via I²C

    LPH7319 controlled via I²C

    The driverchip is called PCF2116. The datasheet can be found here.

    I will post a complete sequence that clears the display and writes ‘Linex’ (x = 1..4) to the four lines soon.

    For now just a photo of the result:

    Tags: , , , , , ,

  • For quick testing of digital circuits and chips I often use the parallelport because it is easy to program in C and QBasic. But writing a program for every new circuit takes to much time. So I wrote a little program to control the parallelport via a nice GUI.

    Parallelport Control

    Parallelport Control

    When you start the executable, you get the Port-Control-Screen, which is divided into the three registers that contain the pins of the port. The pins can be set individually or a script can be created, which places the bitpatterns on the port automatically. Therefore you must select a port, enter the hex-value of the byte, and click ‘Add’. Delays work the same way. The script can be saved and loaded via the contextmenu of the listbox. You can also write the script with any editor, as long as the same syntax is used.

    The ‘Run’-button runs the script n times, with n being the number in the field next to the button.

    The I²C-Mode is activated with the button of the same name.

    I2C Control

    I2C Control

    Here you have a sequence-listbox, the available actions, the necessesary parameters and a listbox which displays the recieved data. Just select the desired action, enter hex-value of the byte to send or delay (if necessary) and click ‘Add’. The contextmenu of the sequence-listbox provides save and load for the scripts.

    In datasheets for i²c-chips you often only find binary values for the commands to send. So I included a field which converts the binary values to hexadecimal numbers. Instead of entering the binary value you can also select the bits directly. The value is loaded into the datafield by clicking the small ‘<‘ button right next to it.

    After clicking ‘Run’ it is first checked, if the bus is ready, that is if SCL and SDA are both high (idle). Then the sequence is processed.

    The pins are hardcoded for my parallel-i²c-adapter, which can be found here. If you have a different interface, you can change the code. Maybe I will in include those options in the next version.

    Delphi6 sourcecode can be found here (executable and inpout32.dll included).

    (I only use the code on a Win98 PC, where the inpout32.dll is sufficient. To use it with Win2K or XP you need something like DirectIO.)

    Tags: , , , ,