I was checking out V2 of Microchip’s C32 compiler, a much needed update to the MIPS GCC 4.5 compiler. When I looked at the release notes, they the compiler supported a bunch of part numbers I had never seen before. Here is the device support table:

The part’s on the left in green are the new ones. I did a search for the first part number (PIC32MX110F016B). It was already in the Newark database although not in stock. Newark has it listed at $1.98 with the following specs:

PIC32, 16KB Flash, 4KB RAM, 40 MHz, CTMU, 4 DMA 28 QFN 6x6mm TUBE

This makes sense. PIC32 used to to rank well on the list of low-cost 32-bit MCUs. These days the slew of new value-line ARM Cortex M0 and Cortex M3 MCUs make it look rather expensive. If the Newark price of $1.98 at QTY 183 is correct, it makes the PIC32 somewhat competitive price-wise. I am glad, I would love to see an ultra low-cost 32-bit alternative to ARM. For comparison, here are some of the cheaper ARM chips. The prices listed are also from Newark at QTY 250:

So if that data is correct, the PIC32 would be ahead of TI but still a bit higher than the cheapest parts from ST and NXP. Of course, I don’t know the whole story without the datasheet. I am sure the PIC32 will have it’s own unique advantages.

The pictures shows the size difference between the hardware font and the new bitmap font. I wrote the function to work only with the included 16 pixel fixed width font (Lucida Console). I didn’t have time to write a proper font converter utility and all that.

The bitmap function should work fine with the any LCD bitmap converter. Pixels are encoded left to right, one byte representing 8 bits and each new line starting with a fresh byte (see example bitmap header file). You must specify the correct size or the bitmap will be garbled.

First of all, don’t interpret this as some kind of anti-Arduino rant. I think the Arduino is a handy tool and, I think it’s great for introducing hoards of people to something they enjoy. I am not writing this because I don’t like the Arduino; I am writing this because there is no solution for every problem. Speed, flexibility, and cost would be the primary reasons not to use Arduino. There are times when you will need more than 8-bit microcontroller or a different peripheral set. If you are looking at production, even if the ATmega series does meet your needs in those areas, you may want something cheaper. The ATmega has its high points but as far as 8-bit micros go, price is not one of them.

I think that most Arduino users realize that the hardware is nothing particularly special. The part of Arduino that is usually lauded is the software environment. I have heard comments such as “It’s a lot like C but easier” or “It’s an easy to use language based on C”. Well, I have news for you. All of you have been HOODWINKED! It is not like C; it is not similar to C; IT IS C. Well, it’s actually even harder than C; it’s C++, which is a bit odd for the 8-bit space. The Arduino IDE is not even a preprocessor. When you compile an Arduino program, your code is taken completely unmodified and compiled directly with AVR-GCC (the open source AVR compiler). I know what you’re thinking; it’s like the Twilight Zone. Here you’ve been, shaking in your Nikes at the thought of the vast and scary world of big-boy microcontrollers, not knowing that the whole time you were already in it. You have already been using the standard open-source AVR tool suite, you just displaced AVR studio with the Arduino IDE. There is a tutorial about how to compile your project outside if the Arduino IDE on their website here.

So why does anyone care about Arduino? The magic of Arduino is in the library that comes with it. It is a set of source files that is included with your project when it is compiled. You are free to look at those files, they can be found inside the Arduino directory under hardware\arduino\cores\arduino. Essentially, these files contain a set of functions that hide special function register access from you. SFRs are locations in memory that do things in addition to just storing data. For example, the SFR register assigned to an I/O port would make the pins go high or low when you wrote to it. That’s it; writing to registers is everything that separates you from programming for any microcontroller you want.

Guess what else? The Arduino library, being high level and all, could just as easily be written for any other microcontroller. That means, assuming you didn’t access registers directly, that all of your existing Arduino code can be used as-is on any microcontroller you want. All you have to do is write the functions you used for the new platform. For example, on a PIC, the digitalWrite function might look something like this:

There are times when you should think about accessing the SFRs yourself, even if you don’t need a different platform. Take, for example, this line of code that sets pin 1 of ATmega port D high:

PORTD |= 2;

Literally, that line includes at least three instructions: read the value of PORTD, do a logical OR with the result and the value 2 (10 in binary), then write that result back to the port. However, AVR-GCC knows what you want and it will compile that into a single instruction that takes two clock cycles to execute. You can learn something about that here. Now, let’s consider the Arduino alternative:

digitalWrite(1,1);

Assuming AVR-GCC does not automatically inline the digitalWrite function (it is not declared inline), that will take about 16 cycles. The Arduino library was written for usability and development time, not for performance. In this case, accessing the register directly results in a 8x performance improvement.

If you are already using Arduino but you decide you want to be able to program microcontrollers in C, you will need to learn two things, neither of which should take you very long. The first thing is some additional semantics of C. You’ll need some basic knowledge of includes, defines, etc. I think this tutorial is very good but there are many. The second thing is how to handle bit manipulation in C. For example, you’ll want to know how to set the fourth bit of a byte to 1. You can find a tutorial on that here.

Don’t throw out your Arduino. It’s a good thing to have. On the other hand, if you haven’t branched out, you are like a tourist who travels all the way to China just to see the airport. Sure, the airport is great but now that you’ve come all that way, you might as well step outside.

The S1D13700 is an LCD controller IC made by Epson. It is common among 320×240 monochrome LCDs. It has a software interface that is similar or identical to the SED1335 and Raio RA8835. Recently, I had the pleasure of writing some software for it. Several quirks made it kind of a pain, so I thought I share for the next guy.

First, have a look at the timing diagram found in the S1D13700 Datasheet.

S1D13700 Datasheet Timing

OK, now stop looking at it because it’s wrong. For some reason, following that timing pattern produces unstable results when writing to the graphics layer. Here is a video demonstrating the type of problems you end up with:

It turns out the trick is to only activate the CS line while you transition the WR or RD pin on its sensitive edge but not the other edge. So, when writing, you would only hold CS low long enough to transition WR from high to low. The opposite applies to RD. Here are some working code snippets:

Since that did not cause enough frustration and productivity loss, there is another gotcha. There is an apparently vital but unmentioned (I couldn’t find it in the datasheet) delay that must be inserted after the initial system set command and before the parameters are passed for that command. If you don’t ensure a proper delay, the LCD either won’t start or, strangely, will output the wrong data when you attempt to do a read. So the start of the initialization routine should look something like this:

I had been using a mix it yourself from powder solution for tin plating. It’s a PIA and has to be heated prior to use. I heard about Liquid Tin some time ago. Not only do you not have to mix it, you don’t have to heat it. I didn’t bother with it because if it’s not broken, why fix it. Well, two weeks ago, I got aggravated with tin plating so I figured I would give it a shot. I cannot believe how well it works. I feel like an idiot for wasting my time now. I guess I assumed that a solution you heated would work faster and better but I was seriously wrong. Liquid tin works almost instantly and seems much more tolerant of not getting that last spec of oxide off with the scrub pad. I highly recommend it.

ARM has apparently decided they want to go after markets traditionally reserved for 8-bit and 16-bit applications. They have released the new Cortex M0 core, a lower capability 32-bit core, with mostly 16-bit instructions, targeting cost sensitive applications. The only company, that I know of, selling chips based on this core is NXP with their LPC1100 series. This isn’t a huge surprise; two other typical ARM adopters that spring to mind, ST and TI, both have there own 8/16 bit lines and they wouldn’t want to compete with themselves.

After review the LPC1100, I have to say, they have quite a convincing case for using their product in lieu of 8-bit micros in many applications. To start, it is shockingly cheap, you can get these parts at mouser starting around 1$ for QTY 1. So, in the cost arena, it truly does compete well with 8-bit parts. It can be had significantly cheaper, for example, than a similarly spec’ed ATMEGA. The LPC1111 with 8KB program memory and 2KB RAM costs $1.30 at QTY 1; the new ATMEGA88PA, with 8KB and 1KB costs $3.05. I am not going to say the ATMEGA has no advantages vs. the LPC1111, because I am sure that it does (I have not looked in detail) but the Cortex M0 part has some very big computational advantages here. The chip runs at 50Mhz and runs most instructions in 1 cycle, including single cycle multiply. Compare that to the ATMEGA series which tops out at 20 MIPS or the PIC18 series which tops out at 16 MIPS. That’s a huge difference in power. The only thing I know if that comes close anywhere near 3$ is the Atmel XMega series which does 32 MIPS. The XMega also has a set of peripherals that blows away the LPC, it is too bad most xMega models are never in-stock anywhere.

If that weren’t enough, the LPC1100 series lists ridiculous power consumption figures. The chip consumes 3mA at 12Mhz and 9mA running at full bore at 50mhz, in active mode. At 3V and 4Mhz, the ATMega88PA is already consuming almost 3ma and doing only 1/3 the work. To the best of my knowledge, Atmel’s most efficient 8-bit micro is the xMega, which consumes about 12ma at 32mhz. If we make an apples to oranges comparison with one of Microchip’s new darlings of power efficiency, the PIC16LF1823, things look a little better. The Pic uses 0.84ma at 16Mhz. Remember though, the PIC instruction cycle is 4 clocks long, so 16Mhz here can be though of as 4Mhz when comparing to an Atmel or LPC. To compare it to the LPC figure, we can roughly estimate by multiplying by 3 and getting about 2.52mA for 12 Mips. Slightly better, but this is comparing a much less capable micro in a different class with no hardware multiply. So basically, the power figures are impressive. It is worth noting that the PIC16LF1823, can be run on 1.8V, in which cases it only uses 0.47ma at 16Mhz.

One particular implementation defined feature (defined by NXP and not ARM) that caught my eye was the way in which bits can be assigned to the GPIO ports in one cycle using address masking. This feature is also implemented by the NXP Cortex M3 series. Rather than having one register address for a GPIO port, or even 3 (INV, SET, CLR) like many micros, the LPC1100 series has 16,000 or so register addresses for each GPIO port. The address serves as a bit mask for the port assignment. For eample, The adress range for PORT 1 is 0×5001 0000 to 0×5001 3FFC. The port is 12 bits wide and the mask bits are bits 13 through 2 of the address. The hex number 0×3000 expands to the binary number 11 0000 0000 0000. As you can see only bits 12 and 13 are high. Those bits correspond to 11 and 12 of the port. So, no matter what I write to address 0×5001 3000, only pin 11 and pin 12 of the port are effected. I think that is an incredibly useful feature and I much prefer it to the set, invert, and clear triage of registers. The Texas instruments Cortex M3 series employs a similar addressing scheme but the ST M3 series does not.

Are ARM vendors going to steal all of Microchips business overnight? No, of course not. Currently, the LPC1100 series consists of one line of chips, offered in two packages, QFN32 and TGFP48. Obviously, that can’t compete with the huge range of micros offered by 8-bit vendors. Nor can ARM compete with the huge amount of support already available from 8-bit vendors for typical 8-bit applications. For example, if I need the lowest cost method of implementing embedded Ethernet, I will still be headed to Microchip. However, for those situations where NXPs limited range of Cortex M0 micros happens to fit the needs of your application, they make a very convincing argument.

I am going to follow-up my last post on current sensing with a real world example. I am going to set up an example circuit designed to sense current flowing from a 24V 60Hz AC Source using a 5V instrumentation amplifier. Before we do that, however, I want to illustrate the relationship between the ground in a circuit that has been rectified into DC and its original source. Note this example set-up:

An exaggerated sense resistor is used for clarity. Here we examine the sense voltage relative to rectified ground. This is the oscilloscope result:

Sense Resistor Voltages

As you can see, we have an ugly waveform on the top. Sometimes pin 1 (blue channel) of the sense resistor is at a higher potential, sometimes pin 2 (yellow channel) is. The red waveform is the difference between the two channels, it represents the sense voltage, and of course, is perfectly sinusoidal. The scope is set up for DC coupling here. The key point here is that the AC voltage is always positive with respect to your rectified ground. This will always be the case as long as a pin of your resistive sense element is aligned with either of the AC source nodes. If you try to sense across a reactive element (capacitor, inductor) or place your sense resistor in between reactive elements, the voltage will be out of phase with the voltage you rectified from; as a result, part of the waveform will be negative relative to rectified ground.

The schematic below represents a circuit designed to exploit this “always positive” property to sense current. If you consult the original post, you’ll see that we need to offset the voltage so that the single supply micro can tell if it is negative or positive. We could use a quad op-amp chip, use 3 op-amps for an instrumentation amplifier and the final op-amp to buffer our offset voltage. In this case, however, it is going to be much easier to use a pre-packaged instrumentation amplifier. I have chosen the Analog Devices AD8293 amplifier. It is a fixed gain amp, offered in either 80 or 160 gain. It has very good characteristics and accuracy and is reasonable priced at $1 – $2 USD in very low quantities. Especially useful for our purposes here, it has a high impedance REF pin for offsetting the output. The datasheet specifically states that no buffering of this offset is necessary. Its major limitation is low bandwidth but that won’t be an issue for sensing from the 60hz mains. I have set up the following circuit.

As you can see, the voltage is divided down by a factor of 11 so that it is in range of our amplifier, which then amplifies the difference by 160. It would have made more sense here to use the AD8293G80 80 gain version and use a higher sense resistance like 0.4 ohms, but I only had the AD8293G160 on hand. The net result is that our sense voltage is amplified by a factor of 14.55 [formula: (1/11) * 160] and referenced to half of VCC . Since the offset divider is radiometric, no matter where the supply moves, the offset will always be exactly half of the ADC top value. Here is the oscilloscope shot of the results. The oscilloscope ground is connected to the rectified ground and the probe is connected to the ADC OUT to ADC IN line.

DC Coupled Waveform

AC Coupled Waveform

As you can see from the DC waveform, the voltage is well within the sensing range or a 5V microcontroller. When selecting your range, make sure that your full scale expected current range does not cover the full scale ADC range. You will want some margin for detecting fault conditions. Using my Fluke 87 true RMS meter, I measured the circuit voltage to be 23.3VAC and the total resistance to be 78.2. This would equate to about 298mA which would create create a sense voltage of about 59.6mV across the 0.2 ohm sense resistor. When amplified by the 14.55 gain, our expected output voltage is about 867mV RMS. Per the oscilloscope shot, the measured result is 860mV RMS, quite an impressive result.

In order to calculate RMS current in the micro, the waveform must be sampled at regular intervals and combined into an RMS figure. The following is a psuedo-code example:

/* The following is pseudo for concept illustration. It has not been checked or debugged */
int results_array[1000];
int result_count;
//get a full 60hz cycle of 16.66 ms
begin_time = get_millisecond_tick();
result_count = 0;
while ((get_millisecond_tick() - begin_time) < 16.66)
{
startADCConversion();
while (isDoingConversion());
int result = getADCResult() - 512; //subtract half value for 10-bit ADC to get signed result
results_array[result_count] = ConvertADCValuetoAMPS(result);
result_count++;
}
int total = 0;
int i;
for (i = 0; i < result_count; i++)
{
total += results_arry[i] ^ 2; //square each term and add them up
}
total /= result_count; //divide by the total number of terms
int TrueRMSCurrent = sqrt(total); //the square root is the RMS value

The main point of caution about this circuit is that it is extremely sensitive to common mode error caused by resistor divider mismatch. For this demonstration, I manually matched two 10k resistors, then matched two 1k resistors. 1% tolerance resistors can not be counted on here. Unchecked you will simply end up with useless readings. Basically, you have three choices here.

I made some minor changes to a prototype before ordering the final PCBs. Of course, I made a mistake. It was the kind of annoying mistake that results from not paying attention. I am now the proud owner of 100 green coasters.

The circuit is essential the same as an operational amplifier in a differential amplifier configuration. The important difference is, instead of connecting the non-inverting input to ground, it is connected to a buffered voltage which is equal to half of your ADC reference voltage.

Bidirectional Current Sensing Schematic

In software, you retrieve an unsigned value from the ADC register, copy it to a signed integer value and subtract half of the top value. For example, for a 10-bit ADC:

int MY_SIGNED_RESULT = ADCVALUE - 512;

If your ADC supports differential conversions, You can still use the above and save a pin; or you can direct VHALF into the inverting input and the op-amp output into the non-inverting input and convert with a signed result.