• (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: , , , ,

  • Some years ago a friend of mine introduced to me a numerical puzzle called Sudoku. For every one who has not already heard of it, i will give a short description: The puzzle consists of a square field divided into 9 rows and 9 columns. Furthermore the 9×9 block is divided into nine 3×3 blocks. In every of the nine rows, nine columns and 3×3 blocks the numbers from 1 to 9 have to be positioned, so that every number occurs only once in every row, column and 3×3 square.

    At the start some, depending on difficulty, cells are already filled in. Then one has to conclude the missing numbers by logic. This can be done by a process of elimination.

    My solver sequentially checks the remaining possibilities for every cell. This is done by checking every cell in the same row, column and 3×3 field for the already filled in numbers. The remaining numbers are the possible for the cell. If there is only one, it is written to the cell. This is the simple version, but also the one that executes quicker.

    The more complex version compares the possible solutions for one cell with all the cells in the same row, column and 3×3 field. This allows to assign an number to a field, even if there are more than one possibilities, if one of them only is true for this cell.

    Some times the solution for one cell is ambigous. Then the solver chooses one of the remaining possibilities and then continues with the solution process. If the field can not be solved (when contradictions occur), the next possibility is checked until the field can be solved.

    The code may be a bit over complicated at some points because the strategy developed over time and was not planned in advance. Besides that, all (of the very few) comments are in german, as are all loging-outputs.

    Delphi 5 sourcecode can be downloaded here.

    Tags: , ,

  • R/2R Digital to Analog Converter

    R/2R Digital to Analog Converter

    The first thing I wanted to do with the new oscilloscope was to test the X-Y-Mode. Not with some lame Lissajous-figures but with arbitrarily adjustable positions. And the easiest way to to so, was to take an ATMega32 and two DAC’s.

    I had two parallel-input DAC’s lying around, but i did not want to make a layout or to wire so many pins.
    The next best alternative was to build two R/2R-resistor ladders. I found a large amount of 620kΩ resistors (can’t remember why I bought them. They seem to have been there for years.) and some perfboard.

    I wired the resistor networks directly to Port A and B of the AVR, so I could directly assign 8-bit numbers to the port register. I wrote a simple program where an interrupt updates the ports at ca. 30Hz and displays some bouncing dots.

    Tags: , , , , ,

  • When the timebase knob on my old Hameg HM-312 fell off, i decided that it was time for a new oscilloscope. After all, the old one has endured my using for almost 10 years now. Actually the old one had everything I needed.

    Hameg HM-1005 Oscilloscope

    Hameg HM-1005 Oscilloscope

    I considered buying a digital storage oscilloscope, but other than the measuring functions for frequency and duty-cycle, I would scarcely need any of the additional features this would offer over an analog model. Additionally the price for an analog one is only about a third.

    eBay offered a wide variety of analog oscilloscopes, mostly from Hameg. After a few days of searching and comparing, I found a relatively cheap HM-1005, which has 3 channels, 2 separated timebases and adjustable trigger-offset and bought it.

    The package arrived only 4 days later, but unfortuneately I found one edge of the case partly broken and the intensity knob totally destroyed. Some moron at the post office must have dropped the package. After further inspection it appeared that not only the knob was destroyed but also the axis which connects the knob to the potentiometer was split in half.

    Not keen on a fight with the post over who is to blame for the damage, I opened the case and tried to repair the broken axis. Some glue fixed the problem and the knob was replaced by knurled screw.

    The old HM-312 is still in use. I even fixed the knob. Was quite easy, but i needed an excuse to buy a new one…

    Tags: , ,

  • I completely recoded the Image Manipulation program. It is now better structured and easier to use. Additionally I implemented the Canny Edge Detector Algorithm and some more filters. 8-bit BMP’s are still not supported, so that would be the next step.

    Binary edge image output from canny algorithm

    Binary edge image output from canny algorithm

    To test the edge detector, I used the image from the Wikipedia article on the topic, as the desired result was known for that image.

    Complete C++ code can be downloaded here (executable included).

    Executing the program without parameters displays the help.

    To perform edge detection on an image, use the following parameter sequence:

    image <input.bmp> <output.bmp> -g -f 0.8 -e -n 80 -w 80 50

    This command first converts the image to greyscale (-g), then applys gaussian blur with a standard deviation of 0.8 (-f 0.8). After that, Sobel filters for X and Y direction are convoluted with the image, which gives an edge image. Those edges are now thinned by Non-Maximum-Suppression (-n 80),  which only leaves one-pixel wide edges, which are above the given threshold. Finally the edge tracer (-w 80 50) deletes pixels not belonging to an edge, by appling hysteresis thresholding.

    Tags: , , , , , , , ,