Enigma machine – more robust & reliable

Intro and motivation

The goal of making my first Enigma replica was to reproduce the original functionality and wiring, while using current technologies (pcbs instead of hand wiring) and current components (just byuing the switches instead of making exact replicas). The encryption rotors were connected to each other using pogo pins, and while this worked fine, there were visible scratch marks on the pcbs from pogo pins, meaning that sooner or later some failing connections will appear due to pogo pins scratching through the pcbs on the rotors (because each key press meant rotating the rightmost rotor and thus scratching it a little).

The plastic case (and thus looks) would be reused, so lot of work would be saved on this second replica.

This replica making description will be slightly different to first one, as I will go more through the ideas and iterations of going from start to the one that landed in the final version.

rotor_scratch

 

 

Encryption rotors with IR interconnections

The first idea on increasing the reliability and avoiding the scrathing through of the rotors pcbs was to use IR LEDs and phototransistors instead of pogo pins. This way one could keep the rest of the Enigma machine (keyboard, lights, plugboard) as is, and just replace the encryption rotors part with the new IR based one.

There are several problems with the IR encryption rotors, though:

  • possible IR light leakage – IR light from activated letter on rotor could potentially activate the letter next to it, too, then the result would be unreliable. One of the ways to fight this is to have the LED or phototransistor deeper in the plastic tunnel, this would reduce the light that could escape this channel and activate neighboring letter
  • too many components per single rotor – for each letter you need: 2 resistors, 2 IR LED, 2 IR phototransistors, 2 transistors to amplify the received current and drive the LED – the 2 transistors were reduced to single component having 2 transistors inside. So that’s 7 components per letter, 26 letter on a rotor – that’s 182 components per rotor. Having 3 rotors (3 * 182), entry disk (4 components * 26 letters = 104 components), reflector (4 components * 26 letters = 104 components)… So that’s 754 components on the encryption rotors part. This is a lot to solder by hand, so this started a quick pcb reflow owen side-quest. Additionally, 754 components – that’s a lot of opportunities for a failure. I’ve soldered one wheel, reflector and entry board and decided that this wouldn’t be great for reliability
  • powering of the components on the encryption rotors – this could be done using slip rings, or wireless power transfer, or a batteries on the encryption rotors. The battery option seemed like the simplest one, still thinking of future switch to other means.

As the whole point of my 2nd Enigma replica was higher reliability and durability, I’ve decided not to proceed with this IR option (after spending about a month or more on this).

rotors_ir

 

Magnets based clutch / torque limiter

One of the complaints from my older son was that on my first replica you couldn’t move the encryption rotors back and forth by hand – as the rotors were driven by small DC motors with gearboxes, the gearbox increased the torque output of the weak DC motor, but also didn’t allow turning the rotors by hand, because small holding force of the DC motor was converted to high holding force with the same gearbox. In this next version of my Enigma replica I decided to connect the DC motor to the gear using a small clutch / torque limiter, which had 6 magnets in each of the clutch’s parts. The magnets are strong enough to hold the clutch together, so the motor can drive the encryption rotor and make it rotate, but they are also weak enough to allow human to move the encryption rotor by hand and just allow to slip the clutch on the next letter position. This worked pretty well when the rotors was moving without friction, but in case it would hit any minor obstacle (e.g. the rotor touching the sensors due to slack), the clutch would slip due to the increased friction. The rotor movement by DC motor was left out in the finished version and the movement was completely virtual (not really moving, but the encryption accounted for a virtual rotor movement after each key press).

clutch2    clutch1

 

Better keyboard

One thing I’ve realised during making the first enigma replica was, that making the whole keyboard by just 3D printing it comes with a penalty – the shafts / pillars created some friction with the holes they were going through, because their surface wasn’t smooth – the layers after 3D printing are small, but still large enough to create friction.

In this second replica I’ve decided to use thin aluminium pipes, which are very smooth on the surface and they are sliding nicely through their openings in the case. Additionally, I’ve kept them long enough to minimise the movement of the buttons to the sides when pressing the button down. The catch was how to cut the aluminium tubes to exact same sizes, which the cut being nicely flat and perpendicular to the tube withouth using any special tools like lathe, as I don’t have those. I’ve modeled and 3D printed a holder for my Dremel cutter, so I could cut nicely, and also another variant of it to grind the ends of the pipe flush and perpendicular.

keyboard_pipes keyboard_front

 

Less wires with microcontrollers

I simplified the wiring of my first Enigma replica by using flat cables and IDC connectors, so instead of soldering 26 wires to connectors or to boards, I’ve just crimped the IDC connectors on both sides within seconds. But even then, during some testing, either there was a bad connection of connector to wire, or some dirt (flux?) on the pin headers, sometimes I’ve got missed key press. In this second version of Enigma I’ve decided to use microcontrollers to handle the buttons, lights, encryption and the plugboard, so each of these would be connected to the next one using only 4 wires – VCC (5V), GND, TX, RX. For 4 different PCBs (keyboard, lights, plugboard, rotors) to work together using single UART line I’ve decided to go with single master (the keyboard) and 3 slave devices, where master would drive the TX line, and the slave devices would respond on RX line. For this to work each slave device had a diode going from RX line to the TX pin of mcu and a pull up resistor on the RX line, so the slave device would either leave the line at H level, or pull it to L level when transmitting L. This diode + resistor is a substitution for open-collector (open-drain) output of the TX pin on slave device.

uart_slave

This is how the master-slaves communication works in my Enigma:

  • master devicekeyboard – scans for a pressed key. When a key is pressed, it sends a packet to plugboard – ‘ENS% \n‘, where ‘%‘ is the upper case letter which was pressed (A-Z)
  • plugboard receives the packet, checks if the the received letter is connected to any other letter, and sends a response back to master – either the same letter (no cable connected) or the updated / changed letter (cable connected between pressed and some other letter)
  • master device receives the letter from plugboard, sends a packet to the encryption rotors part – ‘ENR% \n‘, where ‘%‘ is the upper case letter which came from plugboard
  • encryption rotors part gets the packet, moves the rotors virtually (no real movement is happening), encrypts the letter based on all the rotors positions
  • encryption rotors part sends the packet back to master device ‘ENr%#\n‘, where ‘%‘ is the upper case letter after passding through the encryption rotors, and ‘#‘ is the currently selected (on power switch) brightness mode – ‘F‘ for full LED brightness, ‘D‘ from dim LED brightness
  • master device receives the packet from encryption rotors and sends a packet to lights part – ‘ENL%#\n‘, where ‘%‘ is the upper case letter received from encryption rotors and ‘#’ is the currently selected brightness mode
  • once the master device detects that the key has been released, it sends another packet to lights board – ‘ENL%O\n‘, where O means OFF

master_slave

Encryption rotors with 6 rows of holes

Alright, so now that I’ve went full microcontrollers on this project, I could minimise the components on the encryption rotors by using the encryption rotors just as a mere rotary encoders. With 26 letters on keyboard, lights and rotors, you must use at least 5 bits to represent each position. These 5 bits would be read through the holes on the encryption rotor, so each letter would have different set of holes, thus you could read the position of the rotor by just detecting the lights through the set of holes. An additional (6th) row of holes would be used to tell if the rotor is in the exact position on letter (e.g. on rotors movement by motor).

First attempt had holes directly on the big wheel, but that meant that the pcb with IR LED and phototransistors would have to be between the big wheels, which added an ugly spacing between them. In The second attempt I’ve moved the holes on the middle wheel, which was originally used just to transfer movement from DC motor to the big wheel.
After drawing the PCB, soldering parts, making the 3D model and printing it, I wasn’t very confident with the reliability of this, so I’ve decided to try something else.

rotors_binary    rotors_binary_whole

 

Just using rotary encoders?

I’ve looked around the internet and component resellers on other options of reading the position of a wheel, one of the most obvious options was to use a rotary encoder component. But again, from what I saw and read, I wasn’t fully confident in this option, either, because:

  • absolute encoders would be the best option, but these absolute encoders are either not available at my local reseller, or they were too expensive
  • having with exactly 26 positions (for absolute encoders) or 26 impulses per rotation would be ideal, but many of them have less, or I would go with much more (like 50 or 100 impulses), but they seemed too expensive
  • rotary encoders without detents (clicking) would be great, because if the impulses per rotation and my 26 letters wouldn’t match, it could try to stay in the wrong position
  • I’ve read too many negative comments on the internet on people complaining about cheap rotary encoders glitching, or their handling code wasn’t good enough and caused glitches
  • I couldn’t figure out a good way how to mount these rotary encoders into my setup of 3 wheels next to each other

This option was dropped before it was actually tried.

rotary_encoder

 

Encryption rotors using AS5600 (hall-based rotary magnetic position) sensor

During the investigation of how to detect the rotor position I’ve also found the hall-based magnetic position sensors, like the AS5600. You basically just need to put a small magnet infront of this sensor, rotate it, and you will read the angle either via digital interface (i2c, uart, spi), or as an analog value. They are cheap (at least if you but them from chinese shops) and seem to do exactly what I needed. So I’ve ordered 3 of them, changed my current design, did the code changes. I was using the analog output of the AS5600 sensor, which is the default output of the sensor if you don’t configure it in any way, and it was perfect… Well, almost. When I was testing just 1 of them, everything worked fine, I thought I have finally hit the solution which I will use. Then I’ve put all 3 of them together, and one of them decided to do reverse output after some power ups – so while 2 of the sensors were going nicely from 0 to 360 all the time, one of them decided going from 360 to 0 when he felt like it. It could have been a single faulty sensor, but I’ve lost confidence in it…

as5600_wireframe    as5600_solidas5600_photo

 

Encryption rotors using single track absolute encoder

After a discussion with my brother he proposed to use single track rotary encoder to detect the position of the rotors. The single track encoder allows to place all the sensors on the outside of the rotor, so the detection points would all be of the same size (compared to my attempt to just place holes with binary code on the rotor, with each hole being closer to the next one due to the circle of holes getting smaller in each row).

The thing that made the ‘single track rotary encoder‘ into ‘absolute single track rotary encoder‘ were the de Bruijn sequences. We got 26 letters, looking at 5 bits of information to determine the 1-in-26 position of the rotor. So what does de Bruijn sequence mean for my use case:
- generate 26 bit long (random) sequence
- create a 5-bit window, with which you check all 26 bits (bits 0-4, then 1-5, then 2-6, …)
- if all the 26 combinations are unique, this is a de Bruijn sequence
- this means, that in any rotor position I can tell the exact letter to which this rotor is turned to (== absolute position encoder)

An example of de Bruijn sequence of 26 bits is this: 01000100110000111100101101

de_bruijn_sequence

 

Encryption rotors with hall-based sensors

Now that I have found a valid de Bruijn sequence which could be used for single track absolute encoder (01000100110000111100101101), one of the options was to use magnets and hall sensors to read the 5 bit position of the rotors. The rotor was designed with holes for magnets, pcb for hall sensors was drawn, made and assembled, and even though I had done some tests and measurements on magnets vs hall sensors sensitivity, distance of detection, and so on, the version with the magnets was not 100% reliable. If the magnets were perfectly aligned with hall sensors, the output was correct. But if you would move the rotor like 30% on the way to the next letter, the results were not reliable…

de_bruijn_magnetic_wireframe  de_bruijn_magnetic_photo

 

Encryption rotors with photoelectric sensors

The final method I ended up using was the single track absolute encoder based on de Bruijn sequences, but an optical one – using existing photosensors (IR LED + IR phototransistor in a single package). Instead of adding magnets to rotors (like in the hall based option) I’ve created holes in the rotors, and these photosensors work fine even if they are not perfectly aligned to the exact position, as the holes are wide enough. The outputs of the sensors are connected to 74HCT165 (parallel load shift register), so even though I need to read 3 * 5 bits, they are all transfered to microcontroller using 3 wires only – LOAD, CLOCK, SERIAL_DATA (plus VCC and GND for power, obviously).

The individual de Bruijn sequences read from the absolute encoders are not numbers going linearly from 1 to 26, but their unique value is mapped in the microcontroller to th actual letters A-Z.

de_bruijn_opto_render   de_bruijn_opto_photo

 

The result

This second replica of Enigma machine has these attributes compared to the first (close) replica, which increase the reliability:

  • less wires connecting individual boards together (4 wires instead of 26 wires)
  • encryption / decryption in firmware only replaced the electro-mechanical encryption (rotors with pogo pins) (removing 4*26 = 104 connections which could fail, e.g. due to dirt on pogo pins / rotors pcbs)
  • no moving parts during encryption / decryption – the rotors do not turn after each key press, so lower chance of bad change to next rotor position
  • no risk of pogo pins scratching through the PCB on rotors now

With this setup I am confident that I can present this machine repeatedly and let my kids play with it over and over without it starting to fail due to mechanical or electrical reasons. It is definitely a reliability improvement over the close replica, even though the inner workings are now further away from the original.

It took more time to complete than expected – I thought that having one working version on which I would just build the changes, would reduce the project completion time, but trying out multiple options for the encryption rotors took some time. On the other hand, I’ve learned a couple of things and experimented a bit, so that’s great! :)

 

Encryption of HELLO to ILBDA, then decryption of ILBDA to HELLO on this replica can be seen here:

 

Photos of my second Enigma replica

enigma3  enigma4 enigma2

enigma1  enigma5

 

Comments are closed.