Bad things happen when programmer finds a soldering iron

Cananka, the Raspberry Pi HAT: EEPROM

[This post is part six in the series.]

What makes HAT a HAT is its EEPROM. While official instructions are lacking in details there are some forum posts and tutorials dealing with that issue.

In order to follow steps later in this post, we first have to install some packages:

sudo apt-get install git i2c-tools

For HAT EEPROM access we have to tell system to allow use of, usually inaccessible, I2C bus 0:

sudo bash -c 'echo "dtparam=i2c_vc=on" >> /boot/config.txt'
sudo reboot

Easiest way to see if we have set it up correctly is to probe I2C bus 0 for EEPROM at address 0x50 and see what we have there. We are searching device with ID of 0x50:

i2cdetect 0
i2cdump 0 0x50

To manipulate it any further we need to install EEPROM utilities from the Rasbperry repository:

git clone https://github.com/raspberrypi/hats.git
cd hats/eepromutils/
make clean
make

Before anything else is done, it is a good idea to clean out EEPROM:

dd if=/dev/zero ibs=1k count=4 of=blank.eep
sudo ./eepflash.sh -w -f=blank.eep -t=24c32

Now we are finally ready to actually create .eep file from our text config and upload it to EEPROM:

./eepmake eeprom_settings.txt hat.eep
sudo ./eepflash.sh -w -f=hat.eep -t=24c32
sudo reboot

If everything is ok, you should have directory /proc/device-tree/hat with product, vendor, and other files:

more /proc/device-tree/hat/product

But this is not where we want to stop - we want also device tree so that our CAN bus can get some auto-configuration magic. And frankly that whole concept is such a mess that creating it from scratch takes unholy amount of time. However, since CAN over SPI is one of the already existing overlays, we don’t have to do anything other than include it and flash our EEPROM again:

./eepmake eeprom_settings.txt hat.eep /boot/overlays/mcp2515-can0.dtbo
sudo ./eepflash.sh -w -f=blank.eep -t=24c32
sudo ./eepflash.sh -w -f=hat.eep -t=24c32
sudo reboot

Even if our CAN bus implementation didn’t match existing overlay completely (e.g. using different frequency), we could still use it as a template for our modifications. We would first dump it:

dtc -I dtb -O dts /boot/overlays/mcp2515-can0.dtbo > hat.dts

Once we have it in (semi) human readable format, we can change what is needed (e.g. clock-frequency) and then use the same flash procedure as before:

./eepmake eeprom_settings.txt hat.eep hat.dts
sudo ./eepflash.sh -w -f=blank.eep -t=24c32
sudo ./eepflash.sh -w -f=hat.eep -t=24c32
sudo reboot

Now you can remove all modifications done to /boot/config.txt and our interface will still appear:

ip -d link show can0
 3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
     link/can  promiscuity 0
 ...

With that, we have Cananka project completed and the only post remaining is to reminiscence over development problems.

Cananka, the Raspberry Pi HAT: Software

[This post is part five in the series.]

One of the requirements I’ve stated was that we should use as much of Linux driver defaults as possible. In this step we should reap benefits of that as all needed to enable CAN should be:

sudo bash -c 'echo "dtoverlay=mcp2515-can0,oscillator=16000000,spimaxfrequency=10000000,interrupt=25" >> /boot/config.txt'
sudo reboot

After reboot, we should see device loaded:

ip -d link show can0
 3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
     link/can  promiscuity 0
     can state STOPPED restart-ms 0
           mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
           clock 8000000

When I was setting this for the first time I was brought on a wild goose chase as nothing really worked. No matter what I did, can0 device would not appear (Cannot find device "can0"). It took me a while to notice something is off:

dmesg | egrep "spi|can"
 spi_bcm2835: disagrees about version of symbol module_layout

As this Raspberry was used for other projects and I’ve updated it multiple times it seems at one point something went wrong with drivers. A fresh reinstall of Raspbian sorted that out.

More careful among you will notice that CAN interface is actually down upon boot. This is easy to correct and the only piece of data we need is the bus speed (this example will use 125 kHz):

sudo ip link set can0 up type can bitrate 125000

ip -d link show can0
 3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
     link/can  promiscuity 0
     can state ACTIVE restart-ms 0
           bitrate 125000 sample-point 0.875
           tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
           mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
           clock 8000000

Unfortunately this doesn’t survive the reboot. To make it stick just execute:

sudo bash -c 'echo >> /etc/network/interfaces'
sudo bash -c 'echo "auto can0" >> /etc/network/interfaces'
sudo bash -c 'echo "iface can0 inet manual" >> /etc/network/interfaces'
sudo bash -c 'echo "    pre-up ip link set \$IFACE type can bitrate 125000" >> /etc/network/interfaces'
sudo bash -c 'echo "    up /sbin/ifconfig \$IFACE up" >> /etc/network/interfaces'
sudo bash -c 'echo "    down /sbin/ifconfig \$IFACE down" >> /etc/network/interfaces'

For testing install can-utils:

sudo apt-get install can-utils

With them you can use cansend and candump, e.g.:

cansend can0 02A#FEED
candump can0

At this moment we have are HAT working. However, without EEPROM, we cannot really call it a HAT. So, guess what’s next

Cananka, the Raspberry Pi HAT: Layout

Illustration

[This post is part four in the series.]

The most difficult part of board setup is done for us - we have both dimensions and we’ve decided on components. Even better we don’t need to think about board much as our HAT specification has it all sorted out. Or does it?

If you make board based on HAT specification you won’t be able to fit official case around it. We need additional cutouts if we want it to fit - bigger on the left side and just a small one on the right. As board is not really crowded, it was easy to carve out the additional space. However, it might not be as easy for more dense layouts.

Illustration

Top side is dominated by our DC-to-DC converter and nice 3.81 mm 4-pin CAN bus connector. Additionally there are through-hole LEDs so we can see activity and a through-hole oscillator purely because I hate SMD ones. To help with troubleshooting a few pads without solder mask are along the edge.

The whole board is essentially split into two parts. On top we can find components that can safely connect to Raspberry Pi. Most notable being MCP2515 CAN bus controller and 24C32 EEPROM needed for HAT compatibility.

Between CAN bus connector and controller we have isolation border crossed only by isolated DC-to-DC converters and ISO1050 CAN bus transceiver. Two millimeter spacing between these two universes should provide adequate protection.

It is a pretty straightforward layout mostly driven by the need to have isolation border and the size of the components.

Now, let’s get the board working.

Cananka, the Raspberry Pi HAT: Components

[This post is part three in the series.]

Usually behind component selection for any project there is a method in the madness. I will try to go through mine. :)

For the most visible part of board, we are going to need a nice CAN bus connector. I personally prefer Phoenix connectors for this purpose. As we are dealing with low voltages, I feel their MCV series is a great choice. It is a 3.81 mm pitch connector allowing for 8 A of current. Better yet, it is a two part connector so you can wire your plug in peace only connecting it to board once ready.

On the bottom we need to have a 40-pin female header. Final distance between our board and Raspberry, per specification, has to be 10-12 mm. However, that doesn’t mean your header has to be that high. Male header on Raspberry is already 2.5 mm. As long as our connector is between 7.5 and 9.5 mm, all is good.

First electronics component is easy - in order to satisfy HAT specification we need EEPROM for our settings. Here we pretty much take recommended circuit and roll with it. Maximum current CAT24C32 will take on write is 2 mA from 3.3 V rail.

Component selection is primarily driven by requirements and rarely we can see it as clear as here: As we need existing Linux driver to support our board, we are pretty much boxed into selecting MCP2515 as our CAN controller. Another obvious choice would be SJA1000 but that one is a few times more expensive. As Raspberry header pins are using 3.3V signal level, we will power it from 3.3 V rail in order to avoid level translator. Maximum of 10 mA will be used from 3.3 V rail.

Clock for MCP2515 can be up to 25 MHz but I’ve decided upon 16 MHz as this figure fits nicely with Raspberry’s divisor controlling SPI bus. It wouldn’t hurt to use higher clock-rate but 16 MHz is a value I use often in another project so I had component handy.

For CAN bus we also need transceiver and of course there is no single answer on which to select. For isolation we can go either with a dedicated isolator (e.g. Si8421 paired with MCP2561) or we can use one of rare isolated CAN bus transceivers.

As isolated transceiver already needs two power supplies, we can avoid level translator and keep each side on its own preferred level. Signal side will be powered on 3.3 V and CAN bus side will be on 5 V. One device that matches these requirements is ISO1050. Not exactly cheap but not too expensive considering it is all-in-one solution. Maximum current of 3 mA on 3.3 V side fits well within our restrictions. On its 5 V side we need 75 mA maximum from the isolated 5 V rail.

Typical application circuit for ISO1050 also mentions additional protective diodes and we shouldn’t forget those too. Searching for basic two-channel TVS diodes supporting 30V and above (in case we get to work with 24 V CAN bus) PESD1CAN comes as a first choice. And guess what NXP tells intended usage is? Yep, CAN bus protection.

There is a big chance we will need to terminate our CAN bus with 120 Ω resistor. For this purpose a place for two 1206 resistors is available. Combined this allows for about 1 W power dissipation, depending on the exact resistors used. Considering transceiver short-circuit current is 105 mA at 12 V, we are cutting it a bit close for the worst-case scenario. But, as such peak currents are not going to last for long, even at 24 V this should be sufficient.

My plan is to use nice Phoenix connectors and simply get through-hole resistor next to the wires. ISO 11898 even recommends such cable termination since that way you can disconnect node without impacting bus. What I definitely don’t want is header or DIP switch controlling this.

Speaking of which, in order to power up our 5 V goodness, we need isolated DC-to-DC power converter. Many of them come in 4-pin SIP interface and can be directly substituted for one another. I opted for ROE-0505S as it is cheap, small, uses standard pinout, and 200 mA it offers is more than sufficient for our needs. It is a bit finicky at low currents so we should put a LED to waste some of that (e.g. 15 mA). Taking into account its efficiency of 79%, we will use around 110 mA from Raspberry’s 5 V rail.

To power Raspberry Pi from CAN bus power, we get to use another DC-to-DC converter. Unfortunately Raspberry Pi is a hungry beast so we must get into bigger and more expensive choices. After taking literally every DC-to-DC converter capable of producing 5 V / 1.5 A from 12 V source available at Digikey and getting theirs pinouts, I’ve noticed essentially two groups with a few outliers. First group was of devices measuring 32 x 10 mm. These devices run around $25 and all share same pinout (e.g. JTF0824S05). Another group came in 25 x 25 mm size, sharing the same pinout, but unfortunately at a slightly more expensive $30 (e.g. JCM1512S05).

With board measuring only 65 x 56 mm, both would fit, but square one would be much easier to place due to camera slot so I’ve decided to go with that. While those are more expensive devices, for some reason they offer higher current output than their rectangular cousins so 2 A is the norm here. Fact all devices in this group use the same pinout means it will be easy to find replacement if original choice (S24SE05002NDFA in my case) becomes unavailable.

We also need a simple 2 A fuse on power-back circuit together with an ideal diode circuit as recommended by HAT specification. As with any DC-to-DC converter we have to keep minimum load in mind (usually around 10%) but Raspberry Pi is hungry device so we can ignore it this time. Even if we do not meet it, nothing bad will happen as only effect is that supply will go out of spec. As Raspberry Pi doesn’t use 5 V directly but goes over another DC-DC converter, we are safe even in sleep mode.

For those wondering why the heck we are accounting for each mA, answer lies mostly in Raspberry Pi header and 3.3 V rail. Maximum current we should pull is around 50 mA. Anything more and you might make for an unstable system unless you use a separate voltage regulator bringing beefier 5 V rail into play. On 5 V rail we are pretty much only limited by power supply used. If using normal 2 A supply, you should have round-about 500 mA available provided there are no hungry USB devices connected. If you kept with accounting, we have 15 mA usage from 3.3 V rail and 110 mA on 5 V. Well within the spec.

Onto the board.

Cananka, the Raspberry Pi HAT: Requirements

[This post is part two in the series.]

Signalling-wise you can see CAN bus as 5V based but its automobile roots make 12V supply voltage quite common and that is what I am actually using at home. Annoying thing when using 12V is that every CAN board has to drop voltage to 5V needed for logic. Good thing is that you are carefree with longer cable runs. When using 5V, even drop of 10% is a problem and 12V can give you much more breathing room.

Considering I will connect this device to the potentially harsh world, it would be splendid to have its CAN bus portion completely electrically isolated from the Raspberry Pi board. Therefore it will need a major screwup on the input interface to take Raspberry to its death. As CAN bus can span quite a lot of distance and you don’t know all components will be on the same power circuit, this will also help to deal with ground loops and all those different potentials.

Having CAN driver isolated also means we have to power it from somewhere. While my “slave” devices obtain power from the 12V line, for HAT I’ve decided to go with on-board DC-to-DC converter. This makes my device essentially compatible with any CAN bus, regardless of its voltage. Removing external power from consideration also makes it less likely to have a outside high-currents flowing around.

Of course, it would be nice if we could power Raspberry Pi from our CAN power rail. Since isolation is name of the game, we need DC-to-DC converter capable of at least 1.3A (preferably 2A) at 5V. As these modules are usually expensive, this has to be optional part. And yes, back-powering device should be safe even if user forgets to unplug it from USB.

On mechanical side, in addition to HAT basic requirements, possibility of having the HAT on while Raspberry Pi is in the case would be desired. Official case is preferred but other cases should be taken into consideration. This will greatly limit component placement and it could even impact size as, on the first glance, the official HAT dimensions might be a smidge too big for the official case.

On software side it would be ideal to make a board compatible with existing CAN device driver already present in Linux. Default settings for device should be as close as possible to defaults used by that driver. While creating your own driver is possible and not that complicated considering simplicity of a CAN bus, it makes a little sense to create something you will have to compile every time when new OS is installed if you can go with something already present in the kernel.

Onto the component selection.

Cananka, the Raspberry Pi HAT

Illustration

[This the first post in the series.]

As I got myself a Raspberry Pi, I started thinking about connecting some electronics to it. And in Raspberry world you can either just connect some wires to connector or go about making a HAT.

Raspberry Pi HAT specification defines both mechanical properties and a minimum of electronics while still allowing you to do whatever you please with available IO. Pretty much the only strict requirements here are board size (65x56 mm), hole placement, and presence of a special EEPROM with board identification data. A bit more complicated than bare wiring but simple enough.

Armed with knowledge of what’s needed, I had to decide what I’ll actually make. As I played a lot with CAN bus lately, it seemed as a reasonable choice. Not only I go with something familiar on a first try but I get to connect it to the rest of my humble CAN bus world.

Early into the project one has to decide on a name. In this case the name was obvious - Canberry. Unfortunately it was obvious to someone else too as there is already a project with that name. Lesser man would give up here as not only the name is taken but it is taken by a really similar project. However, project is not exactly the same and differences will make exercise worth-while.

With the preferred name taken, choice fell onto CanPi. Guess what - there is also project named CANPi out there. One guess at what it is about. :)

For a while I’ve settled onto Can314 and actually used it for a few days in my notes until, unrelated to electronics, I was playing with Red Hat. Suddenly its younger sister Fedora came to mind. As fedora is type of hat, what else to call Raspberry Pi HAT than Candora. Name seemed good for a while but I wasn’t completely happy.

However, now I had an idea. With the help of Wikipedia hat page I’ve came upon a few other names inspired by hats: Canbeen, Canullo, Canetto, Canouch… just to name a few.

But at the end Cananka, a name based upon Russian ushanka hat, won. Not only it is easy to pronounce but Google only finds 7100 matching pages.

With the name selected, onto the requirements.

No Delays.h

After not touching project for a while, using MPLAB X 3.26 with a newer XC8 compiler (1.37) brought me error: (141) can't open include file "delays.h": No such file or directory. For some reason delays.h got cut from the environment. Fortunately, the only function I’ve used from that header was Delay10KTCYx - one you can directly replace with a _delay macro.

For example

Delay10KTCYx(6);

can be directly substituted for:

_delay(60000);

But that works only up to 19 - values 20 and above will give you error: (1355) in-line delay argument too large.

For those we can always create a more direct substitute:

void Delay10KTCYx(unsigned char count) {
    do {
        _delay(10000);
    } while(--count != 0);
}

Using AN20 on PIC16LF1559

For one pet project, I decided to use Microchip’s PIC16LF1559. as it was close to perfect as far as my needs went in that particular scenario. So I got all parts, soldered it onto the board and it almost worked perfectly.

Single thing that gave me trouble was light detection. It seemed as if ADC converter was giving me nonsense. I check and rechecked my code multiple times as this was the first time I’ve dealt with this chip. It took me a while before I remembered to check errata sheet. And, lo and behold, there was an known issue: “AN20 is not internally connected to the ADC bus when AD2CON0’s CHS bit select the pin.” And guess which pin I decided to use for light sensor?

Initialization of ADC is something that will slightly vary with application but what follows is a reasonable starting point:

ADCOMCONbits.ADFM = 1;      //right-justified
ADCOMCONbits.ADCS = 0b111;  //Frc (clock derived from A/D RC oscillator)
ADCOMCONbits.ADPREF = 0b00; //Vref is Vdd
AD2CON0bits.CHS = 20;       //select AN20
AAD2CHbits.CH20 = 1;        //AN20 is connected to ADC2

This will nicely work around the issue by using AN20 on the secondary channel. Not an ideal situation but it was ok in my case as I had no other plans for secondary channel anyhow.

Reading a value is a bit different than when dealing with a usual, single-channel, setup:

uint16_t getAdcValue(void) {
    AD2CON0bits.ADON = 1; //Turn on ADC

    AD2CON0bits.GO  = 1;
    while (AD2CON0bits.GO_nDONE) { nop(); } //Wait for A/D convert complete

    AD2CON0bits.ADON = 0; //Turn off ADC

    if (AADSTATbits.AD2CONV) {
        return AD2RES1;
    } else {
        return AD2RES0;
    }
}

For my purpose it made sense to turn on/off ADC as needed - for some other scenarios it might be better just to leave it always on. But interesting bit comes when reading a value - ADC saves it interleaved between two registers: AD2RES0 and AD2RES1. Code simply had to make sure to read correct one.

And this, slightly roundabout process, finally got the project working.

Date in a MPLAB Hex File Name

Illustration

Every compilation in MPLAB results in the same file - Source.production.hex (yes, assuming you are not doing debug build). This is perfectly fine if we want to program it immediately. However, what if we need to store files somewhere else and, god forbid, under different name?

Answer is simple enough. Under Project Properties, Building there is a post build step option. Enable it and get code for copy in. In my case, I wanted to have hex file copied to Binaries directory:

${MKDIR} "Binaries" && ${CP} ${ImagePath} "Binaries/Whatever.${OUTPUT_SUFFIX}"

But simple copy is not necessarily enough. It would be great if we could include date in the file name. And there problems start - there is pretty much no documentation for build commands at all. Only way to figure things out is to see how they are setup by the platform itself in nbproject/Makefile-default.mk and nbproject/Makefile-local-default.mk. To cut a long story short, there is a way to get output from external command. Just wrap any command in completely unexpected $(shell ) pseudo-variable.

In order to get actual date I prefer using code>gdate (comes with MPLAB installation). Using it our line becomes:

${MKDIR} "Binaries" && ${CP} ${ImagePath} "Binaries/Whatever.$(shell gdate +%Y%m%d).${OUTPUT_SUFFIX}"

Finally after build we will have both our usual Source.production.hex and also a copy of it under Whatever.20150128.hex.

How Fast Can You Charge?

Recently I saw SONICable Indiegogo project promising to double the charging speed on computer. It is supposedly an advanced USB cable with a magic switch cutting your charge times in half. But not everything is as it seems.

First onto a topic of “unleashing double the charge power of the regular charge cable”. As you might know, USB standard limits current to any USB device at 500 mA. What is not obvious from this is that even now you can have devices pulling much more than this - all the way until small fuse stops you. Devices obeying the standard pull 500 mA because they are well behaving citizens - not because USB restricts them from more. Just measure current of any USB cup warmer. :)

Some devices, mobile phones in particular, also have a fast charging mode that triggers when they detect a wall charger. Detection method itself used to be different for every manufacturer. Fortunately they got standardized into two camps - Apple and everybody else. Leaving Apple aside, most phones use USB Battery Charging Specification. Deep in technical text there is a Dedicated Charging Port (DCP) detection method consisting of “short D+ to D- through resistance RDCP_DAT”. At end specification we have RDCP_DAT defined as maximum resistance of 200 Ω. In laymans terms - just connect the freaking D+ and D- wire together.

Since standard USB cable has four wires (5V, D-, D+, and GND - let’s forget about ID for now), whole high-tech solution is to connect two wires together. That will make device think it is connected to a wall charger and that it can stop being good 500 mA citizen. It is the phone who will then pull around 1000 mA (rarely more) from computer. Since fuses on USB port are intentionally overdimensioned, computer will generally allow it.

There are thousands of YouTube videos alone showing you how you can do this. All you need is to get an old USB cable and cut it open. Then short data wires (white and green) together and voila - you have a cable giving you 1000 mA magic.

There are devices enabling this on eBay. Quick Google search found me The Practical Meter and USB Meter Pro on Kickstarter using exactly the same “magic” as SONICable. Heck, even my UsbAmps uses exactly the same principle from 2013 onward as a button option. Unofficially, there were people seeing me use small screwdriver to connect D+/D- lines way before that. :)

This functionality is nothing special, nothing secret, nothing patentable, and definitely not magic. Paying for a $25 cable promising you magic when all it does is enabling something you can get either for free or for fraction of a cost is crazy in my opinion. To be completely fair, just based on images, it does look as a nice cable - those with fashion in mind might be able to justify $25 cable. Just don’t buy it for its technology.

And remember - with USB 3.1, its new connector, and a new USB Power Delivery standard all this will become pretty much irrelevant side note in the history of USB.