Blog

Hanover LED Display Reverse Engineering

This sign is programmable via RS485 (the orange connector) but uses proprietary hardware and software so is ripe for reverse engineering. The 8 pin ribbon cable to the display board suggests a serial protocol and probing with an oscilloscope showed 0-5V digital signals. Time to attach a logic analyser.

Here is the overview on start-up:

This looks like some initialisation data and then regular data transmission every second. There is a 100Hz pulse train on pin8 (heartbeat from the display?) and a delayed pulse on pin6 about 15ms after each data transmission

Here is a zoomed-in trace for one of the data transmissions:

So definitely SPI style with a rising edge 2.4 MHz clock on pin5 and data on pin4. By default, the display powers on with the top-left led lit. The ’80’ byte in the first set of data suggests the data is being sent left-to-right, top-to-bottom, MSB first. The pixel data is gated by pin3 (active low). Each row of display data is preceded by a header, ‘3E’ for the first row and ‘BE’ for the second. Header data is gated by pin2 (Active High). Some further experiments showed that pin7 accepts an analog voltage to set the display brightness (0-5V).

In summary the function of the connector pins is:

  1. GND
  2. HEADER_SEL (Active high)
  3. PIXEL_SEL (Active low)
  4. DATA (Idle high)
  5. CLK (Idle high, rising edge, 2.4MHz)
  6. EOT (End of data transmission)
  7. BRIGHTNESS (analog 0=on 3V = off)
  8. HEARTBEAT? (100Hz pulses from the display)

Now we have enough info to create a prototype. I used a Wemos D1 Mini (ESP8266) which has hardware SPI and WiFi support. 5V power is available from the sign itself so no other hardware is needed. Here are the pin mappings:

Hanover PinWemos Pin
1GND
2D1
3D2
4D7 (MOSI)
5D5 (SCK)
6D3
7D4
8Unused

Some code was written to implement the above protocol. It subscribes to the MQTT topics “hanoverled/display” (64 bytes of display data) and “hanoverled/brightness” (0-1023) and updates the display as these topics change.

Here is an extract of the code showing the main display routine. It accepts 64 bytes of data being the pixel values in left-to-right, top-to-bottom order. Not sure what the header values mean so just used the captured values 3E and BE. The ‘EOT’ pulse at the end of transmission is required otherwise the display does not update properly.

void UpdateDisplay(byte data[64])
{
   SPI.beginTransaction(SPISettings(2500000, MSBFIRST, SPI_MODE2));

   // meta data row 1
   digitalWrite(MS, HIGH);
   SPI.transfer(0x3E);
   digitalWrite(MS, LOW);

   // pixel data row 1
   for(int i = 0; i < 32; i++)
   {
      digitalWrite(DS, LOW);
      SPI.transfer(data[i]);
      digitalWrite(DS, HIGH);
   }

   // meta data row 2
   digitalWrite(MS, HIGH);
   SPI.transfer(0xBE);
   digitalWrite(MS, LOW);

   // pixel data row 2
   for(int i = 32; i < 64; i++)
   {
      digitalWrite(DS, LOW);
      SPI.transfer(data[i]);
      digitalWrite(DS, HIGH);
   }
   SPI.endTransaction();

   // pulse EOT line
   delay(15);
   digitalWrite(EOT, HIGH);
   digitalWrite(EOT, LOW);
}

To test the display a version of Conway’s game of life was written. Random start populations are generated, evolved and sent to the MQTT “hanoverled/display” topic. The program generates a new population if a game starts to repeat.

Here is a video of the sign in operation:

Sinclairduino? Vintage Calculator Reanimated

I bought this Sinclair calculator off eBay with the intention of repairing it. The power supply rails, LED display and driver chips were working fine. The keyboard had several keys that did not show any connectivity which could be fixed. But the main C-595 calculator chip was faulty and outputting random signals.

The C-595 is of course unobtainable these days, so could we replace it with a suitably programmed Arduino chip and bring it back to life?

First job was to fix the keyboard. Several keys were not functioning so this needed a tear down and clean.

The keyboard was held in place by plastic pegs which naturally snap off when disassembling! Some small holes were drilled in the plastic frame using a hand held 1mm CNC drill bit taking care not to go through to the other side. Small lengths of 1mm ABS rod were then glued into the holes and melted with a soldering iron to keep the keyboard layers tightly sandwiched together.

With the keyboard working we turn attention to the main calculator chip. The plan was to design a small PCB carrier for an ATMega328 chip that could plug in in place of the original chip.

A datasheet is available for the C-595 (local copy here) and after some reverse engineering we arrived at the following schematic:

The C595 runs with a positive earth, so we’d have to install the Arduino upside down. A bit of a brain ache but it should work. I wanted to use the existing driver ICs to minimise changes.

Removed the C595 IC and replaced with a socket. Removed the coil to disable 15V and 9V generation. Added a jumper wire to supply -3V battery power to an unused pin 10 on the socket.

The LED display is a 9 digit, seven segment common cathode device. To turn on a segment requires the segment line to be at 0V and the corresponding digit cathode at -3V. Allowing for the voltage inversion by the driver and the upside down Arduino, that corresponds to a HIGH for the segment and a HIGH for the digit.

To add to the fun the keyboard is multiplexed to the digit driver pins. An INPUT_PULLUP pin on the Arduino will pull to 0V, so we need to strobe the digit pins with -3V (LOW) to detect a change in state on the KP, KN and KO input pins.

We need 17 digital outputs and 3 digital inputs. To run at low voltage we use the internal oscillator which helpfully frees up pins PB6 and PB7 for use as GPIO.

The software was developed initially as a prototype running on an Arduino Nano. It runs in a loop with three main functions; update the display, read the keyboard and update the calculation when a key is pressed. Updating the display is slightly complicated by the fact that the circuit uses the same pins to enable display digits as well as drive the keyboard. We need to take care to blank the display while the keyboard is polled. For the calculator part of the software a simple state machine is used in conjunction with a custom decimal floating-point library. Firmware can be found in this github repo

Here is a picture of the prototype:

The case wouldn’t close properly using the prototype so a small PCB was designed around a bare bones ATMega238P to fit in the C595 socket. The ICSP and Tx/Rx pins were connected to exposed pads for testing purposes.

An Arduino Uno was used as a programmer to flash the firmware to the ATMega using these pin connections.

PCB    ->  Arduino Uno
PIN 15 (VCC) -> 5V
PIN 10 (GND) -> GND
PIN 7 (KO, MOSI) -> 11 (MOSI)
PIN 8 (KN, MISO) -> 12 (MISO)
J103 pin 5 (~RST) -> 10 
PIN 16 (D9, SCK) -> 13 (SCK)

To support the bare board, definitions were loaded from: https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json

We use the factory defaults of 1MHz internal oscillator and BOD disabled so no need to change the fuses. Just set the drop down menu items correspondingly.

Here is a short video with a demo of the finished calculator and a quick look inside.

Rigol DS1054 (DS1000) Viewer/Controller

This was originally designed to just mirror a Rigol DS1054 screen over a LAN, but I couldn’t stop myself adding a few features, so you can now:

  • Click on the Timebase box to change the timebase
  • Click on the channel numbers at the bottom to toggle the corresponding channel on/off
  • Click on the channel voltage displays to change the vertical scales
  • Click and drag a trace to move it up/down
  • Click and drag in the “waveform memory” window at the top centre to move the traces left and right
  • Right-click on the main display to copy an image of the display to the clipboard or to a file.

Here’s a screen capture showing it in use.

With just 1 channel enabled you get about 6 FPS which drops to about 1 FPS with multiple channels.

On first run it will ask you for the scope’s IP address. Enter it and click Save

The app is packaged as a UWP app and doesn’t require any VISA drivers to be installed.

Here are some links:
Microsoft Store: https://www.microsoft.com/store/apps/9NPPVW8MWZW6

Source code: https://github.com/ynformatics/DS1000Viewer

Low cost GPIB to USB adapter

A simple GPIB to USB adapter using an Arduino Uno. Constructed following: http://egirland.blogspot.com/2014/03/arduino-uno-as-usb-to-gpib-controller.html

A 24-way connector (RS 239-1207) was used for the GBIP connector and wired to the Arduino with two lengths of cat 5 cable as follows:

cable 1 pin mapping
GBIP	Wire	Uno
1	wh/or	A0
2	or/wh	A1
3	wh/bl	A2
4	bl/wh	A3
13	wh/gr	A4
14	gr/wh	A5
GND	wh/br	GND
GND	br/wh	GND

cable 2 pin mapping
GBIP	Wire	Uno
5	wh/gr	12
6	gr/wh	11
7	wh/br	10
8	br/wh	9
9	bl/wh	8
11	wh/bl	7
15	or/wh	4
16	wh/or	5

A 3D printed case was designed in Fusion 360. CAD files available here.

The Uno was programmed with GPIB6.1.ino available from Emanuele’s website.

Compact roller blind motor

I have a few roller blinds ripe for automation. The first attempt used a stepper motor with a 3D printed cog to pull the cord.

Remains of cord puller

This worked but had the look of a Heath Robinson / Rube Goldberg love child so I looked for a neater solution.

Hardware

Tubular motors that fit inside the roller tube can be bought online but were rather expensive and bulky for my purposes so I opted for a more compact design. Taking measurements from the existing blind pulley mechanism and a suitable 30 RPM 12v DC motor with 20mm external diameter:

let me design a replacement in Fusion 360

Using a DC motor requires some sort of encoder to keep track of the blind position. I opted for a magnet/hall sensor mounted in the drive mechanism. This keeps the the sensor unobtrusive but limits the resolution to one revolution (about 10 cm of blind travel in my case). I hoped that combining this with timing data would be accurate enough. It was.

Output from the printer. Note a small 2 x 1 mm magnet has been inserted in one of the holes.

I hand carved a small PCB to hold the Si7025 hall effect sensor and connected everything up.

For the controller I used a Wemos D1 mini with a TB6612FNG driver module which can handle up to two DC motors. A small buck converter supplies 5V for the electronics from the 12V motor supply. All wired together in point to point style:

Software

The code was written using the Arduino IDE. One unexpected problem was occasional glitches on the sensor output. This screenshot of the sensor output while running at 30 rpm shows the expected high -> low transitions as the magnet passes the sensor, but with the occasional spurious pulse. These pulses were always less than 1ms duration so are simply filtered out in software.

To move the blind to a given position, the software moves to the next magnet home position, then counts complete revolutions while timing how long each revolution takes, and then keeps the motor running for the required time to move the remaining distance.

An MQTT API was implemented, controlled from a Node Red flow.

Installation

A small case to contain the electronics was 3D printed and wired up to a 12 V power supply.

And here are the blinds in action:

Blind goes up
Blind goes down

Files

https://github.com/ynformatics/roller-blind

Precision 30 A Current Shunt

I needed a precision current shunt to calibrate a recently fixed E3631A power supply. The Agilent 34330A looks nice and is colour coordinated, but at $108 seemed a bit pricey for a resistor in a box.

Agilent 34330A

So let’s make a DIY clone…

For the resistor we use an SMD Current Sense Resistor, 0.001 ohm, CSS2H-2512 Series, 2512 [6432 Metric], 5 W, ± 1%. This will give the required 1 mV/A response and can cope with a 30 A current.

A small PCB was cut from a piece of copper clad FR4. The holes are 19.2 mm apart as this is a commonly used binding post separation. Care should be taken to route the sense connections as close to the ends of the resistor as possible.

The resistor and sense leads were soldered on

Mounted in a 3D printed box with banana sockets and plugs

Here is the shunt under test showing we are within 1% tolerance.

A couple of lessons learned:

  1. If any solder gets on the resistive part of the resistor it will reduce the resistance!
  2. The sense connections must be connected as close to the ends of the resistor as possible. A few extra micro-ohms will exceed the tolerance.

DeLonghi DEM10 Dehumidifier fix

I have a three year old DeLonghi DEM10 dehumidifier whose low temperature warning light is now permanently on. The unit is indoors where the temperature never drops to such low levels.

Internet searching suggested a faulty capacitor on the main PCB. I replaced this but to no avail.

The schematic shows that connector CN2 leads to the temperature sensor. Disconnecting this and measuring with a multi-meter showed a sensor resistance of 650 ohm. I experimented with a few different resistances and it seems that anything above about 1500 ohms turns the warning light off. I settled for 2k7 ohms, cut the sensor lead, soldered it in place and covered with heat shrink.

All working now!

Variable Isolation Transformer

This project couples a variac with an isolation transformer.

Two design decisions to make:

1. Does the isolation transformer go before or after the variac? Here it was placed after the variac as the variac was rated to 4A and the transformer 5A. Any turn-on surge current will be less through the variac.

2. Is an earth connection passed through to the output socket? No, because it’s an isolation transformer 😉 For convenience the earth connection is made available separately on the front panel.

The schematic is straightforward:

A PZEM-061 module is used to display output voltage, current and power. It is hacked (ref 1) to run off a separate 12V supply which is sourced from a small transformer to maintain isolation.

A box was constructed from MDF and plywood to contain the hardware.

With two large transformers the unit weighs in at 25 kg.

Interior view

The variac was positioned so it pokes through a hole in the front panel. Re-using its original scale gives a rough idea of the voltage and tidies up the hole. Even the rubber feet were reused.

Front panel

All finished and ready to use.

Refs:

  1. https://web.archive.org/web/20190901144559/https://webx.dk/oz2cpu/energy-meter/energy-meter.htm

Lego Music

Description

This project describe the construction of a tangible user interface which allows the creation of music from an arrangement of physical blocks.

Coloured blocks are laid out on a flat surface and observed by an overhead camera. Computer vision algorithms are used to convert the pattern of blocks into a set of musical notes. Changing the position of the blocks changes the audio output in real-time.

Inspired by Yamaha’s Tenori-on

Details

Lego blocks (other plastic blocks are available) are arranged on a virtual 16 by 16 grid layout and a virtual cursor repeatedly scans the grid from left to right. As the cursor reaches each grid column, the blocks in that column trigger a note to be played, the pitch of which is determined by the vertical position of the block. Multiple blocks in a column result in multiple notes being played simultaneously.

Here’s a diagram to show the principle more clearly. Time is on the horizontal axis and pitch on the vertical axis. (For simplicity this shows an 8 by 8 grid)

 

This arrangement of blocks would play an ascending scale. When the cursor is at the position shown a three note chord would be played.

The final pitch of a note is not only determined by the position on the grid, but also by the user-selectable scale. There are nine scales in the software which map position to pitch. The pitch can also be globally transposed in semitone or octave increments.

Hardware design

The hardware consists of a webcam and some blocks. The webcam is connected to a laptop where all image processing and sound generation takes place.

To keep it simple Lego blocks were used. They have a consistent size and shape and should make it easier for the computer vision system to reliably track them. It was found that yellow blocks were not reliably detected and are more sensitive to lighting conditions. Other darker colours worked better.

The webcam used was a “GUCEE HD92 720P” model. A resolution of 640 x 480 is sufficient for this project so most webcams should work OK.

The webcam was mounted directly over the blocks using a hacked IKEA Tertial lamp. The original webcam clip was removed and the lamp bracket drilled out to accept the fitting.

 

For audio output the built-in PC sound card was used.

Software Overview

The overview of the system is as follows:

On the left are the vision components. These are responsible for getting images of the blocks from the webcam and converting them into a set of notes to be played. Open CV is a well known library for image processing and here we use the Emgu.CV wrapper for C#/.Net

On the right are the audio components. These convert the extracted notes into sound. The NAudio library is used for MIDI sound synthesis.

Software – Audio subsystem

The key component here is the Sequencer. This maintains the sequence of notes to be played and steps from one set of notes to another on receipt of a timer tick. Once the last note has been played it repeats from the beginning.

The human ear is very sensitive to changes in timing of sounds, so it’s important to use a regular beat for the timer. Standard Windows timers have a resolution of about 15 ms which is not quite good enough. Using the multimedia timer gives a resolution down to 1 ms and can be set to generate a periodic time tick with good consistency.

To simplify the audio output code MIDI synthesis is used. This avoids having to deal with analogue waveforms and keeps all audio in the digital domain. For this project the built-in Windows Microsoft GS Wavetable MIDI Synth is used. This is not the best sounding, but it allows up to 32 notes to be played simultaneously from a selection of 127 instruments and is adequate for our purposes.

The sequencer component can be run and tested independently. A sequence can be loaded using the SetNotes method which takes a 2-dimensional array of Notes and will then play that sequence in a loop until stopped.

Software – Vision subsystem

The job of the vision subsystem is to keep the sequencer updated as the arrangement of the blocks is changed.

The software continually grabs video frames from the webcam, identifies the block positions and maps them to cells on a 16 by 16 virtual grid. These cells are then converted to an array of notes for loading into the sequencer.

To identify the blocks the “SimpleBlobDetector” class from Emgu.CV is used. As the name suggests this identifies blobs in an image and outputs a list of the blob centroids (the coordinates of the block centres). The blob detector can be configured to only accept blobs in a certain size range, which can be optimised by trial and error for the particular blocks used.

Once the block coordinates are obtained they can be mapped to the nearest grid cells and then to an array of notes, the cell row and column giving the pitch and order of the notes respectively. The note array is then loaded into the sequencer.

This process runs independently of the sequencer so differences in frame rate or blob detection time do not affect the timing of the audio output.

The video sub system also displays the captured images and overlays some markers showing the positions of detected blocks and the current grid column being played.

User Interface

In addition to the tangible blocks interface there is a traditional Windows Forms user interface. This allows parameters such as tempo, instrument, transposition and octave parameters to be set. These parameters can be altered while the audio is playing and it will react in real time.

The user interface also shows the view from the webcam and overlays some markers showing the positions of detected blocks and the current grid column being played.

 

Demo Videos

 

 

 

References

Software available for download from:https://github.com/ynformatics/LegoMusic

Yamaha Tenori-on https://en.wikipedia.org/wiki/Yamaha_Tenori-on

Featured on Hackaday! https://hackaday.com/2018/12/30/turning-lego-blocks-into-music-with-opencv/

Ohaus Scout Pro Wireless Interface Hack

Introduction

A potential project required wireless connectivity to an Ohaus Scout Pro SPU401 balance.

This balance takes a proprietary USB or RS232 adaptor which plugs into a 2×6-way edge connector on the PCB, but as an adaptor costs more than the balance cost on eBay it was decided to hack it.

Tracing out the edge connector pins on the balance PCB to the NXP LPC2103 micro-controller revealed the following circuit fragment:

An extra menu item only appears on the balance’s display when a serial adaptor is plugged in, so a reasonable guess was that the lines with pull-up resistors are pulled low in some combination by the adaptor to enable the unit to recognise it. And indeed after some experimentation it was found that starting the unit up with pin 8 grounded adds the Print and USB options to the menu. Grounding pin 33 on startup adds Print and RS232 items.

Navigating through the new menu options, setting baud rate to 9600,N,1 and print setting to continuous non-stable showed the expected serial output on TXD0 pin.

Hardware

The idea was to use an ESP8266 module to send and receive serial data from the balance to an MQTT topic. The edge connector has a 3.3V pin available, however the balance powers off if more than about 100 mA current is drawn. This was not enough to power the ESP8266 so a mini-buck regulator was used and fed directly from the 12V input jack.

Final hardware schematic:

And all wired together on a small strip-board. A 12 way, 2 row, 2.54mm pitch female edge connector (RS718-8245) from TE was used:

Software

A simple program to send/receive any serial traffic to an MQTT topic was downloaded to the ESP8266. Commands can be sent to/from the balance by publishing/subscribing to the “ohaus” topic.