Mini Museum: Morse Telegraph Relay

Sometimes, you find the coolest things at antique stores. While on vacation last year in Maine, I came across a Morse model 4-C telegraph relay (circa 1900). It looked complete, so I bought it to add to my collection of cool historical tech. Once the contacts were cleaned off and the settings adjusted, it turned out to work quite well.
(Oxidation is an insulator, so vintage “patina” or no, it had to go.)

Here’s a clip of it sending “HELLO, WORLD” in Morse code.

The Morse 4-C relay, sending “HELLO, WORLD”.

To a computer engineer, vintage relays are a fascinating tease of possible alternate timelines. With even as simple a device as this (a pair of electromagnets moving a contactor) you have the basic building elements of a computer, provided a NC contact was added. And there’s even a spare contact screw for one.

With such a device, you can build logic gates. By combining them, you can make flip-flops, which can themselves be combined into memory devices, registers, counters, and all of the other pieces needed for a computer. We could have had computers in the 1800s!

…And not only does it still work, it’s crazy efficient for an electromechanical device! It will strike at about 2.5V (depending on settings), and draws only 25mA at that voltage. If I weren’t running it loose and loud to get that nice clicking sound for demonstrations, it could probably be driven directly by a microcontroller pin (or two of them ganged, worst case.) The whole works, in fact, is powered from a USB port! (The diode across the coil is to snub electrical noise when the coil is depowered.)

It’s kind of surprising to see such efficiency in a device that was already old enough to graduate high school around the time my grandparents were born. It’s a reminder that, although earlier eras didn’t have all of our technological knowledge, they still very much had competent engineers who often came up with amazing solutions, even with limited technology.

It’ll make a great first exhibit for the new Mini Museum of Computing History that I’m making.

Posted in Digital, Mini Museum, Nostalgia | Tagged , , , , | Leave a comment

Constructors in FreeBASIC

FreeBASIC continues to impress me with its modernity. I already found out that it’s possible to implement C-style pointers in FreeBASIC — and it turns out that you can have C++ – style constructor functionality, as well (code that runs automatically when an object is instantiated.)

For our “object,” we’ll use a custom FreeBASIC type :

type node
    x as double
    y as double
    visited as ubyte
    end type

It would be nice if we could assign default properties to these values automatically when they are allocated. Looking through the documentation, it seems provision is made for this:

type node
    x as double = 0
    y as double = 0
    visited as ubyte = 0
    end type

This works, of course. But what if we wanted random values — would that work?

type node
    x as double = rnd*100
    y as double = rnd*100
    visited as ubyte = 0
    end type

It turns out that this works, even when allocating an entire array of the type:

dim as node lotsOfNodes(1000)  'This will allocate the memory AND assign default values!

There was only one question, at this point. How far could we go? Was it possible to call a function and therefore run arbitrary code? Yes!

'Demonstration of "constructor"-type initialization

'Copyleft 2022, M. Eric Carr / Paleotechnologist.Net
'(CC:BY-NC-SA)

const MAXNODES = 20

declare function myFunction(x as double) as double

type node
   x as double = myFunction(100)
   y as double = myFunction(100)
   visited as integer = 0
   end type
   
dim as node f(MAXNODES) 'Nodes are initialized as they are created
dim as integer n

for n=0 to MAXNODES-1
   print f(n).x,f(n).y,f(n).visited 'View the contents to check initialization
   next n

sleep

function myFunction(x as double) as double
   static callCount as ulongint 
   callCount=callCount+1
   return rnd*x
   end function
   

Maybe they’re still not true “objects” — but they pass the duck test (with the possible exception of not having similar destructor functionality.) At any rate, it’s fun to see a language that’s ultimately still a descendant of 1964 Dartmouth BASIC capable of things like running arbitrary code implicitly on object creation.

…I wonder if it’s thread-safe?

Posted in BASIC, Coding | Leave a comment

Quadrature Encoders

One common task for an electronic device is to read the position of a rotary input. This could be to determine the position of part of a mechanical assembly, or simply to allow the user to select from various options using a scroll wheel.

Rotary encoders generally come in two varieties — absolute and relative. Absolute encoders, as you might expect, convey information about their absolute position. Even if the system has been powered off, these encoders will tell the system exactly where it is (plus or minus one position count.)

Quadrature encoders, on the other hand, do not remember any information about their position. They simply allow the microcontroller (or other circuit) to determine how far the encoder has turned while the microcontroller is monitoring it. This is perfect for jog dials used by the user, where absolute dial position doesn’t matter. Also, they’re easier to manufacture and work with — just two signal wires will do (plus ground and power.)

A generic quadrature encoder module from Amazon.
CLK and DT are the quadrature signals; SW is a normally-open SPST push switch contact.

Quadrature encoders are so named because they supply two phases of information, in quadrature. That is, these two phases transition 90 degrees apart in phase. One cycle of quadrature output (usually corresponding to one “click” of a dial) comprises four distinct phases. Turning it in one direction, the output might be

LL –> LH –> HH –> HL –> LL.

Turned the other way, this encoder would then output

LL –> HL –> HH –> LH –> LL.

Only one line changes state at a time (the criterion for a Gray code) — and by monitoring both lines, the direction of travel can be determined. (If the old state were HH, for example, the next state would have to be either LH or HL — one for clockwise and the other for counterclockwise. The state it changed into would tell you which direction it turned.)

As long as the microcontroller checks both lines faster than the maximum rate at which they can change, no position skip is possible. (Skipping may not be a huge issue on a jog wheel if it only happens once in a while — but skipping steps would make a positional encoder lose track of where it was, possibly causing a mechanical crash.)

Here is Arduino C code (tested on ESP32) to read two pins: ROTARYDAT and ROTARYCLK (defined elsewhere) to get the quadrature state of a rotary input, and update global integer variables called encHalfPhases and encTheta. (Using encHalfPhases directly resulted in the control being too sensitive to use reliably, so encTheta divides it by two.)


void IRAM_ATTR ISR() {

  //Interrupt handler for quadrature encoder on pins ROTARYDAT and ROTARYCLK.
  //Check the quadrature state, update theta, and GTFO...
  //CC:BY-NC-SA M. Eric Carr / Paleotechnologist.Net

  //Grab the new state (TODO: use raw GPIO reads to do this atomically and faster)
  uint8_t newState;
  newState=0x00;
  if(digitalRead(ROTARYDAT)){newState|=0x01;} 
  if(digitalRead(ROTARYCLK)){newState|=0x02;}

  //Update enctheta based on pin state changes
  if((newState ^ encState) & 0x02){
    //Clock changed. Increment or decrement count based on if clk and data match
    if((newState & 0x01)^((newState & 0x02)>>1)){
      encHalfPhases++;}
    else{
      encHalfPhases--;}
      }
  
  //Update the encoder state
  encState=newState;

  //Update theta
  encTheta=(encHalfPhases>>1); //Divide by two. Shift may be faster than div??
      
  }


The code is written to be run as an interrupt service routine (ISR), so it should execute and return very quickly, with no loops or delays. Attach it to interrupt-on-change-capable pins as follows:

  attachInterrupt(ROTARYDAT, ISR_quadrature, CHANGE);
  attachInterrupt(ROTARYCLK, ISR_quadrature, CHANGE);

Through the magic of interrupts, when either pin changes state, the ISR_quadrature routine is called automatically, the saved state is updated, theta incremented, and control is handed back to the main program. All of this should take a few microseconds on most MCUs.

The IRAM_ATTR requests that the compiler place this routine in SRAM instead of Flash memory, for speed of execution (interrupt handlers should be very fast, because you want it to finish before another important interrupt event comes along.)

If implemented as an ISR tied to interrupt-on-change, this routine should work reliably to track quadrature changes. Use it to implement jog controls or to see how far your robot has traveled etc.

A subtle note: Although it may be tempting to use CLK and DT to clock directional data in to a D flip-flop, this setup can glitch if CLK is toggled without changing DT. The “Clock” and “Data” names are misnomers; thinking of them as Phase A and Phase B is safer.

Share and enjoy!

Posted in Arduino, Building blocks, Digital, Electronics, HOW-TO, User Interface Design | Tagged , , , , , , , , , , , , | Leave a comment

New Toy: Round LCD Displays

Full-color (okay, 16- or 18-bit color) LCD and LED displays have been available as breadboardable, microcontroller-friendly modules for several years now. Recently, though, round displays have been appearing in hobbyist-friendly form. These can be thought of as rectangular displays that simply don’t implement pixels that aren’t in the circle radius.

A GC9A01 120-pixel, 18-bit SPI display as a breadboardable module.

GC9A01 display modules use an SPI bus interface, which is slightly more involved to set up than the ubiquitous I2C (or “Wire”) interface. There’s a good reason for this — at 240×240 resolution (really 120px radius), that’s some 45,000 pixels per frame, or north of 800,000 pixels. If you want to do any kind of video or animation, you need several frames per second. SPI is generally used for higher data rate applications, since it can run at 8Mb or more.

I followed the instructions in this video to get the display set up using a standard ESP32 dev board module. The Arduino GFX Graphics Library referenced in the video can drive the GC9A01 via the usual set of APIs for drawing pixels, lines, circles, etc.
Do note that these are 3.3V parts — it’s best to drive them with something modern and fast like an ESP32, which will probably be a 3v3 part itself. An Arduino Uno or PIC16F84A or 8051 could work with these, though — just very slowly. Maybe I’ll get the DrACo/Z80 to run one (via a voltage divider, at least).

They’d make great aircraft instrument replica displays, if only they were a little larger…

Posted in Arduino, Components, Digital, Toys, User Interface Design | Tagged , , | Leave a comment