Prototype VFD Driver Tested With Placeholder LED

PIC16F18345 VFD driver PCB

Once I had assembled our first prototype vacuum fluorescent display (VFD) driver circuit board, it’s tempting to connect it right up to our salvaged VFD and bask in its glow. But that would have been premature: there were bugs still to be ironed out with potential for fatal errors to damage or destroy our one and only salvaged VFD.

The first tests were what we used to test our bread board prototype: drive a 4-digit 7-segment LED, a Lite-On LTC4627-JR from my earlier PIC display driver project. From there I could verify 8 of 11 segments on this driver board functioned as expected by a demo program that constantly flips between two patterns, one spells “Hello” and the other “Ahoy”.

I then tested the I²C capability with a small update, changing the second pattern from “Anoy” to a very mutilated “MLE”. (It’s hard to do “M” on 7 segments.)

These experiments exposed a few minor bugs, just as tests were supposed to. After they were fixed I expanded my test with a second LTC4627-JR for eight total segments. I also expanded my use of I²C by continuously updating all digits from Raspberry Pi to create a text marquee. This experiment exposed some timing issues that is visible as a slight lag just as the “u” in “thank you” came up on screen.

That lag was diagnosed to my code inside a timer interrupt service routine (ISR). On a simple chip like this PIC, a hardware interrupt signal could not interrupt another ISR already in progress. So when my code inside a timer ISR grew beyond a certain point, it started interfering with timely response to hardware interrupts necessary for I²C communication. The solution is to put my timer ISR on a severe diet, moving almost all of its bulk elsewhere so that I²C handlers could run with minimal interference.

Once the software problems were sorted out, I started experimenting with the flexibility given by this project’s design decision to keep PIC code simple. It meant I could play with patterns that have nothing to do with displaying letters or text. I decided to try a pattern that keeps a single lighted segment running through the display in a figure 8. When cycled through all digits like a text marquee, it gave us a neat looking wave. I look forward to more experiments in driving a multi-segmented display in unusual ways.

Assembling Prototype VFD Driver PCB

PIC16F18345 VFD driver PCBIn addition to exploring the idea of aggressively packing chips densely, there were a few other design considerations in building our prototype driver PCB.

Why I²C?

When I was tearing my hair out trying to figure out why a tried-and-true piece of template code has stopped working, I was sorely tempted to move to some communication protocol other than I²C… good old TTL Serial always looks good whenever I run into a problem.

The answer is voltage compatibility: I want my driver board to be capable of running at either 3.3V or 5V, which is easy to do with an old 8-bit chip like the PIC16F18345 I’m using: give it power anywhere in its specified range (and probably a bit beyond that range) and it’ll happy run. But this doesn’t necessarily apply to whatever my driver board will accept commands from. Fortunately, I²C was designed from the start to accommodate devices that work off different VCC levels. So something like a Raspberry Pi (3.3V) can communicate with my PIC. (5V).

Pin Assignments

In addition to moving the decoder output pins so it could be placed immediately adjacent to my PIC, I also took advantage of my particular PIC’s feature of Peripheral Pin Select (PPS) by moving the I²C pins (handled by Master Synchronous Serial Peripheral – MSSP) from their default to RA4 & RA5 for easier routing on the PCB and easier data writes in my code.

Pin Isolation

This is the first time I planned to use pins RA0 and RA1 on a PIC16F18345 project. I usually avoid them because they are used as in-circuit system programming data (ICSPDAT) and clock (ICSPCLK) pins. They’re perfectly usable outside of this scenario, but they must be disconnected from the rest of the circuit during programming. In this case, it meant I had to put in two jumpers that are removed during programming. The jumpers are installed exactly where my PICkit 3 programmer would attach, so there’s no way for me to forget to remove them when reprogramming this chip.

Wires From CAT-5E Network Cable

Even with all these concessions to easier routing on a prototype PCB, there will still be an unavoidable nest of wires. In order to keep things tamed, I harvest my spool of CAT-5E network cable for wires that are thin and rigid. Thin wires help me fit more wires in a small volume, and rigid wires stay where I’ve put them. In addition to being affordable and easily available, the four twisted pairs of wires give me eight different insulation colors to help me keep track of which wire goes where.

Chip Packing Experiment On Prototype VFD Driver PCB

While we were building a breadboard prototype for our VFD driver, we weren’t terribly concerned with chip layout as it was largely constrained by the practicalities of a bread board anyway. Once we start thinking about transferring it to a PCB, however, we had more flexibility to be creative. The prototype printed circuit board is a grid of through-holes that we can use in any way we like. How shall we abuse this power?

While looking at how wires were run on our bread board, I noticed that there were a few pins that were perfectly aligned from one chip to the next. Placing the decoder output on PIC pins RB4, RB5, and RB6 lines them up perfectly with the input pins of 74138 decoder. As for the decoder output, six out of eight pins were directly lined up with a ULN2003.

Chip pin alignment

This allows some fairly straightforward wiring solder as these wires will not cross over each other and won’t tangle up and make a big mess. By itself that is valuable, but we were tempted to go one step further: how about we eliminate the wires entirely and jam those chips together? If they share the same PCB through-hole, that would eliminate wire soldering entirely.

It sounded good in theory, but in practice the chips are just a little too large for us to fit them three-abreast. I could push my decoder up against my PIC, but couldn’t push the Darlington array alongside the decoder as well. This is probably for the best – there’s value in having the ULN2003 lined up with its siblings.

Chips tightly packed on PCB

We may learn in the near future why this is a bad idea, but it’s all part of the fun: trying things and seeing how they work. (Or not, as the case may be.)

Breadboard Prototype of VFD Driver Project

Once we had some idea of what we wanted to do, it’s time to start wiring things up on a breadboard to see if it actually does anything interesting. Dealing with actual chips meant reading their data sheets and figure out where the rubber meets the road and how well theory meets practice.

Not having a lot of first-hand experience with such modules, it was a great way to learn by doing. The first surprise was behavior of the 74HC138 decoder module: Conceptually it takes a three-bit input and decodes it to one of eight pins. Conceptually we thought that meant raising one of eight pins high, but it actually lowers one of eight pins low.

We thought this was going to be a problem and started looking into inverters… before we realized it is a perfect pairing with ULN2003 to do what we actually wanted: The ULN2003 line inverts its input in the sense that when an input pin is high it connects the output pin to ground. So the output of a 74HC138 decoder (seven pins high, one pin low) driving ULN2003 results in seven pins connected to ground and one floating. We can work with this.

A 4-digit, 7-segment LED module stood in for the vacuum fluorescent display while all the logic got worked out. This flexibility is exactly where a breadboard is strong, letting us experiment and verify pieces of our circuit piecemeal. But it is not great for looking respectable or for long-term reliability, so once it successfully ran the LED module, we start planning to commit the design to soldering parts on a prototype PCB.

PIC16F18345 VFD breadboard and PCB

Hardware Side of Keeping PIC Driver Simple

For the VFD driver project, there were software design motivations to keep things simple. But that’s not the whole picture, there were also motivation from hardware constraints too. My previous projects to make a PIC drive a multi-segmented LED display had fairly simple wiring that connected most output pins of my PIC to current-limiting resistors. A few of the lines could have seen current flow higher than what a PIC is capable of handling, and those were handled with simple transistors. I knew there existed chips designed specifically to drive LEDs, but I wanted to learn the principles of controlling one myself.

Building something to drive a VFD requires dealing with voltages different and sometimes far higher than what is required to drive LED display modules. During our probe of this specific VFD we saw 2.5V AC and 30V DC, atypical of logic circuits. And just as there existed dedicated LED driver chips, there exist chips specifically designed to drive VFD modules, but again the project goal was to learn by building one ourselves.

So we turn to our standard electronic hobbyist toolbox item for controlling power and voltage beyond what our standard parts can handle: the ULN2003A line of Darlington arrays. The go-to solution for controlling inductive loads like relays and small motors, it can handle voltages up to 50V which we need for a VFD.

And again, with multiple different display projects on the horizon, it didn’t make sense to create a controller with hardware pinout specifically tailored to a specific unit. To keep things simple and consistent across displays, all of our controller outputs will be either left floating or tied to ground. If a particular device desires a particular pin to be at a higher voltage, we’ll have to wire up a pull-up resistor on that device’s specific interface board. We will learn if this concession to consistency will cause problems down the line.

VFD driver schematic

Why And How Of Simpler PIC Display Driver

Earlier in my outline for starting a new PIC display driver project for a vacuum fluorescent display (VFD), I mentioned one objective was to “keep the PIC side very simple and move more display-specific logic into driving code“. Let’s go into more detail on that part of the plan.

In my previous PIC display projects, the code was written for a specific multi-segment display unit as part of the overall project. This meant the source code reflected whether the LED was a common-anode or common-cathode design, it also knew about which segment represented which parts of a particular digit. This knowledge was required because I put priority on making control communication interface easy. For the temperature demo, making my display unit show “72.3F” was a matter of sending the actual UTF-8 text string “72.3F” as bytes. The PIC then parsed that string and determined which segment to illuminate.

But there’s a good chance we have several other matrix display projects in the future, and I didn’t want to invest the time to hard code intricacies of each unit into the PIC. It would be much easier to adapt and experiment if such logic was moved to a more developer-friendly environment like Python on a Raspberry Pi. In the case of the current NEC VFD under consideration, there are segments corresponding to days of the week and other function specific segments like an “On and “Off” text, “OTR”, little clock icon, etc. Most of which won’t necessarily be present on another VFD unit, why spend the time to embed such knowledge in my PIC driver?

NEC VSL0010-A VFD Annotated

We also want the flexibility to explore using the display in ways that are far afield of its original intent. For starters, that seven-segment display in the center doesn’t have to be constrained to display numbers for a clock. All these desires meant moving away from performing data interpretation on the PIC.

Instead, the PIC will accept a raw data stream where each bit corresponds to whether a segment is on or off. Each byte will correspond to 8 segments in a grid, and so forth. This means the task of mapping a desired digit to a set of segments will be the responsibility of driver code on host device rather than PIC peripheral. PIC will only concern itself with rapidly cycling through the matrix of digits keeping them all illuminated.

Old Microchip MCC Boilerplate for MSSP Requires C90 Compatibility Mode

PIC16F18345 VFD driver PCB

I’ve figured out how to compile the new Microchip Foundation Services Library boilerplate code for implement I²C peripheral, only to learn it doesn’t do what I wanted it to do. Well darn, it’s time to go back to the tried-and-true I²C boilerplate code I’ve used in earlier projects. It’s still there, it compiles with only the “this is outdated” warning, and I knew it worked well enough to be a good starting point for my projects. It was the tried-and-true known quantity that shouldn’t give me any trouble at all.

Except it did.

The code compiled fine, but it didn’t actually work. It would give a response to the first I²C query but then it would stop responding. Here’s the default boilerplate code, which responds to address 0x08, as probed by a Raspberry Pi using i2cdetect tool.

pi@raspberry:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- 08 -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

That part looks good, the problem comes when we run the same tool again.

pi@raspberry:~ $ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

It has disappeared from scan, as it no longer responds to I²C commands sent to its address.

Comparing the I²C boilerplate code with my old LED project, I saw no differences worth mentioning. It should be the exact same code but it no longer does the exact same thing. What has changed between my old LED project and now?

Eventually I found the answer: Microchip has updated the XC8 compiler to C99, and this compiler update causes problems with existing code. I previously saw this in the form of compiler errors on an empty MCC-generated project. I no longer see compiler errors on an empty project template but arguably this is worse: no compiler errors but silent changes in behavior.

The solution is the same as before: change project properties so XC8 compiler uses its old C90 compatible mode. Once I switched over, the I²C boilerplate code functioned as expected.

Project Properties

Since Microchip has marked this old I²C boilerplate code as deprecated, I don’t expect them to bring it up to date with the new compiler. And given its history of causing me headaches, I guess I’ll plan on using C90 mode for all my projects for the foreseeable future.

Getting Microchip Foundation Services Library I2C Boilerplate To Compile

PIC16F18345 VFD driver PCBMotivated by the desire to get an old VFD up and running for fun, I set up my PIC16F18345 to act as an I²C peripheral. I could write my own code from scratch, or I could build on top of boilerplate code published by Microchip for implementing an I²C slave device. My problem is that I had two choices – the new thing that doesn’t compile, or the old thing that is deprecated.

I’ve since figured out how to resolve the two error messages to compile the new thing, formally called Foundation Services Library.

The first compiler error message was this:

In file included from mcc_generated_files/USBI2C_app.c:25:
mcc_generated_files/drivers/i2c_slave.h:55:34: error: unknown type name 'interruptHandler'
void i2c_slave_setReadIntHandler(interruptHandler handler);
^

Searching elsewhere in the generated boilerplate, I found a declaration for interruptHandler in another different header file. Copying it into i2c_slave.h addressed the “unknown type name” error.

typedef void (*interruptHandler)(void);

However, that error was replaced by a warning that there are now duplicate declarations of interruptHandler. This seems silly – if there were a declaration to collide with, it should not have thrown an unknown type name error signifying the declaration’s absence.

MPLAB should either not throw the error, or not raise the warning, but it is doing both. I have yet to figure out if the toolchain is busted or if the boilerplate code is. For now, though, I could proceed to the next problem.

The second compiler error message was this:

mcc_generated_files/USBI2C_app.c:30:14: error: no member named 'SSP1IE' in 'PIE3bits_t'
PIE3bits.SSP1IE = 1;
~~~~~~~~ ^
1 error generated.

This one was easier to figure out – go into the header files for this chip and look for SSP1IE. I found it declared on PIE1bits instead of PIE3bits. So to get this code to compile, I changed the boilerplate code from this:

void USBI2C_Initialize(void){
PIE3bits.SSP1IE = 1;
i2c_slave_open();
}

To this:

void USBI2C_Initialize(void){
PIE1bits.SSP1IE = 1;
i2c_slave_open();
}

What does PIE1bits.SSP1IE actually do? I’m not sure so I’m not positive this is actually the correct fix. But at least all of the foundation boilerplate compiles, and I start browsing through sample code for MikroElektronika USB-I2C Click module to figure out what it does and what I can do with it. Reading through code and comments, I saw this comment block.

- This module only supports byte operations. Block read and write operations is
not yet supported by MCC Foundation I2C Slave Drivers.

This comment implies Microchip has decided to deprecate their previous I²C library even though the new library is unable to duplicate important functionality. If true, this is… unsatisfactory. I want block read and write operations for my project.

Now I’m even more motivated to stay with the old code, but unfortunately there were some complications with that, too…

I2C on PIC: Microchip Foundation Services Library Is Less Beginner-Friendly

About a year and a half ago I poked my head into the world of I²C programming with my PIC16F18345 chip. I was pleasantly surprised the MCC boilerplate code actually included an example implementation emulating an I²C EEPROM. That turned out to be a great way for me to get started.

Now that I have another PIC project in mind, I retraced my steps and saw this:

I2C driver will be removed soon

In file included from mcc_generated_files/mcc.h:55:
mcc_generated_files/i2c1.h:55:2: warning: "This version of the I2C driver will be removed soon and the correct driver to use is the Foundation Services driver" [-W#warnings]
#warning "This version of the I2C driver will be removed soon and the correct driver to use is the Foundation Services driver"

Looks like what I had used before is on its way out.

Since this is a new project, I thought I might as well check out what the new shiny object has to offer. Reading around the web, I found complaints that the previous MCC I²C code would work when conditions are ideal, but it was not very good at letting developers write code to handle error conditions. This might not be important in hobbyist projects like mine, but it was of great importance to people trying to engineer real products.

I added the Foundation Services Library module for my PIC’s MSSP. After code generation was complete, I went into the generated header files and saw a lot more functions declared than previous boilerplate code. There were a few related to overflow and bus collision errors, which I assume were there to address complaints about error handling capability.

Unfortunately, there is no longer a friendly example implementation to reference. There are a lot of declarations but no information on how to use those functions. Microchip’s claim that the Foundation Services Library code is self-documenting has been wholeheartedly laughed at by other forum users. But the forums did point me to Microchip’s  MikroElektronika Click Library which interfaces between those nifty little Click modules to a PIC using Foundation Services Library. The trick is finding one that most closely matches what I’m trying to do. Many Click modules are I²C slaves controlled by a PIC acting as master, I wanted my PIC to act as I²C slave accepting commands. A first pass through the Click library found only the USB-I2C Click module, so I installed sample code corresponding to that module and tried to build it.

unknown type name interruptHandler

In file included from mcc_generated_files/USBI2C_example.c:36:
mcc_generated_files/drivers/i2c_slave.h:54:34: error: unknown type name 'interruptHandler'
void i2c_slave_setReadIntHandler(interruptHandler handler);

Sample code that fails to compile is… not the height of beginner friendliness.

After 30 minutes of hunting around, I failed to find a solution to this problem and decided to return to the old deprecated I²C driver. It may not be the newest and shiniest thing, but it does compile and run.

Dusting off Past PIC LED Driver Projects For Potential VFD Driver

While the VFD salvaged from a VHS timer/tuner unit was designed to run on voltages unfamiliar to me, once we probed the control pinout I found it much less intimidating. The entire array can be treated as a matrix with its eight grids along one axis and ten elements along another axis. The array is only partially filled: there aren’t actually 80 elements on the VFD. A driver chip will energize one grid at a time, and energize the desired elements within that grid. After some time, the driver will move on to the next grid and its corresponding elements. When the switching happens quickly enough, our human eye sees only a completely illuminated display and would not notice that grid-to-grid cycling.

NEC VSL0010-A VFD Annotated

This general principle is identical to how I drove a LTC-4627JR 7-segment LED array in an earlier PIC project. The only real difference is that the transistors I had used earlier is only good for the +5V used by that LED array and not suitable for +30V for this VFD, but that can be addressed by substituting some switching components.

IMG_5272

In the previous project, I was interested in learning KiCAD and the process of ordering custom PCBs for a device for potential low-volume production. Many lessons were learned, most of which discouraged me from pursuing the thought further. This time around there is no fantasy of volume production, this will be an one-off project for a single salvaged VFD.

But now that I know the concept of a display matrix is generically applicable across multiple units, this time around I’m more inclined to keep the PIC side very simple and move more display-specific logic into driving logic which usually runs on a more programmer-friendly device like an Arduino or Raspberry Pi. (Or maybe even a ESP32!) So this time around I’m not going to decode ASCII characters or anything along those lines: I’m going to create a PIC driver that listens for commands over I2C specifically about cycling through and toggling pins. The idea is to avoid unnecessary PIC code churn that uselessly reinvent the wheel from one LED display to another, instead moving that to the Arduino/Pi/ESP32/etc side.

IMG_5238

Learning How To Use Pololu Stepper Driver Modules

My first experience with stepper motors is with this very inexpensive Amazon offering. I’ve since learned that these stepper motors are termed “unipolar” which incurs some trade-offs. From the price tag I knew they were cheap, and from the description I knew they were easy to control from a simple program. What I did not know about is the fairly significant headwinds if one wishes to get beyond the basics.

The simple driver module that goes with these simple motors only works for straightforward on/off control. When I tried to modulate the power to be somewhere between on and off, mysterious electromagnetic stuff started happening causing erratic motor behavior. At the time I decided to postpone solving the issue and to look into it later. Well, now is later and I’m going to solve my problem by ignoring unipolar motors entirely. Because it’s more productive to look at the bipolar stepper motors used by pretty much every halfway decent piece of hardware.

The motors themselves are more expensive, and the drivers are as well. Fortunately economies of scale meant “more expensive” is still only a few dollars. Pololu sells a line of stepper motor driver modules that are popular with the 3D printing crowd. (Or at least that’s where I learned of them.) The module’s physical form factor and pinout has become something of a de-facto industry standard. And a bipolar stepper motor for experimentation is equally easy to obtain as pretty much any stepper motor salvaged from consumer electronics will be a bipolar motor. For the purposes of my experiment, this motor came from a dead inkjet printer’s paper-feed mechanism.

Hooking up the electronics is a fairly straightforward exercise in reading data sheet and following instructions. The only thing I neglected was a capacitor across the motor input pins, something pointed out to me when I brought this experimental rig to a local maker meet. Fortunately I had been playing with a small enough motor that the absence of said capacitor didn’t fry everything.

All I needed to do was generate two data signals: direction and step. This is apparently a fairly common interface, even industrial-type stepper motor controllers accept similar inputs, so a Pololu is a great way to start. I created a small program to run on an 8-bit PIC microcontroller to generate these pulses, and the motor is off and running. It was super easy to get started, and this setup is enough for me to play around and build some basic understanding of stepper motor behavior. How they trade torque for speed, and how they respond to higher voltage/amperage. It’s a good foundation for designing future robotics projects.

Pololu ExperimentComponents on the breadboard, from left to right:

  1. Breadboard Power Supply
  2. Pololu A4983 Stepper Driver
  3. PIC16F18345 with program to generate step/direction based on potentiometer value.
  4. LEDs hooked up in parallel with step and direction signals.
  5. Potentiometer

Microchip’s New XC8 Compiler Appears Incompatible With MCC Boilerplate

For the purposes of experimenting with a Pololu stepper motor driver, I wanted to generate pulses from a PIC running a simple program. This meant downloading and installing the latest tools from Microchip for 8-bit PIC development: The MPLAB X IDE, the XC8 compiler, and the MPLAB Code Configurator (MCC).

With these tools set up, I pulled down my previous PIC stepper motor project intending to use it as a starting point. The stepper driver portion will be different, but I wanted the analog dial capability to adjust speed and direction. Before I start modifying code, though, I hit “Build” to make sure everything still compiled.

It did not.

In file included from mcc_generated_files/mcc.c:74:
In file included from mcc_generated_files/mcc.h:52:
mcc_generated_files/interrupt_manager.h:110:6: error: variable has incomplete type 'void'
void interrupt INTERRUPT_InterruptManager(void);
^
mcc_generated_files/interrupt_manager.h:110:15: error: expected ';' after top level declarator
void interrupt INTERRUPT_InterruptManager(void);
^
;
2 errors generated.
(908) exit status = 1

Since “void” is a very fundamental type for C programs, this error tells me this isn’t the matter of a minor typo, something is wrong at a very basic level. As a test, I created a new MPLAB project with a bare skeleton generated by MCC. This “Hello World” program failed to compile in the same way, indicating the problem is a system configuration issue.

A little digging around found the issue was introduced with XC8 compiler version 2.0, introduced just a few months ago in May. It moves C language support up to C99, keeping up with industry standards. However, this change also broke compatibility with old code. Not just old code sitting on a hobbyist’s Github page, but also old boilerplate code generated by MCC.

I expect that Microchip will eventually update these templates in a future MCC update, but for now, PIC programmers that use MCC for rapid prototyping will need to change their project settings to fall back to the older C90 standards. See xc8 2.0 migration document here for more details on this workaround.

Project Properties

Microchip “Curiosity” Development Board and its Zero Ohm Resistors

When I purchased my batch of PIC16F18345 chips, Microchip offered 20% discount off standard price for its corresponding Curiosity development board (DM164137). I thought it might be interesting and added it to my order, but I hadn’t pulled it out of its packaging until today.

Today’s motivation is the mTouch button built onto the board. As part of my investigation into projects I might tackle with the Hackaday Superconference 2017 camera badge, I found that the capacitive touch capabilities of the MCU is unused and thought it might be interesting to tie it into the rest of the camera badge. Before I try to fabricate my own touch sensors, I thought it’d be a good idea to orient myself with an existing mTouch implementation. Enter the Curiosity board.

Looking over the board itself and the schematics on the user’s guide, I noticed a generous scattering of zero ohm surface-mount resistors. If I had seen zero ohm resistors in isolation, I would have been completely mystified. Many electronics beginner like myself see a zero ohm resistors as something that does nothing, take up space, and there’s no point. For those beginners, a web search would have led them to this StackExchange thread, possibly the Wikipedia article, or maybe the Hackaday post.

Curiosity Zero OhmsBut I was not introduced to them in isolation – I saw them on the Curiosity board and in this context their purpose was immediately obvious: a link between pins on the PIC socket and the peripheral options built on that board. If I wanted to change which pins connected to which peripherals, I would not have to cut traces on the circuit board, I just had to un-solder the zero ohm resistor. Then I can change the connection on the board by soldering to the empty through-holes placed on the PCB for that purpose.

This was an illuminating “Oh that makes sense!” introduction to zero ohm resistors.

Reading the PIC32MX1XX Datasheet As A PIC16F18345 User

A review of the Hackaday Superconference 2017 “camera badge” hardware provided adequate orientation but no lightning strike of project inspiration. Today I did find the project page for last year’s Supercon badge as well as a summary page of some things people have created with the 2016 badge. People have done some really cool things with that badge serving as foundation. I’m feeling intimidated but also determined to keep trying to see what I can devise.

Today’s tactic: Dive into the data sheet for the Microchip control unit at the heart of the 2017 badge, the PIC32MX170F256D. No matter what else happens, it would be good to have an overview of what the chip can and can’t do. I was also hoping that a review of the data sheet will unveil something about the chip that would inspire a project. Since I’ve already read the PIC16F18345 data sheet back-to-back, I hoped the familiarity with Microchip conventions will give me a head start.

The first surprise was the size (length) of the data sheet. Only 344 pages when the much simpler PIC16F18345 chip had a 491 page document. It didn’t take long for me to figure out why, since every feature section started the same way: a disclaimer that the data sheet was only the summary and tells me I need to do more reading if I want the details.

OnlyASummary

Well, that explains the size! For my purposes today, it’s no big deal. In fact it is helpful since the summaries mean I don’t have to press “Page Down” as often.

There are some comfortable commonality with the PIC16F18345 I’m familiar with: Timers and comparators. Digital I/O and analog input (ADC.) Communication via SPI, I2C, UART. And all these peripheral modules are mapped into a memory space so everything is accessed via memory reads and writes. And finally: a big focus on power management.

There are some differences that I might miss in the PIC32MX1XX:

  • PWM seems to have gone missing, unless there is a much more advanced component that can serve similar purposes but I don’t recognize it as such.
  • I/O pins are much less powerful. The PIC16F can handle up to 50mA on any single I/O pin and up to 250mA total. The PIC32MX can only handle 15mA per pin with 200mA total.
  • Narrower voltage range: Unlike the super flexible and relaxed PIC16F that is happy to run with anything from 2.3V to 5.5V, the PIC32MX prefers to stay within 2.3V to 3.6V. The maximum is listed as 4.0V, so it might be dicey to run this thing on a single rechargeable lithium cell – the nominal voltage is 3.7V but a fully charged cell might be up to 4.2V.

The PIC32MX uses a different instruction set (MIPS32 M4K) and that’s no surprise. I expect to be mostly isolated from this fact by writing in C and letting the XC compiler worry about the instruction set. The PIC32MX also requires more support circuitry. Whereas the PIC16F can literally connect directly to a battery and it’ll start running. Again I’m mostly isolated in this case because the camera badge is already built for me and all the support components are already on board.

And now, on to the things that might be interesting. I started with the title description: “32-bit Microcontrollers (up to 256 KB Flash and 64 KB SRAM) with Audio and Graphics Interfaces, USB, and Advanced Analog

The first thing to catch my eye: USB, backed by this promising-sounding bullet point on the cover page: “USB 2.0-compliant Full-speed OTG controller“. USB OTG would let us plug-in USB peripherals and greatly expand the possibilities of what we can do. Alas, my hopes were dashed when page 2 clarified that USB OTG is only on the PIC32MX2XX series and absent on the PIC32MX1XX we have on the camera badge. So that’s out.

The “Advanced Analog Features” bullet items seem to mostly center around support for capacitive touch sensing, mostly around their “mTouch” design. Since their reference implementation involves copper traces and plates on a printed circuit board, that won’t be directly applicable to me. But perhaps this type of support circuitry can be hacked into something fun.

I have yet to explore the world of audio electronics, so sadly the audio interface features are mostly gibberish to me. I had higher hopes for the “Graphics Interfaces” side of that claim and… I came up empty-handed. There’s nothing that obviously said “graphics” to me on the feature set. The closest thing I can find is the PMP (Parallel Master Port) peripheral which is good for talking to display panels, and is indeed already employed on the camera badge to drive the 128×128 OLED screen.

So in the category of “stuff that the chip can do, but isn’t already being used” the best candidate at the moment is the analog circuitry to support capacitive touch. Since I don’t have time for a OSH Park PCB, it’ll have to be something creative. Perhaps something as primitive as taping down loops of wire to cardboard or 3D-printed plastic parts.

The gears in the brain keep churning…

 

Supercon 2017 Badge – Hardware Orientation

Today was spent getting orientated on the hardware components making up the camera badge for Supercon 2017. The starting point is the project documentation’s “hardware description” page, which gave a basic overview that helps me decide where I want to dig deeper.

2413581507673490011

The CMOS sensor at the heart of the OV9650 camera module claims to support up to 1280×1024 resolution, which isn’t bad for such an inexpensive component. The sample image posted on the project file section, however, is only 128×96 resolution. It’s not immediately clear where >99% of the pixels disappeared to or how feasible it’d be to bring them back.

Perhaps that resolution was chosen to match the OLED screen, which has 128×128 pixels of resolution controlled by a SSD1351 chip. If this is the case, and more pixels can be captured from the camera with minimal effort, that opens up project ideas such as having the little screen pan across a larger image. (a.k.a. the Ken Burns effect.)

We have multiple tiers of storage that makes different capacity/speed trade-offs. First we have some space for data on the PIC itself, then we have a Microchip 23LC1024 serial RAM, and finally a microSD card.

There’s an LIS2HH12 accelerometer on board which might enable some cool projects, though I’m struggling to think up one that captures my fancy. Maybe in a bit.

The chip that orchestrates all of this is a PIC32MX170F256D. Fortunately for me, I already had the tools on hand to develop for it thanks to my time playing with the PIC16F18345. They’re very different chips, but since they’re both from Microchip I would write code to both using the same MPLAB X IDE albeit with different C compiler underneath: XC8 vs XC32. The PIC32 is set up to run a .hex file off the microSD card, so it’s not necessary to have a PIC programmer. But if I need to flash at a more direct level, the board has headers to connect the same PICkit 3 programmer I use for the PIC16F18345.

All in all, a decent set of hardware. Now I just need to think of a really cool project to do with it all.

Supercon Badge – Initial Exploration

Supercon 2017 is coming up soon and I now have a ticket to attend. Part of the fun is the badge which, unlike SIGGRAPH or WestTec, is not a printed piece of paper. In the case of Supercon (and a few similar conferences) it is actually a circuit board with some functionality. The Supercon 2017 badge is a very minimal low resolution digital camera. Why would we want such a thing when most of us carry cell phones with far superior cameras? Because it is only the start: conference attendees are invited (expected?) to use it as a starting point and build something cool.

Which means I have only about 10 days to do my homework – what would I build with the badge? As a first-time attendee I’m not sure what to expect. Last year I saw brief glimpses of the badge under construction, but I didn’t see any of the projects built by conference attendees.

Well, with any project, the first step is to look for documentation. The official source of information is, naturally, the camera badge’s own project page on Hackaday.io. I felt intimidated on first look: my own adventures in electronics hardware hasn’t covered anything to do with cameras, OLED panels, or the like. About the only thing I am vaguely familiar with is the microcontroller at the heart of the device. It is a Microchip PIC, though from their PIC32 series which is higher-end and more capable than the PIC16F chips I had been playing with.

Fortunately, it uses the same MPLAB X IDE for development. I had to download and install the XC32 compiler corresponding to the PIC32 chip, but that was relatively easy. After changing the path separators from the author’s Windows machine (‘\’) to the Ubuntu I’m working on (‘/’) the project builds successfully.

That’s a good start. The next step is to go digging through the code base and look for something interesting for me to do.

cambadgebuild

 

A 3D-Printed Enclosure to Take My LED Project On The Go

For the Connect Week event put on by Innovate Pasadena, the Hackaday LA group is hosting the “Bring-A-Hack” event where attendees are encouraged to bring projects (in any stage of completion) for show and discussion. Since I’ve been building my LTC-4627JR driver board as a learning project, I wanted to bring it in for show-and-tell.

Now I could just bring the assembled circuit board and pass it around as an inert object, but what fun would that be? I wanted to bring in something that shows it doing something, and provide some way for people to interact with the whole contraption. Looking at my parts on hand, it seemed easiest to rebuild my thermometer test project. I can have a simple Python program run on the Raspberry Pi, reading temperature from the Tux-Lab Si7021 breakout board, and sending it out to my display. That makes 3 circuit boards, plus they’ll need portable power. I will enlist my Amazon purchases: the 3-cell lithium ion battery pack protected by a S-8254A IC, and the MP1584 buck converter to translate the battery pack’s power into Raspberry Pi friendly voltage.

They present a logistics challenge. There are many parts and while it’s fine to just connect them with wires on my work table, it’s too unwieldy to carry on the Gold Line to Pasadena. I’m going to need some kind of enclosure to carry the whole thing.

To Fusion 360 we go! I just needed a simple enclosure so it was pretty fast to draw up. The bottom tray is for power: it holds the battery cells, their protection board, and the buck converter to 5 volt output. The upper tray holds the Raspberry Pi. The lid of the tray holds my custom LED circuit board, and a few clamps holds it all together. The clamps should be easily removable so I could disassemble the box to show people what’s inside.

ShowandTellBox

I had originally intended to mount the Si7021 breakout board as well, but ended up deciding it would be more fun to have it dangling out for people to play with it. Here are the layers without the clamps, so they can be taken apart and show off the insides.

IMG_5273

And here’s the “travel configuration”, with clamps holding the pieces together.

IMG_5274

This setup worked well. I was able to carry it in my backpack without worrying about tangling up or shorting out wires. Once I arrived, the project was fairly well received and lots of people had fun playing with the thermometer.

PIC Controller for LTC-4627JR LED Now Accepts Strings

Now that our circuit board from OSH Park is populated and running, it’s time to evolve the PIC code beyond displaying a test pattern. The objective of the exercise all along was to display data sent to the unit over I²C, but the exact details of what to send hasn’t been finalized.

Stage 1: Raw Bits

This was the easiest and so was the first thing we implemented. It is the lowest-level way to communicate between the host and the display. The host sends data in the form of raw bytes. Each bit in a byte correspond to the 8 segments in a single digit. The host sending 4 bytes will fill 4 digits. We send that byte directly out to PORT C on the PIC micro controller, which are connected to 8 segments of a LED digit.

This method is powerful in the sense it allows the host to display arbitrary patterns. But it is terribly unfriendly to use. The program running on the host has to tailored to the implementation details of our display: the host has to know which bit corresponds to which segment, and whether a bit value of 0 or 1 corresponds to light or dark. Which means if the user wants to swap out to a different display, they would have to rewrite the host code.

This system served its purpose to prove we could light the LED, but it is not a good way forward.

Stage 2: Hexadecimal Decode

In this system, the bytes sent by the host is decoded into their hexadecimal representation and displayed on screen. Since a hexadecimal digit represents 4 bits, the host sending 2 bytes (16 bits) will fill the 4 digits. This is actually a pretty useful mode in certain debugging operations where we do want to see those values. However, it is very difficult to represent human-friendly information this way. We’re also unable to make full use of the LTC-4627JR this way: there’s no way to represent the decimal point or the colon in the middle.

Since it is useful for machine-level (not human-readable) data debugging, we might want to retain this capability in the form of a special mode later. In the meantime, let’s move on.

Stage 3: Binary-Coded (Hexa)Decimal

The next evolution resembled binary-coded decimal system, which separated out each digit to its own byte. This makes the host program easier to write because each character can be treated individually instead of having to pack 2 characters into the upper/lower 4-bits of a byte. Unfortunately it also shares the limitation that we couldn’t represent the decimal point or the colon.


Which brings us to the latest approach:

Stage 4: String

Since most computer operations that result in human-readable information end up with the string data format, we’re going to try using that as our I²C protocol. It is established, well-understood, and a piece of cake to use from high-level programming languages like Python. The downside is that it is much more verbose. The character sequence to light up all the LED is 8.8.:8.'8. which requires 10 bytes to represent. This is a five-fold increase in bandwidth relative to the 2 byte hexadecimal decode. Will this added bandwidth cause problems? I don’t know yet, we’ll find out.

But for now, we have a very user-friendly interface. Sending the string “79.2F” resulted in the picture attached to this post. The easy interface also enabled a very short example program.

(The project discussed in this blog post is publicly available on Github)

IMG_5272

 

First OSH Park Order Arrived

My first KiCad project was sent to OSH Park almost two weeks ago, and my digital design is now back in my hands in physical form. It is really quite exciting to hold in my hands a circuit board I designed. Three copies of it, in fact, as per usual OSH Park practice.

The first order of business is to check for simple mistakes. I pulled out my multimeter to verify that I have good connection between all the VCC pins to the VCC plane, and similarly all the ground pins are connected to the ground plane. Then I brought up my design in KiCad and checked continuity for the pins I designated. I don’t know if I exhaustively checked them all, but a large portion were verified.

Once I’m satisfied my design has been faithfully produced by KiCad, it was time to pull out the soldering iron. I thought I’d do some incremental tests – solder a subset of components to verify the subset of LEDs light up correctly – but I was eager to see it all light up so I went ahead and populated the whole board. The legs of the 2N2222A transistors in their TO-92 package were closer together than I’m used to in my soldering projects, but other than that challenge it was all simple and straightforward soldering.

Populated LED board

And finally, the moment of truth. I was working in Tux-Lab and a bunch of nearby guys gathered around to see me power up the board for the first time.

<drum roll>

It’s alive! The test pattern already programmed into the PIC started cycling through the LED display. This success is a great confidence-builder. I had fully expected to find problems with the board that I would have to fix in KiCad and send back to OSH Park for another set of circuit boards to be produced. The only problem I encountered was the PICkit 3 does not fit nicely alongside the power connector. I could make it work by making them wedge together at an angle. Neither were happy with it but it should be relatively rare to have the programmer attached.

Well, I guess break time from PIC software is over – I no longer have an excuse to play with other projects. The task of writing my I²C driver routine for this display is back on the to-do list.

Placed First OSH Park Order

After several revisions – including several PCB layouts that were restarted from scratch – I’ve learned a lot about using KiCad.  I don’t know for sure it’s all going to work, but I feel confident enough to make the first revision of my board. If it comes back and the board doesn’t work, I’ll have new lessons to learn. Or if it does, I celebrate!

Off to OSH park!

They have a very KiCad-friendly pipeline that accepts the PCB data file directly, no file conversion or data export necessary. I was worried about file format compatibility since I am running the latest nightly build and OSH Park only officially supports the most recent stable build. Some people have reported issues, but in my case it seemed to have gone through successfully.

The OSH Park verification screen is a great confidence builder. They took my file and generated these images for me to look over. This is awesome! I can clearly tell that it is my design and it generally looks fine. The resolution is a little lower than I would have liked. It is starting to be difficult to make out individual traces on my board, it would obviously be impossible to do so on a large complex board. But I assume detailed checks are not the point, we just need to verify we haven’t uploaded the wrong board and that nothing’s fundamentally broken in OSH Park’s interpretation of it.

OSH Park Verify

Upon checkout I was surprised that two Teensy boards were available as add-ons to my purchase. I don’t know why the circuit board fabrication shop is selling their own edition of the Teensy board, but since I had been thinking about buying one to play with anyway, it was an easy impulse buy to add a Teensy LC to the basket.

And now I wait. The board should arrive in two weeks and I won’t know what I need to fix in KiCad until I get the board and put it to (in)action. This puts a hold on the PIC micro controller hardware side of the project, and I can turn my attention to something else for a while.

(The work described in this blog post are publicly available on Github.)