Bad things happen when programmer finds a soldering iron

XC8 and Fixup Overflow Referencing Psect BssBANK1

Illustration

For one PIC microcontroller program I had to use assembly code for some critical timing. Rest of code was just plain XC8 C code and everything compiled (and performed) without any issue. So I decided to share code with another project of mine.

Suddenly I got bunch of warnings all saying almost same thing: wait.h:19: error: fixup overflow referencing psect bssBANK1 (0xA2) into 1 byte at 0xB3E/0x2 -> 0x59F (dist/default/production\Source.production.obj 136/0x3E). Program did work (fixup did what its name says) but each compilation would pepper output with warnings - unacceptable.

It was easy to find a culprit:

unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W
    ...
#end asm

Address of an variable was used inside assembly code. Original program had this variable in bank0 and thus no warning were issues. This project had slightly different allocations and variable ended up in bank1 (e.g. 0xA2). Since assembly instruction can only deal with 7-bit registers, address was outside of allowed range.

Once solution is forcing variable into bank0:

bank0 unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W
    ...
#end asm

This works but only after change to project’s compiler flags (Properties, XC8 global options, XC8 compiler, Option categories: Optimizations, Address qualifiers: Require). Just thought of having to remember to change project properties each time I reuse this code made me wince. Yes, it was a solution but not what I wanted.

What I wanted is way to transform offending value 0xA2 to non-problematic 0x22. Quick bit-masking solved that issue and warnings were gone:

unsigned char wait_asm_W; //copy of W
...
#asm
    BANKSEL _wait_asm_W
    MOVWF   _wait_asm_W & 0x7F
    ...
#end asm

Omega Is Not Ohm?

Whenever I had to enter resistance I would use Greek capital letter omega (Ω, U+03A9). It is how I was thought since high school and I never questioned it. That is until I accidentally saw that there is an actual ohm sign (Ω, U+2126). All these years I was doing it wrong. Or did I?

Unicode is known for lot of things but logic is not one of them. Although special ohm sign is available and it is clearly named as such, its use is not encouraged. To quote:

The ohm sign is canonically equivalent to the capital omega, and normalization would remove any distinction. Its use is therefore discouraged in favor of capital omega.

In other words: We created special character but we changed our minds since. Please do not use it.

Well, aside for awareness of this Unicode curiosity, I gained absolutely nothing. Omega I used before and omega I shall continue to use.

Long live 42 Ω.

Elusive CONFIG3H Setting

For toy project of mine I wanted to test PIC18F13K50. Nice fast PIC, lot of RAM, some ROM and USB connectivity. All that while working on good old 5V.

First order of business was to set configuration bits. Code should be familiar to anyone who used XC8:

#pragma config HFOFST = OFF
#pragma config MCLRE  = OFF

Unfortunately that did not work. I could set all bits other than those in CONFIG3H. And thus I could not make MCLR pin behave as normal input. Since PCB was already done, I could not just opt to use other pin. I had to have it my way.

I also tried to use:

__CONFIG(_CONFIG3H, HFOFST_OFF & MCLRE_OFF);

Hell, I even tried

 __PROG_CONFIG(3, 0x00);
```]

Nothing worked.

And than I noticed a curious thing. This PIC has CONFIG2H register followed by CONFIG3H. There is no CONFIG3L. Could that be an issue?

On a hunch I went to edit `18f13k50.cfgdata` (in `C:\Program Files\Microchip\xc8\v1.01\dat\`). There I added single line (highlighted) just before CONFIG3H declaration:

```plain
CWORD:300004:00:00:CONFIG3L
CWORD:300005:88:88:CONFIG3H
CSETTING:8:HFOFST:HFINTOSC Fast Start-up bit
CVALUE:8:ON:HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.
CVALUE:0:OFF:The system clock is held off until the HFINTOSC is stable.
CSETTING:80:MCLRE:MCLR Pin Enable bit
CVALUE:80:ON:MCLR pin enabled; RA3 input pin disabled
CVALUE:0:OFF:RA3 input pin enabled; MCLR disabled

With that simple change all was well and configuration bits were set.

And it works!

P.S. This workaround is valid for all other 18F family PICs that have CONFIG3L missing (e.g. PIC18F1220, PIC18F14K50…).

P.P.S. This should be solved in XC 1.10. Let’s hope. :)

[2012-08-11: As of XC8 1.10 this issue is fixed.]

Selecting a LDO Voltage Regulator

Illustration

I am in process of creating new USB board for my personal nefarious purposes and I needed nice 3.3V voltage regulator. Usually I just use LD1117DT33TR. It has decent maximum current, works up to 15V and it comes in nice DPAK package that helps to keep it cool. However, for this occasion, it was just too big. I wanted something smaller.

While simplest thing would be to pick one that would suit me in this project. However, I always like to spend a bit more time in order to get a chip that I can reuse in bunch of other projects. Here were things that I desired:

  • 3.3 V
  • at least 50 mA
  • SMD
  • LDO
  • easily available in Croatia
  • very simple
  • preferably cheap

First I searched on RS Croatia site for all LDO 3.3V regulators in SOT-23 package. Sorting them by price gave me few candidates. They were AP7313, TS9011SCX, TC1014, SP6201EM5 and MCP1700. All others that were cheap enough were variations of same basic devices. Quick search on DigiKey didn’t find TS9011SCX so it was automatically disqualified. High cost removed SP6201EM5. If I am searching for jelly bean component, I want to have one that is always available and very cheap.

Another odd-man out was TC1014. I haven’t had anything against it’s specifications. They were good enough and in some parts better than chips that stayed in competition. However, it had five leads. I wanted my final choice to be as simple as possible. That left two SOT-23-3 devices in race: AP7313 and MCP1700.

Both these devices satisfy all my needs. And then some. Both have short-circuit protection, thermal protection and both are stable with 1 μF ceramic (nice!) output capacitor. For most parameters where MCP1700 was slightly better they were close enough not to really matter. Great example would be quiescent current. While on first glance there is huge difference in favor of MCP1700 (40x) that only matters in case of extremely optimized battery-powered device. Since almost all devices I do revolve around computer, it is just parameter that I do not care about. For all jelly bean 5 to 3.3 V LDO purposes they are equivalent.

After spending some time going back and forth I decided to use MCP1700T-3302E/TT. Reason was stability. While both regulators work with ceramic capacitors, AP7313 requires output capacitor ESR to be 20 to 200 mΩ. This does cover wide range of ceramics, but for MCP1700 is even better. It’s output capacitor can have ESR anywhere from 0 to 2000 mΩ. That range covers pretty much all capacitor types that I would find on my shelf.

If something comes up where AP7313 would be great fit (e.g. no minimum load), I am fine with that also. You see, AP7313 comes in two different footprints. In case of AP7313-33SRG-7 footprint is same as one that MCP1700 uses. You can mix and match them based on cost and availability as much as your heart desires (just watch for those capacitors!). And that gives real lesson of this post: whenever you can try not to limit yourself to single supplier.

Smoothing

If you are making some measuring device with display it is always a challenge to select proper rate of refresh. Usually your measurement takes only small amount of time and it is very hard to resist updating display after each one. I saw number of devices that have displays that are just too fast to read.

Slowing rate at which measurement is taken is almost always beneficial for both user comfort and battery life. And that is valid solution, especially if value is relatively stable. However, if measurement fluctuates a bit, that results in jumps between values.

To cure that you should be doing averaging. If your measurement takes 10ms to complete, you can do 10 of them, average the result and still have quite a decent 10/second refresh rate. This is probably solution gets most use but it is not the only one.

My favorite way of slowing display is simplified weighted average. Between two measurements one that is current always carries more weight than newer one. Exact weight is matter of trial but I found small numbers like 23% work the best.

To clarify it a bit, let’s say that we have measurement of 10 and measurement of 20. Our new “average” value will become 12.3. If third measurement is also 20, value becomes 14.1, then 15.4 and so on. Value keeps getting closer and closer to real reading but speed with which it does that is very limited.

If you have measurements that are relatively stable this method works almost like an average. If value jumps occasionally this method will smooth such temporary change. That gives much nicer end user feeling as far as measurement goes. And since we are doing this at much faster rate than actually showing data, if permanent jump does occur, user will see such change relatively quickly.

Code for this might look like:

float value = measure();
while (1) {
    showValue(value);
    for (int i=0; i<10; i++) {
        float newValue = measure();
        value = value + (newValue - value) * 0.23; //to smooth it a little
        value = (int)(value * 1000.0) / 1000.0; //rounding
        //do other stuff
    }
}

In this particular code, we show a value to user as soon as we can (to enhance perceived speed). After that we average next 10 values (each new one is given 23% of consideration). Then we display new average to user. Rinse and repeat. Optional rounding step additionally limits small changes.

This code is not that good if measurement takes a long time. E.g. If you have one measurement per second you will find it takes eternity to change a value. For such cases you are probably better off just displaying current measurement to user. Or, if some smoothing is required, using higher values (e.g. 0.79 or similar).

P.S. This method might not work as expected for your measurements. Do test first.

P.P.S. This is intended for human display only. If you are logging values, it is probably best to write measurements without any adjustment. If you average them before writing, you are losing details.

P.P.P.S. If you are doing averaging in full-blown desktop application, ignore this code. You can use proper moving average (linear, exponential, weighted…) that allows for much greater control. This method is just a workaround to get similar results when working on memory-limited PIC.

Quick, Hide It

Illustration

Last half of year I live in a hotel. I do not have my workbench here nor do I have extensive electronics part collection but I do have some basic equipment. And I do use it.

Pictured here is last thing that I made - voltage and current monitor. It has one input, three outputs, display and two switches (that I forgot to order). On bottom there is an PIC, sense and LED resistors. Pretty simple SMD board (45x72 mm) as it goes.

What it does? Basically it just displays voltage, current or power on it’s display for selected input or output.

Once I assembled it, I left it turned on for a while, pressing button here and there. Ok, since buttons are missing, pressing is probably not the correct word for what I was doing, but you get the drift. There is nothing like long-term abuse to bring code bugs out.

As I was leaving for work, I took one last glance at device, stopped, powered it off and hid it in the drawer. Call me crazy but I haven’t dared to leave it on like that for cleaning lady to see.

Somehow I think that she would only see some clock-like device with some wires coming out and numbers that change. Even more innocent-looking things were misidentified.

How Annoying Can You Get?

Most of my electronics is geared toward micro-controllers. And there my undisputed champion is Microchip PIC. They are cheap, full of options and readily available. And development environment is not too bad.

When I say not too bad, I think of MPLAB 8 IDE. Kind of old fella but it gets job done. I did try a beta of their flagship MPLAB X but we never clicked. It didn’t help that it would not load my projects either.

Since I was just starting new project it seemed like a good time to finally get newest and greatest IDE. So I went to their download page and I was greeted by total of 2:30 minutes of video with voice narrative.

I am not sure whether problem lies in me but stealing my speakers for something like download of a tool is ANNOYING. And, of course, some idiot decided to LOOP the video. Probably the same idiot who though that putting stop control was too much work. I though that kind of annoying behavior was reserved for porn sites but Microchip never ceases to amaze me.

Only image that gives me any peace is seeing manager whose idea this was in tenth circle of hell listening to these instructions over and over again. Well at least looping comes handy.

Jelly-bean PIC

My first PIC was 16F84. Choice was easy. Not only that Microchip had relatively few models those days but almost all were of higher price. Yes, brave men would go for write-once chips, but that was pain for any kind of learning or development.

I considered this chip as pure jelly-bean part. I would always have few around. Whatever I designed it was around it (with some exceptions, of course). I probably ended-up using it in 90% of my projects. And I would never run out of it. If there wasn’t any in new parts bin, I would just pull one from old project. Good old days of DIP.

As time went by, there came much more powerful chips but I liked my old trusty 16F84. It took huge price increase from Microchip for me to look for replacement.

It was only natural to select 16F628. It was better chip (good bye USART bit-banging), it was cheaper and it was almost completely pin-compatible with 16F84. These days this is considered quite a modest chip. There is no ADC, no PWM, no I2C and price is rather high for what you actually get. Using it in new projects was just not a real option.

Since last year my default choice fell on 16F1826. It is decent device and it has all things that modern PIC should have. And it is cheap and stocked almost anywhere.

But when I contrast it with good old 16F84, I notice that I am nowhere near 90% usage. Somehow my projects always end-up using more pins that this little gem has or I need some more advanced functionality (e.g. LCD). I probably spend hours looking for micro-controller and then cross-referencing this data with stock in RS or DigiKey. And that is time I lose each time I start something new.

Not even jelly-bean components are what they used to be.

P.S. Yes, I am old and looking back toward good-old-days.

Pogo PICKit

Illustration

Whenever I design board with PIC I need ICSP connector. And connectors take space.

Therefore I started used Au Group Electronics connector soldered to simple cable that plugged into PICkit. By using pogo pins I could put six through-hole pads on borad and have connectivity. Works nicely and it is as cheap as it goes.

That did worked but connector was weak spot. No matter how you hold it, there was need to re-solder broken wire every few weeks. Not too annoying, I guess…

Well, I found myself a new personal favorite.

Mill-max has a nice pogo connector “clearly” named 829-22-006-20-001101. Out of box it comes as 90° PCB-mountable connector but, with the help of pliers, I straightened those pins and they fit perfectly into PICkit 3 (they actually hold better than straight pins). Now I can press onto my board’s pads with whole PICkit and that feels much better.

There is only small issue of fitting into snug spaces. With cable you can get into any space, with this “connector” things work better if connector is at board’s edge. But it is small price to pay.

P.S. Connector is available from both DigiKey and Mouser.

P.P.S. Yes, connector works with both PICkit 2 and PICkit 3.

Rule Number One

Illustration

I got into discussion with friend about best practices when it comes to designing things around PIC micro-controllers. One that we agreed on was to never, absolutely never use ICSP (in-circuit serial programming) pins for anything other than connecting to PIC programmer.

Yes, I know that there are things that you can connect safely to those pins while having them functional as far as programming goes. Yes, I am aware that I am talking about two-and-half perfectly good I/O pins (PGC, PGD and MCLR). Yes, I am probably overreacting. Taking all into account, I still stand by my recommendation.

I know how it goes, first PGC and PGD are left alone. As design develops, we seem to be one pin short. No biggie, we just use PGC for a button. Simple button cannot hurt. Then we need status LED, PGD can do that!

As design develops we move pins back and forth and, sooner or later, we end-up with something like pull-up or diode on ICSP. And that spells trouble. I will not even go into how exactly are we to use ICSP for in-circuit debugging if we have to use it for e.g. input button that triggers action we are trying to debug.

I am not saying it is impossible to use ICSP in your circuit. Those pins can serve as excellent last resort. But most of time it is better to go for a bigger gun PIC.

P.S. Yes, I broke ICSP rule fair number of times.