Let's make circuit diagrams accessible: Part 1

Let’s say you’re a blind hobbyist who’s into electronics. You look online for project ideas, but 99% of circuit designs are provided as an image. That’s completely useless with a screen reader. Here’s what a circuit diagram (also called a schematic) looks like:

Schematic
A single transistor relaxation oscillator

If you have a Braille embosser that supports images, you might be able to enlarge the schematic, emboss it, and feel it. Chances are you don’t though - graphical embossers cost thousands of dollars, and even if you had one most graphics aren’t easy to feel when directly embossed. What you need is a textual description of the circuit that your PC can read to you.

There’s some precedent for this: the Smith Kettlewell Technical File published circuit descriptions for blind people for years, in both Braille and talking book format. Unfortunately a small publication simply can’t keep up with all the new parts and designs out there, with only a few people are writing these accessible project descriptions. Naturally you want to access as many different designs as possible. Maybe software could bridge this gap?

What we need is a way to automatically convert circuit designs by sighted people into text so that blind engineers and hobbyists can work independently. We need to figure out how to read the circuit diagrams by machine, and how to provide the most useful description possible. Neither is an easy problem. This post is the first in a series discussing the design and implementation challenges. The first order of business: what do we want the output to be?

Representing circuits in text

Here’s the design problem: how to represent complex circuits using only text? Text is linear while circuits have a web of different connections that all influence each other. Before we examine different approaches, it’s important to realize that we probably won’t get it right the first time and will need to refine the representation as we test it and get feedback. When we start writing a program to translate circuits into text, we’ll want to make it flexible so we can tweak the output format without rewriting the entire program.

Let’s explore some different ways to describe circuits.

Prose

The Smith-Kettlewell Technical File described circuits in somewhat free-form prose. For example, the circuit in the diagram above might be described this way:

A 5 volt supply is connected through a switch to a 300 ohm resistor. The other leg of the resistor connects to the positive lead of a 10uf electrolytic capacitor, and to the emitter of an NPN transistor. The base of the transistor is unconnected. The collector drives a speaker. The negative lead of the capacitor, the speaker, and the power supply are connected together.

This human-prepared description succinctly describes each part of the circuit in a natural way. These kinds of prose descriptions are probably the nicest way to explain a simple circuit. However, they tend to break down as we add more components and connections. The lack of a particular structure starts to work against us as we’re trying to “navigate” around a prose descriptions with tens or hundreds of connections. In addition, it’s not very easy to generate nice prose descriptions by machine. It might be worth exploring whether a large language model like ChatGPT could help with producing these for smaller circuits, given a more computer-readable input.

Are there more computer-friendly ways to represent circuits in text?

SPICE netlists

One answer comes to us from the 1970s. When Larry Nagel was building a program to simulate arbitrary analog circuits, graphical workstations were vanishingly rare and most computer usage was not interactive. The program he wrote, called SPICE instead took a textual description of circuits called a netlist, which an operator would first type up by hand.

For our example circuit depicted above, a netlist might look something like this:

Relaxation oscillator

** Electrical connections (netlist)
Q1 spkr NC emitter NPN_GENERIC
R1 v_in emitter 300
C1 emitter gnd 10µF IC=0
S2 supply v_in control 0 generic_switch ON
V+ supply gnd DC 5

* Fake part representing the speaker (note: this isn't really suitable for simulation)
R2 spkr gnd 100

** Parts metadata
.MODEL NPN_GENERIC NPN ()
.MODEL generic_switch SW(Ron=1m Roff=1Meg Vt=2.5)

.END

If you haven’t seen these before, you might be scratching your head.

Each line in the netlist section adds a part, gives a name to each of its connection points (these are called “nets”), and specifies options for the part. For example, take a line like R1 v_in emitter 300. The R1 is the part name, and since it starts with R SPICE knows it’s a resistor. Resistors have two connections and a resistance value. I named the connected nets v_in and emitter, so anywhere else in the circuit where I write v_in or emitter will be connected to the corresponding leg of this resistor. This diagram shows the net names I used and their corresponding logical nodes in the circuit:

Schematic

Another example: Q1 is our NPN transistor, whose emitter is connected to emitter, collector is connected to a net I named spkr and whose base’s disconnected net I called NC (for “not connected”).

You might notice, though, that we immediately had to make some compromises. SPICE is designed for simulating circuits on the computer, not for describing projects you can build, so there’s no component for a speaker. We had to simply “fake it” with a resistor to have something to connect. The switch is also a bit odd - component S2 is actually a voltage controlled switch - like a relay - but with no connection to its control pin. In fact, the format doesn’t have any standard symbol types for many common sensors or output components, and also doesn’t allow unconnected wires. The netlist above won’t actually simulate, though that’s beyond the scope of this series.

This ability to name nodes makes SPICE netlists a little easier to construct and understand for humans. The simplicity of SPICE’s format has endured for decades, well past the point where we needed to type circuits by hand. Nowadays many schematic drawing tools can export SPICE netlists, although they don’t typically create meaningful names for the nets, instead assigning numbers because they don’t have names for the wires. So you end up with netlists like this:

Q1 1 2 3 NPN_GENERIC
R1 4 3 300
...

If you thought the original version was hard to understand, this is even less self-descriptive. SPICE is also extremely terse, which is great when preparing punch cards on a keypunch machine but is less beneficial when you don’t have all the syntax and part codes memorized. Finally, since SPICE describes one component at a time, finding all the connections to a particular node in the circuit requires scanning all the lines in the circuit for a net with the same name or number. This is cumbersome when you’re trying to get a functional overview of a large circuit rather than building one up yourself.

Before we move on, I should mention that there are other formats for netlists beyond SPICE. Most of them seem to be less human readable and therefore not very relevant to our goal.

Tabular descriptions

Let’s try to design something that’s not free-form prose and not an input into simulation software. Our audience is 100% human, but the author is 100% machine. How will the human be consuming this information? And what does the human want to know that the machine can provide?

For those who don’t know, blind people often use a screen reader to read documents to them. Screen readers are somewhat smart - they try to understand the structure of a document and provide navigation. For example, they will pick out the hierarchy of headings in a web page and let you jump to a particular part. This is very useful - when it works. Screen readers can typically pull much more structural information from a well-written HTML webpage than from a document like a PDF. That suggests HTML is a good output format for us. Not only is it easy to generate and to share, but there are ways to provide extra hints to a screen reader built into HTML.

What does the human want to know? Let’s first turn our attention to something we’ve neglected so far: background information about the parts in the circuit. My prose description above didn’t say much about the transistor and resistor, or anything about the speaker. Sometimes we have that info for a design, and sometimes we don’t. At a minimum, the diagram has certain parts, and we can provide a parts list up front. For example, we can start our description with a table something like this:

Parts list:

Part Count Description Components
Supply 1 Generic 5V supply PS1
2N3904 1 NPN transistor Q1
300 ohm resistor 1 R1
Speaker 1 Generic loudspeaker LS1
10 uf capacitor 1 C1
Switch 1 SPDT switch S1

This table isn’t very interesting for a simple circuit with lots of generic parts, but once we start using chips and specialized components the descriptions will be more meaningful. Putting it up front also allows the hobbyist to check their parts drawer and see if they’ve got the relevant components, without spending time reading the whole description. We might want to provide even more details about each part, such as pin assignments, if we have them. This could go in a separate section that the reader could skip if they wish.

For the circuit itself, we can describe each net in turn, showing all the part pins that are connected to that particular net. Knowing which parts are connected to a particular point. I’m using the term “connections” here so that people who land on the description can figure out the meaning of the jargon word “net” from context.

Connections:

Net Connections
1 PS1 - lead, S1 pin 1
2 S1 pin 2, R1 pin 1
3 R1 pin 2, C1 + lead, Q1 emitter pin
4 Q1 collector, LS1 + lead
5 PS1 - lead, C1 - lead, LS1 - lead

Notice that Q1’s base has no net, since there’s only one pin connected in this unusual circuit we can leave it out. These nets have arbitrary numbers since most circuit diagrams don’t name their wires. If we have meaningful names for some or all of the points, we can also include them as net names like this:

Connections:

Net Connections
1 (supply) PS1 - lead, S1 pin 1
2 (v_in) S1 pin 2, R1 pin 1
3 (emitter) R1 pin 2, C1 + lead, Q1 emitter pin
4 (spkr) Q1 collector, LS1 + lead
5 (gnd) PS1 - lead, C1 - lead, LS1 - lead

These nets represent fundamental nodes in the circuit, each with its own specific role to play. This gives us a starting point to build from, and it’s easy to see how to extend this to more parts and connections.

Of course, a more complex circuit will be harder to understand, but that’s also the case with diagrams. The biggest missing piece is any form of hierarchy or structure; if we could infer that a diagram we’d improve the output.

What’s next

We’ve got an idea for an output format, now we need input! I’ll describe how we can start reading circuits programmatically and representing them in data structures.

by Troy