Posts Tagged Arduino

Vacuum Tube LEDs: Now With Morse Code

Adding Mark Fickett’s non-blocking Morse Arduino library turns the tubes into transmitters:

21HB5A on platter - orange green

21HB5A on platter – orange green

The plate cap LED blinks the message in orange, while both LEDs continue to slowly change color as before.

You define a Morse sender object (C++, yo!) by specifying its output pin and code speed in words per minute, dump a string into it, then call a continuation function fast enough to let it twiddle the output bit for each pulse. Obviously, the rate at which the callback happens determines the timing granularity.

However, setting a knockoff Neopixel to a given color requires more than just a binary signal on an output pin. The continuation function returns false when it’s done with the message, after which you can initialize and send another message. There’s no obvious (to me, anyhow) way to get timing information out of the code.

The easiest solution: called the Morse continuation function at the top of the main loop, read its output pin to determine when a dit or dah is active, then set the plate cap color accordingly:

LEDMorseSender Morse(PIN_MORSE, (float)MORSE_WPM);
Morse.setMessage(String("       cq cq cq de ke4znu       "));
PrevMorse = ThisMorse = digitalRead(PIN_MORSE);
if (!Morse.continueSending()) {
ThisMorse = digitalRead(PIN_MORSE);
if (ThisMorse) {             // if Morse output high, overlay
PrevMorse = ThisMorse;;               // send out precomputed colors
<<compute colors for next iteration as usual>>

I use the Entropy library to seed the PRNG, then pick three prime numbers for the sine wave periods (with an ugly hack to avoid matching periods):

uint32_t rn = Entropy.random();

Pixels[RED].Prime = PrimeList[random(sizeof(PrimeList))];

do {
  Pixels[GREEN].Prime = PrimeList[random(sizeof(PrimeList))];
} while (Pixels[RED].Prime == Pixels[GREEN].Prime);

do {
  Pixels[BLUE].Prime = PrimeList[random(sizeof(PrimeList))];
} while (Pixels[BLUE].Prime == Pixels[RED].Prime ||
        Pixels[BLUE].Prime == Pixels[GREEN].Prime);

printf("Primes: (%d,%d,%d)\r\n",Pixels[RED].Prime,Pixels[GREEN].Prime,Pixels[BLUE].Prime);

In the spirit of “Video or it didn’t happen”: YouTube!

The Arduino source code as a GitHub Gist:




Vacuum Tube LEDs: Fully Dressed 21HB5A

Black PETG definitely looks better than cyan for this job:

21HB5A - Black PETG base - flash

21HB5A – Black PETG base – flash

Holding the plate cap to the tube with a thin ring of opaque epoxy cuts down on the glare under its edge:

21HB5A - Black PETG base - cyan phase

21HB5A – Black PETG base – cyan phase

Fire in the bottle!

21HB5A - Black PETG fittings - punched drive platter - purple phase

21HB5A – Black PETG fittings – punched drive platter – purple phase

It’s still running basically the same Arduino code as before, but I have some ideas about that



Vacuum Tube LEDs: Hard Drive Platter Base

Stainless steel socket head and button head screws add a certain techie charm to the hard drive platter mirroring the Noval tube:

Noval - Black PETG base - magenta phase

Noval – Black PETG base – magenta phase

Black PETG, rather than cyan or natural filament, suppresses the socket’s glow and emphasizes the tube’s internal lighting:

Noval tube on platter - button-head screws

Noval tube on platter – button-head screws

The base puts the USB-to-serial adapter on the floor and stands the Pro Mini against a flat on the far wall:

Noval tube socket and base - interior layout

Noval tube socket and base – interior layout

A notch for the cable seems like a useful addition subtraction to the socket, because that cable tie just doesn’t look right. I used 4 mm threaded inserts, as those button head screws looked better.

The solid model looks like you’d expect:

Vacuum Tube Lights - hard drive platter base - solid model

Vacuum Tube Lights – hard drive platter base – solid model

Those are 3 mm threaded inserts, again to get the right head size screw on the platter.

The height of the base depends on the size of the socket, with the model maintaining a bit of clearance above the USB adapter. The OD depends on the platter OD, with a fixed overhang, and the insert BCD depends on the OD / insert OD / base wall thickness.

Although I’m using an Arduino Pro Mini and a separate USB-to-serial adapter, a (knockoff) Arduino Nano would be better and cheaper, although the SMD parts on the Nano’s bottom surface make it a bit thicker and less suitable for foam-tape mounting.

I drilled the platter using manual CNC:

Hard drive platter - Noval base drilling

Hard drive platter – Noval base drilling

After centering the origin on the platter hole, the hole positions (for a 71 mm BCD) use LinuxCNC’s polar notation:

g0 @[71/2]^45
g0 @[71/2]^[45+90]
g0 @[71/2]^[45+180]
g0 @[71/2]^-45

I used the Joggy Thing for manual drilling after each move; that’s easier than figuring out the appropriate g81 feed & speed.

The 3D printed base still looks a bit chintzy compared with the platter, but it’s coming along.

The OpenSCAD source code as a GitHub Gist:



Counterfeit FTDI USB-Serial Adapter Roundup

As part of the vacuum tube lighting project, I picked up a bunch of USB-Serial adapters, with the intent of simply building them into the lamp base along with a knockoff Arduino Pro Mini, then plugging in a cheap USB wall wart for power. An Arduino Nano might make more sense, but this lets me use the Pro Minis for other projects where power comes from elsewhere.

Anyhow, I deliberately paid a few bucks extra for “genuine” FTDI chips, knowing full well what was about to happen:

Assorted FT232 Converters

Assorted FT232 Converters

The two boards on the bottom have been in my collection forever and seem to be genuine FTDI; the one on the left came from Sparkfun:

FT232RL - genuine

FT232RL – genuine

The top six have counterfeit chips, although you’d be hard-pressed to tell from the laser etching:

FT232RL - fake

FT232RL – fake

In addition to the boards, I picked up the blue square-ish cable adapters for the HP 7475A plotter project and, again, paid extra for “genuine” FTDI chips. The other adapters, based on Prolific PL2303 chips, I’ve had basically forever:

Assorted FT232 Converters - Cabled

Assorted FT232 Converters – Cabled

Those two have chips with different serial numbers: genuine FTDI chips get different serial numbers programmed during production. The counterfeits, well, they’re all pretty much the same.

Display the serial numbers thusly:

Bus 002 Device 024: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
... snippage ...
udevadm info --query=all --attribute-walk  --name=/dev/bus/usb/002/024 | grep ser

All the counterfeit FTDI chips report the same serial number: A50285BI. The PL2303 chips don’t report serial numbers.

For my simple needs, they all work fine, but apparently fancier new microcontrollers expect more from their adapters and the counterfeits just can’t live up to their promises.

For a while, FTDI released Windows drivers that bricked counterfeit chips; the Linux drivers were unaffected.


ITead Studio Quasi-Colorduino RGB LED Matrix Shield: Redesign Doodles

Some notes on a recent acquisition that ought to allow random dots with individual brightness control (unlike my simple resistor-limited hack job):

Color Shield - DM163 M54565 - demo

Color Shield – DM163 M54565 – demo

A Colorduino is a dedicated board that combines an Arduino-class microcontroller with hardware drivers for an 8×8 RGB LED matrix, with daisy-chaining I/O to build bigger displays. The Colors Shield you see above omits the Arduino circuitry and daisy-chaining hardware: it plugs atop an ordinary Arduino UNO-class board as a dedicated 8×8 tile driver.

I do not profess to understand the ancestry & family tree of those designs and their various incarnations. This schematic doesn’t match the knockoff hardware in hand, which isn’t surprising after half a dozen years of relentless product cheapnification:

ITeadStudio - RGB LED shield - DM163 M54564 - SPI notes

ITeadStudio – RGB LED shield – DM163 M54564 – SPI notes

It comes close enough for a big-picture overview…

The DM163 has 8×3 constant current sink PWM pins that connect to the column cathodes of the RGB matrix. It provides either 8 or 6 bits of PWM control for each output, with either 6 or 8 bits of gamma correction to make the grayscale shades work out properly (those are separate shift registers and the PWM generators use both, so the chip doesn’t care how you divvy up the 14 bits).

The three 1 kΩ resistors set the current to 60 mA per output pin. The LED matrix might support anywhere from  70 to 120 mA peak current per LED, but I doubt the supplied matrix matches any of the available datasheets. The total current depends on the number of LEDs lit on each row, so large dark areas are a Good Thing.

The serial protocol looks enough like SPI to get by, with controls for Reset, Latch, and Bank Select.

The board has no power supply other than the single Arduino VCC pin, so you’re looking at a peak of 24 x 60 mA = 1.44 A through that pin. The Arduino regulator must supply that load pretty much full-time, which is obviously a Bad Thing; plan on plenty of dark areas.

The DM163 SPI connections don’t use the Arduino’s hardware SPI, so it’s full-frontal bit-banging all the way. Three DM163 control bits use a trio of analog inputs as digital outputs. No harm in that, works fine with the knockoff Neopixels.

The M54564 is a PNP high-side driver converting logic-level inputs to the current required for the row anodes of the matrix. The eight input bits are non-contiguous across the Arduino’s digital outputs. You could turn on all the M54564 outputs at once, which would be a Bad Thing.

You shift 24 bytes of RGB data into the DM163 and latch the data, then raise one of the M54564 inputs to enable a given row of LEDs, which light up with the corresponding colors.

The bit-banged SPI runs at 1.9 µs/bit and sending all 24 bits to the DM163 requires 450 µs. With a 100 Hz refresh, that’s a mere 5% overhead, but the fact that the board soaks up essentially all the I/O pins means the Arduino isn’t not doing much else in the way of real-world interaction.

The Arduino driver, of dubious provenance, sets Timer 0 for 100-ish Hz interrupts. Each interrupt shifts another batch of bytes into the DM163 and selects the appropriate row. The driver uses a double-buffered array that soaks up 2x8x8x3 = 384 bytes of precious RAM, in addition to a bunch of working storage.

If I were (re)designing this board…

A separate power input jack for the DM163 that might optionally feed the Arduino’s VIN raw power pin.

Use the Arduino SPI hardware, dammit.

Put an HC595 shift register behind the M54564, so you’d shift 24 + 8 = 32 bits into the board, then strobe the latches. That eliminates eight digital pins used as a parallel port.

You’d surely want to disable the row driver while switching the column drivers to avoid ghosting, so figure on a separate output enable for the HC595. That tri-states the 595’s outputs; although the M54564 has internal pulldowns, it might need more.

It’s entirely usable as-is, but sheesh it’d be so easy to do a better job. That wouldn’t be software compatible with all the Arduino Love for the existing boards out there; there’s no point.



Leave a comment

Switch Contact Bounce

An Arduino hairball for an upcoming Digital Machinist column:

Arduino UNO clone - test setup

Arduino UNO clone – test setup

A short program monitors the switch. When it closes, the program reads the analog voltage from the pot and blinks the LED (on Pin 13, so you don’t need an external LED) for that number of milliseconds.

Some diligent rummaging produced a spectacularly bouncy switch (lower trace) with the output pulse (upper trace):

Contact Bounce - Matsuhita - NO 1

Contact Bounce – Matsuhita – NO 1

A longer timebase shows it’s rattling around for nearly half a millisecond:

Contact Bounce - Matsuhita - NO 2

Contact Bounce – Matsuhita – NO 2

The second pulse in the upper trace shows that the code gets around the loop() fast enough to retrigger on the same button push, which is part of the lesson in the column

A midrange timebase:

Contact Bounce - Matsuhita - NO 3

Contact Bounce – Matsuhita – NO 3

You could surely get a few random numbers out of that noise, although the first few bounces seem surprisingly consistent.


Random LED Dots: Entropy Library for Moah Speed with Less Gimcrackery

A discussion over the Squidwrench Operating Table about injecting entropy into VMs before / during their boot sequence reminded me that I wanted to try the Entropy library with my 8×8 RGB LED matrix:

8x8 RGB LED Matrix - board overview

8×8 RGB LED Matrix – board overview

The original version trundled along with random numbers produced by timing Geiger counter ticks. The second version, digitizing the amplified noise from a reverse-biased PN junction, ran much faster.

What’s new & different: the Entropy library measures the jitter between the ATmega328 watchdog timer’s RC oscillator and the ceramic resonator (on Pro Mini boards) driving the CPU. It cranks out four bytes of uncorrelated bits every half-second, which isn’t quite fast enough for a sparkly display, but re-seeding the Arduino PRNG whenever enough entropy arrives works well enough.

One could, of course, re-seed the PRNG with Geiger bits or junction noise to the same effect. The key advantage of the Entropy library: no external hardware required. The downside: no external hardware required, so, minus those techie transistors / resistors / op amps, it will look like Just Another Arduino Project.

Reverse-bias noise amplifier - detail

Reverse-bias noise amplifier – detail

Le sigh.

In any event, the Entropy library has excellent documentation and works perfectly.

The Arduino PRNG can produce results fast enough for wonderfully twinkly output that’s visually indistinguishable from the “true” random numbers from the Geiger counter or PN junction. I dialed it back to one update every 5 ms, because letting it free-run turned the display into an unattractive blur.

The top trace shows the update actually happens every 6 ms:

Entropy TRNG - LED update vs refresh

Entropy TRNG – LED update vs refresh

The lower trace shows that each matrix row refresh takes about a millisecond. Refreshes occur on every main loop iteration and interfere with the update, not that that makes any difference. Should it matter, subtract one from the update period and it’ll be all good.

The Arduino source code as a GitHub Gist: