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.


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.


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.



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.


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.


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


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)



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.)

A Beginner Learns PCB Routing is Hard

Drawing up the circuit diagram/schematic was a new thing, but I got through it with minimal headaches and was feeling pretty good about using KiCad. After I was done with the first draft, I moved on to route all the connections to be placed on the printed circuit board (PCB). Doing this, I get firsthand experience that wire routing is a hard problem.

The first few connections were easy, but then it got progressively more difficult as I struggled to find a route for the later connections. The center of the board inevitably became a traffic jam and I started having to go around the jam. Every track that go around the outside perimeter of the PCB is a surrender that I couldn’t find a better way.

In addition to the traces going around the outside perimeter, another way to quantify my frustration with my circuit is the number of tracks in the KiCad PCB file. This is a number easily readable in the text format save file.

Fortunately, it doesn’t cost anything to learn by doing, redoing, and repeat.

The first attempt was a hopeless mess and I had to abort before I could connect everything. Here is version 2, where everything is actually connected with almost 200 tracks and multiple traces that go around the perimeter in a last-ditch effort.

LTC-4627JR I2C PCB v2

Version 3 changed the layout of the components in an attempt to make routing simpler. Moved the LEDs to the top, etc. It felt cleaner but is still quite a mess. I managed to avoid long traces that went around the left and right perimeters, but I still needed several at the bottom perimeter. And the track count didn’t improve by much – still just under 200.

PCB Route v3

Version 4 had the same basic layout as version 3 but I’ve learned to recognize a few signs of upcoming problems and could work to avoid them. The result had a further reduction in tracks, almost a 10% cut down to under 180. Plus I needed even fewer perimeter rescue paths.


The English language has the colloquialism “Paint yourself into a corner” and this is a very similar thing – it’s very easy to route yourself into a situation with no way out. I wish I could condense the lessons I learned into a summary here, but so far it’s just a lot of trial-and-error. Try something until I run into an obstacle, then try to figure out how to get out of this mess.

At this point the only words of wisdom I could offer is – dive in and try. It won’t work, but you’ll learn. Try and try again until you get good enough to get to a point where everything is connected, however inelegant it might be, and keep iterating to improve from there.

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

KiCad Circuit Diagram Schematic Editor (Eeschema) Amateur Hour

The KiCad Getting Started guide only covers the basics, but it’s enough to let the user embark on exploratory adventures to learn the rest of the tool piece by piece. I know I don’t have the knowledge and experience to do a good job at circuit design, but I’m a believer that such knowledge and experience is built up by learning from mistakes. So: let’s dive right in and try to implement the circuit board for my LTC-4627JR driver project and see what we learn.

The circuit diagram portion was relatively straightforward. Most of the lessons in the Getting Started guide applies, up to and including how to build a custom component for my schematic because the LTC-4627JR was not in the KiCad standard library. Somebody had built a library of components that included the LTC-4627JR, and made it available on Github. But this is a learning exercise and I wanted to learn how to do it myself.

The PIC16F18345 was not actually in the KiCad library, but a sibling part PIC16F18344 was available with a 20-pin DIP footprint, which is what I want right now. However, the eventual goal is to go to the surface mount version of the part and I hope I’ll be able to find another substitute with the same 20-pin SMD footprint.

There was no specific KiCad part for the 2N2222 transistor, but there are generic NPN transistors and I think that’s good enough. I was puzzled by the large number of options until I figured out they were different combination of a transistor’s pins. The three pins were labelled in order of pin number. So the variant tagged “BEC” has the base on pin 1, emitter on pin 2, and collector on pin 3. The “BCE” variant has the latter two pin swapped, etc. Looking at my 2N2222, I decided to use the EBC variant because that’s the order I see in the Wikipedia article.

The resistors were straightforward, as were the two I/O headers on the board. A four-pin connector for power, ground, and the 2 I²C wires. The five-pin connector is for the PICkit 3 to perform in-circuit programming.

From looking over schematics in the past, I got the distinct feeling of a stylistic convention for laying things out. Much like there are conventions for software source code. But a gut feel is not enough – I needed help from somebody to concretely spell out the rules. A web search for “circuit diagram conventions” pointed me to this article on Electronics StackExchange.

Armed with the list of conventions and a few hours to bump my head in KiCad, I got a passable basic schematic.

LTC-4627 I2C schematic

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

LED Practice Exercise May Have Niche Market

I set out to program a PIC to implement an I²C-controlled 4-digit 7-segment LED display because I thought it would be a decently nontrivial practice project to help me learn. I had fully expected it to end up duplicating the functionality of a commercially available product that does it better for a fraction of the price.

Now that my project is in a decently functional state, I went looking for that commercial product to see what else I can try to imitate for the sake of practice. I was surprised that nothing immediately stood out as both “does it better” and “fraction of the price”.

The first item I found was sold by Adafruit. They have an I²C LED display “backpack” in various colors. Here’s the green version, as one example. The driver chip they used is the MAX7219, which I found curious because the data sheet for the chip does not mention I²C communication. Another curious item is that the complete kit – including populated circuit board and LED – has a list price of $9.95 but if I want to buy the MAX7219 by itself from Adafruit it costs the same $9.95. Digi-Key sells the chip for around the same price. I doubt Adafruit get their circuit board and LED for free, so there’s something else I’m missing.

But I couldn’t have used that chip anyway. The MAX7219 is for driving a display unit with common cathode, and LTC-4627JR is a common anode unit. Also, Maxim is telling people to migrate their designs to the MAX6950, which seems to be a surface-mount only chip with no DIP form factor available.

Looking over Sparkfun catalog I found a similar product, but theirs is controlled by an ATMega328 chip. In fact, it is a baby Arduino complete with the Arduino bootloader. This is closer to what I’ve built, but I think the PIC is a simpler and less expensive chip to perform the task which may mean a small niche below the Sparkfun unit.

All this hints at the possibility my project might actually find an audience as a product. If I were to go ahead with this, I would test the market by putting it up on Tindie. It’s a marketplace that seems to cater to the right audience and there doesn’t seem to be a direct competitor product at the moment.

Well, that was unexpected. I might as well keep going and see how far I can take this.


MPLAB Xpress vs. MPLAB X: Git Source Control

MPLab Xpress IDE LogoI loved the promise of MPLAB Xpress that someday I can do all my PIC development in the cloud. Even in today’s limited form, as long as I stay within certain boundaries I was able to work on PIC programming on a Raspberry Pi! But one downside of keeping the project sources up on Microchip’s servers is that they don’t currently offer any kind of source code version control. I understand why they might not prioritize it for the hobbyist crowd getting started in PIC programming, but version control is something I’ve grown used to having in my software development toolbox. And I occasionally miss being able to review and rewind certain things, even in the relatively simple beginner’s PIC projects that I’ve worked on to date.

MPLAB X logoSo after I inadvertently damaged my MPLAB Xpress Evaluation Board, I decided to graduate to using PIC chips directly without an evaluation board. This meant programming the chip using a PICkit 3 instead of the USB storage-based programmer on the evaluation board. And lastly – it also means leaving the web browser-based MPLAB Xpress and moving over to the NetBeans-based MPLAB X IDE installed and executed locally. One result is that the project files are now on my computer, which means I can bring git into the picture!

Obviously git can handle the C source files that I will be working with. What’s less obvious are the other data files in a MPLAB X project. What is worth tracking in version control, and what are easily regenerated as needed? Such information are usually described in a .gitignore file, but Github’s .gitignore collection does not include one for working in MPLAB X.

Fortunately, the MPLAB community has assembled one and it looks OK to me at first glance. I first dipped my toes using a project that was already complete, pushing it up to Github for archiving the sources. It also allowed me to test that all critical information is preserved, by deleting the directory and “git clone” anew to verify MPLAB X is happy with everything and didn’t complain about files missing from the project.

The second trial run incorporated git from the start, tracking changes along the way so I could see what was boilerplate generated by the tools and separate them from the (quite trivial) code I actually wrote. This test is also successful.

And now, trial run number three: take all the 7-segment LED control code I’ve been working on in MPLAB Xpress and translating them into a MPLAB X project in a way that tracks all the individual tasks along the way.

Lite-On LTC-4627JR + I²C = Using All 20-Pin On PIC16F18345

My shipment of my own PICkit 3 and tube of PIC16F18345 has arrived, so it’s time to pick up where I left off with I²C control of the Lite-On LED module.

This LTC-4627JR module has a few extra enhancements over the standard 4-digit 7-segment display. The first is the addition of a period with each digit, so we can display decimal points in our numbers. The period is an additional segment to make it an 8-segment display.

In addition to the periods on each digit, there are three additional LEDs. Two are in the middle of the display making it possible to use this in a clock, as they’re positioned to show the colon in the ubiquitous blinking “12:00”. The third and final additional LED is towards the upper-right of the display. It’s not immediately clear what that would be good for, but since its siblings are clock-friendly, perhaps it can indicate AM/PM with the help of bezel markings. Electrically, these three LEDs are wired in parallel with 3 of the 8 segments of the other digits and enabled with a common anode in parallel with the 4 digits. Together the three additional LEDs are effectively a partial fifth digit on the display.

Effectively, I’m now trying to control a 5-digit, 8-segment display. A few days ago I tried to control it with a PIC16F1847, but that is an 18-pin chip so I didn’t have enough pins to drive the eighth segment  or the fifth digit. Now that I have my 20-pin chip, I can wire up  my breadboard with:

  • 2 pins for power, +5V and Ground.
  • 8 pins for the cathodes of the 8 segments, via 120 Ohm resistor to keep the current below 25 mA.
  • 5 pins for the common anodes of the 5 digits, via 2N2222 transistor to control the (up to) 200mA current.
  • 2 pins for I²C communication, one data and one clock.
  • 3 pins for the PICkit 3 to program the chip, Vpp, ICSPCLK and ICSPDAT.

Using all 20 pins with nothing wasted.

I know that the Vpp, ICSPCLK and ICSPDAT pins can serve double-duty under restricted circumstances, but I don’t yet have a good grasp on when it’s OK to do that. For now I’m  going to leave them alone for exclusive use of the programmer until I have a better grasp.

On a final note: even though I’m driving one more transistor and one more digit than before, the board still ended up cleaner and less tangled with wires. Practice makes perfect I guess.

To establish a baseline of functionality, I hooked it up to a Raspberry Pi to confirm I could talk to the Microchip boilerplate generated I²C code. And I wrote a small program to confirm I could light up all the LEDs. It looks good, we can proceed.


PIC Exercise: Volt Meter

One aspect of PIC micro controllers that I found to be a novelty is their ability to work across a wide range of supply voltages. For my PIC16F18345, the data sheet said it can run anywhere from 2.3V to 5.5V and can (briefly) tolerate up to 6.5V. I looked for configuration information to set it to “3.3V mode” or “5V mode” or something along those lines, but there was no configuration to worry about. The PIC does not care: give it anything in that range and it will go.

In contrast, the Raspberry Pi requires a steady 5V supply voltage. So does an Arduino though most Arduino boards also incorporate a voltage regulator to take a 7-12V power supply and regulate it down to 5V.

I wanted to play with PIC’s power flexibility and I had the hardware ready to go: my PIC16F18345 evaluation board. I damaged the MSSP peripheral in my I²C experiments and retired it from my I²C project, but the rest of the chip seems OK. It is still perfectly capable of displaying numbers, just not with I²C data.

So here’s today’s exercise: the PIC will measure and display its own varying supply voltage. This project is made possible by a few core-independent peripherals (CIP) built-in to the chip. The input voltage will be compared against a reference voltage created by the fixed voltage reference (FVR) peripheral, and the analog-to-digital converter (ADC) peripheral will be configured to report how FVR voltage relates to the input voltage.

For my project, FVR is configured to 2.048 volts and ADC is configured to determine the FVR position in the range between ground and the input voltage level. The result is expressed as a 10-bit number in the range of 0 to 1023. A few examples:

  • For 5V input, ADC will report 2.048V is 41% of input, represented by roughly 419.
  • For 4.096 V input, ADC will report 2.048 is halfway, represented by 512.
  • For 3.3 V input, ADC will report 62% or about 635.
  • For 2.048 V input, ADC would in theory report maximum of 1023. In practice it would not happen because the minimum voltage is 2.3V and we would trigger a brown-out reset before dropping to 2.048V.

Inside the ADC peripheral, the conversion process takes a little time. Plus the calculation to convert the ADC output to the voltage, then converting that into which LEDs need illumination to convey the voltage to the user, takes a little more time. The process is very fast by human standards, but it paused the LED refresh loop for long enough to cause a visible blink.

Solving this undesirable blink was the extra credit part of the exercise: move the LED refresh code into a timer-driven interrupt service routine, so it can run at guarantee regular intervals. Even if it means briefly interrupting the analog-to-digital conversion process.

Completing the exercise resulted in a PIC that measure and displays its own input voltage on the 7-segment LED. Unlike my earlier project with the 18-pin PIC16F1847, this 20-pin PIC16F18345 has one pin available to illuminate the decimal point. Here it is, running off a fully charged Lithium-Ion battery cell and indicating 4.005V. My multi-meter says 4.041V, so the PIC agrees to within 1-2%. Good enough.


Note: When using the MPLab Xpress PIC16F18345 Evaluation Board (Microchip part number DM164141) shown in this picture, the FVR+ADC calculation is unreliable when connected & powered via the computer’s USB port. This project didn’t work correctly until unplugged from the computer.

Symptom of the failure: ADC result is always the maximum value of 1023, which indicates the input voltage is 2.048 when it is not. This behavior wasted a lot of debugging time which made me less happy with the product.

Si7021 Sensor to Raspberry Pi to PIC to LED

I started this I²C project by creating a simple I²C-controlled LED display using a PIC micro controller. Then I found an I²C Python Raspberry Pi library to communicate with my PIC. The next addition to the mix should be an I²C device I did not create, to verify my code plays well with others.

While talking about I²C at Tux-Lab, one of the past projects came up: a breakout board for the Si7021 temperature and humidity sensor. A unit was brought out for show during this conversation. This particular unit was built a few years ago and has yet to be incorporated into a project.

A web search confirmed this is quite a popular sensor. Lots of sample code and projects. Both Adafruit and Sparkfun sell breakout boards similar to the one Tux-Lab created. And the sensor is also part of the popular Sense HAT. I looked at the data sheet and thought it looked like a good place to start. Best of all, a search for existing code found one in the “Examples” section of the Pi GPIO library I wanted to learn anyway.

I asked to borrow that unused breakout board and added it to my bread board. (Visible in the lower-left of the attached picture.) The additional wiring was trivial, most of the work was on the software side learning Python basics. It didn’t take terribly long to create a rudimentary thermometer. My Python code running on the Pi uses I²C to query the Si7021 for temperature, converted that data for display, and sent that data out the same I²C bus to the PIC.

With the work and learning I’ve put in, I now have an overly complicated contraption that tells me my work space temperature is 75.18 degrees Fahrenheit.

No decimal point on the LED because I ran out of pins on the 18-pin PIC16F1847 chip.


PIC I²C Project Continues with Different Chip (PIC16F1847 for PIC16F18345)

My PIC16F18345 has stopped working properly as an I²C device. It could send data (I could read from it) but it could not receive (I could not write to it.) Debugging this behavior, I got as far as determining a flag on a status register is not being set correctly by the MSSP module. This is beyond my means to repair or work around in software. In the last post I described an ugly hack of a I²C protocol to let me get a little bit of work done, but what I really need is a new chip. I placed an order from Microchip Direct and the replacements are on their way.

In the meantime, I borrowed a PICkit 3 programmer and a tube of chips from Tux-Lab to see if I can continue working until my order arrived. The chip is PIC16F1847, an older design with fewer features but in the same general family as the PIC16F18345 I’ve been learning. I could not load the exact same compiled code onto the chip, but the C code I wrote was fairly painless to migrate. The steps were:

  1. Created a new PIC16F1847 project in MPLAB X.
  2. Configured the chip for I²C communication in MCC.
  3. Click “Generate” to create all the boilerplate code.
  4. Copy the C code I wrote (not the generated boilerplate) from the PIC16F18345 project to the PIC16F1847 project.

That compiled successfully right away, freeing me to make other changes. The pin layout of the PIC16F1847 pin is nothing like that for my existing board, so I had to set it up on a new breadboard. Since I’m rewiring anyway, I incorporated a different, brighter 7-segment LED display unit. This unit uses common anode pins to select the active digit each of which demand more current than a PIC can source. So I also incorporated some 2N2222 transistors to let the PIC control sourcing that current from the positive power rail instead of supplying that power itself.

The remaining key difference is that the PIC16F1847 is an 18-pin chip, where the PIC16F18345 is a 20-pin chip. Before, I had an extra pin unused, but now I’m one pin short for my project. I decided to temporarily sacrifice the decimal point until my 20-pin chip shipment arrives.

This is good enough to get me back up and running. Here’s the setup displaying “1847”



Ups and Downs Implementing I²C on PIC

The original intent of the I²C bus is clearly stated in its name: Inter-Integrated Circuit. It is meant for communication between chips living near each other on the same circuit board. It isn’t designed to be used communicating across wires bridging multiple breadboards on a hobbyist project. So the simplicity of its design is partially related to the fact there’s very little idiot-proofing built-in.

Which is a long-winded way of saying… I broke something. After wiring up the 7-segment LED, I started writing I²C code to control what gets displayed. I was puzzled by the fact my project became gradually less functional over the course of a few hours. I assumed I did something bone-headed in my code but troubleshooting eventually eliminated my code as an issue.

There was a fault in my hardware – the common ground wire I used to connect between the Raspberry Pi and the PIC was only providing an intermittent connection. After repairing the bad solder job, I was surprised to find it did not restore functionality. It’s not clear how the I²C circuit worked while the ground wire was unreliable – the system must have found some other path for ground and something along that line caused damage. Or maybe the intermittent connection was causing current surges through the system as it connected and disconnected at unpredictable times.

The bottom line is that my PIC could still send bytes over I²C but it could no longer receive. When running the boilerplate EEPROM code, this meant my Pi could read from the faux EEPROM on the PIC but any write operation would fail. I guess it’s time for me to get a replacement PIC16F18345.

In the meantime, I wanted to keep working on the 7-segment project. But how could I tell the LED what to display if I can’t send data? This constraint led to an extremely unorthodox I²C communication protocol: I tell the LED what to display by reading the faux EEPROM. The number of bytes retrieved in each read operation is then displayed on  a digit of the LED.

So for the attached picture showing 0x16F1, I performed four reads from the EEPROM: Read 1 byte, stop. Read 6 bytes, stop. Read 15 bytes, stop. Read 1 byte, done. This super ugly hack will unblock my project while I wait for Digi-Key to deliver a replacement PIC, but yuck! This is no way to design an I²C protocol!

The project display dimly showing “16F1”

Wiring up a PIC to control a 4-digit 7-segment LED (Lite-On LTC-5723HR)

Now that I have my PIC micro controller successfully communicating via serial port and via I2C, it’s time to make it do something a little more interesting and practical than just lighting up a single LED. Which means… more LEDs! I could do a RGB triplet and try my hand at colors, or a string of lights, but there’s an existing open project at Tux-Lab that would need to drive some 7-segment LEDs. I borrowed the LED module from that project and got to work.

I could see that the module had 12 pins, but it wasn’t obvious to me how 12 pins would control the display (4 digits * 7 segments+period = 32 individual LEDs.) Fortunately this part was purchased from Digi-Key and still in its shipping bag with the part number, which made it trivial to find the product page and download the data sheet.

Reading the schematic on the data sheet revealed that 8 of those pins are anode (+) connected in parallel across all 4 digits, each of them corresponding to a location on a digit. (7 segments plus a period.) The remaining four pins are cathode (-) for each of the four digits, connected to all 8 segments of the corresponding digit.

It’s immediately obvious we can only have one digit active at any given time, since different digits would probably display different numbers and would need different anode pins active.

Less obvious is the fact we can’t have all the segments on that digit active at the same time, either. The cathode is common across all 7+1 segments of a digit. If all 8 segments light up, that poor cathode pin will have 8*20 = 160mA crashing through all at once. This greatly exceeds the 50mA per-pin current handling limit.

I could probably solve this problem by using the PIC to control transistors that can handle that 160mA, but I don’t have any on hand. So to start with, I’ll cycle through all the segments lighting up only one at a time so there’s only 20mA flowing through the cathode pin. This will result in a display only 1/8th as bright as it could be, but if that’s already bright enough, I won’t have to hassle with transistors.

After wiring work was complete on the breadboard, I wrote a simple PIC program to cycle through all 32 LEDs. The first revision had the cycle running slowly enough for me to follow as it went from one segment to the next. This allowed me to visually verify all the wiring is correct. Then I let the cycle run at full speed to see the brightness level.

It is fairly dim, so I will have to add those transistors later. For now it is visible enough for me to proceed.