Tuesday, September 27, 2011

Checking out the Pierce oscillator

The Pierce oscillator is a very simple circuit and as with the ring oscillator also uses inverters (actually just one inverter will do). The principle of operation, however, is very different. While the ring oscillator exploits the incremental propagation delay through the series of inverters, the Pierce oscillator puts the inverter/gate into the linear region of operation and employs it as an analog amplifier.

To find out the details of the gate-based Pierce oscillator I recommend reading the references listed below. What follows is just a summary of the tips and formulas culled from the said references, pointers and tidbits which I found useful in getting a crystal-based oscillator up and running. I also did a number of breadboarded experiments and the results are shown below.

The following schematic shows the basic Pierce oscillator based on a CMOS inverter as its amplifier.


INV is of course the inverter (buffered or unbuffered). Oscillator signal is taken from the inverter output (Vout). To improve (decrease) its rise/fall time, another inverter or, better yet, a (fast!) Schmitt trigger can be used to spruce up the signal. The signal at the inverter input is a sinusoid and can also be used (some Microchip MCU datasheets show the clock signal being derived from the input of the inverter while other Microchip datasheets show it being taken from the inverter output).

Rf is a feedback resistor that puts the gate in linear (as opposed to digital) mode operation. The following table provides a rule of thumb value for Rf given crystal frequency:


Among other things, Rs limits the amount of crystal drive--increasing Rs decreases drive. A ballpark figure or first cut value for Rs can be derived by computing for and equating Rs to the reactance of Cb:
Xcb = 1/(2πfCb), where f = crystal frequency
According to Microchip:
Rs is typically 40 K ohms or less, but is almost never more than 100 K ohms. If the value for Rs is too high, then the high impedance input side of the amplifier may be more susceptible to noise, very much the same way a pull-up resistor on an input pin is normally kept below about 50 K ohms to prevent noise from having enough strength to override the input.
Freescale (Motorola) meanwhile claims that for low frequencies such as 32.768kHz watch crystals, Rs can go as high as 330Kohms. Because of a permissible maximum drive of just 1µW, a minimum Rs value for tuning fork crystals such as the 32.768kHz crystal is 10kohm.

Ca and Cb along with Rs and XTAL provide a 180 degree phase shift (INV provides the other 180 degrees for a total of 360). Moreover, the Rs and Cb network partly "acts as a low pass filter that discourages the crystal from running at a third or fifth harmonic, or other higher frequency" (Lancaster and Berlin). Increasing Ca and Cb decreases the gain. Ca and Cb are usually equal but Cb can be made larger than Ca. The voltage at the input of INV is (partly) determined by Cb / Ca, so that increasing Cb relative to Ca increases the voltage at INV input. As a rule the values of Ca and Cb should satisfy the following condition:
Cload = (Ca)(Cb)/(Ca + Cb) + stray capacitance
where Cload is the load capacitance of the crystal as per manufacturer's specifications. Typical load capacitances are 12 pF, 15 pF, 18 pF, 20 pF, 22 pF and 32 pF.

Finally, an advice worth keeping in mind: "Oscillator design is an imperfect art at best. Combinations of theoretical and experimental design techniques should be used." And so we move on to the experimental side of things.

I performed a few tests on a breadboard using 4.000 MHz and 32.768 kHz crystals. The values for the resistors and caps are the ones I arrived at after some trial and error. The values below seem to work better. Yes, that's a very subjective assessment and shall leave it at that.


I. Motorola MC14049UBCP hex inverting buffer

A. XTAL = 32.768 kHz
Rf = 10Mohm
Rs = 100kohm
Ca = 33pF
Cb = 50pF

Oscilloscope setup
Channel 1 (yellow) hooked up to INV2 output
Channel 2 (cyan) probe hooked up to Cb


CH1: INV2 output
CH2: INV1 output


CH1: Cb
CH2: INV1 output



I increased the capacitances as follows
Ca = 18pF
Cb = 100pF
and I was pleasantly surprised to see that the waveforms became much more stable--it practically ceased "wiggling" (the frequency was stable but the duty cycle wasn't and so the falling edge would be shifting rapidly to and fro horizontally--I was triggering on the rising edge so that wasn't moving at all)

CH1: INV2 output
CH2: Cb


Notice how the increasing the Cb to Ca ratio has decreased the signal's amplitude at Cb.


B. XTAL = 4.000 MHz
Rf = 5.1Mohm
Rs = 2kohm
Ca = Cb = 18pF

CH1: INV2 output
CH2: Cb


The CMOS 4000 series is relatively slow. In the reading above rise time is almost 37ns.

CH1: INV2 output
CH2: INV1 output


CH1: Cb
CH2: INV1 output



II. National Semiconductor MM74HC02N quad 2-input NOR gate. Unfortunately, I don't currently have any CMOS HC or AC series inverters.  According to the datasheet each NOR gate is buffered as follows:


Using a buffered gate in a Pierce oscillator consumes less power and has a gain in the order of thousands compared to an unbuffered gate which has a gain of hundreds. The drawback of a buffered gate is that it is more sensitive to the values of the passive components and tends to be less stable.



A. XTAL = 32.768 kHz
Rf = 10Mohm
Rs = 51kohm
Ca = 33pF
Cb = 100pF

CH1: NOR2 output
CH2: Cb


I believe the over- and undershoots (at the rising and falling edges) is confusing the scope. In the screenshot above it's 40.98kHz, but in real time it's all over the place, sometimes reaching as high as 80kHz. So I turned on the cursors. As you can see it says 32.89kHz. Resolution is such that moving the cursor just one pixel down results in a reading of 32.68kHz.

To obtain a slightly better reading I sent the INV2 output to a Goldstar FG-2002C function generator / frequency counter. The LED display has a resolution to two decimal places and said the signal was 32.77kHz. I guess the output is pretty close to the crystal's fundamental frequency. The frequency counter apparently loads the INV1 output because connecting it directly produces garbage readings (bounces around from 40 to 65kHz). A minimum of 15 ohms of resistance or a few picofarads (the smallest I have right now is 18pF) of capacitance in series is enough to satisfy INV1. The reading is the same as probing INV2 output.

CH1: NOR2 output
CH2: NOR1 output


CH1: NOR2 output
CH2: VDD


CH1: NOR1 output
CH2: Cb


Changing the time base and capturing those overshoots/undershoots:

CH1: NOR1 output
CH2: Cb
Trigger: rising edge, 1.0V


CH1: NOR1 output
CH2: Cb
Trigger: falling edge, 4.0V



B. XTAL = 4.000 MHz
Rf = 5.1Mohm
Rs = 10kohm
Ca = Cb = 33pF

CH1: NOR2 output
CH2: Cb


CH1: NOR2 output
CH2: NOR1 output


CH1: Cb
CH2: NOR1 output


It turns out that the scope probe might be (largely) responsible for the ringing in the output. When not probing either INV1 or INV2, VDD has much less ripple and the ripple in Cb signal practically disappears:


CH1: Cb
CH2: ground


CH1: NOR2 output
CH2: VDD


CH1: Cb
CH2: VDD



References:

Friday, September 23, 2011

Taking a look at basic ring oscillators

Just playing around with ring oscillators cobbled up using a number of basic CMOS gates. Measured VDD of the linear power supply = 5.07 to 5.09V for all circuits. Circuits were assembled on a solderless breadboard. Interconnect wires varied in length. And the relatively long interconnects--compared to the short traces had these been fabricated on a PCB--almost surely affected performance and the characteristics of the oscillators.

I. First up is the Fairchild CD40106BCN hex Schmitt inverter. According to the datasheet its maximum propagation delay = 400ns at 25°C and VDD = 5.0V. Its maximum rise/fall time (transition time) = 200ns at 25°C and VDD = 5.0V. This oscillator has the lowest frequency among those tested. But its output is also the closest to looking like a square wave. Numbers in the schematics refer to IC pin numbers


I measured the output at the various pins to see how transition time would be affected--wanted to decrease it to make the wave as square as possible. The most significant effect occurs with the very first inverter after the oscillator. However, as you can see below, having inverters to "clean up" output after the oscillator has an impact on frequency as well.

Output at pin 8:

At pin 2:

At pin 4:

At pin 6:


II. Motorola MC14049UBCP hex inverting buffer. After discovering how lousy the output of a 3-inverter configuration was I tried a 5-inverter one. As you will see there is improvement but it isn't that remarkable, even if the frequency is almost halved.

At room temperature and VDD = 5.0V, maximum rise time of the 4049 is 160ns, while maximum fall time is 60ns. Maximum propagation delay for low to high transition = 120ns. For high to low max propagation delay = 60ns.

A. Using 3 inverters:

Output at pin 15:

At pin 6:

At pin 4:

At pin 2:


B. Using 5 inverters:

Output pin 4:

At pin 2:


III. If I had them in my inventory I would've tested a 74AC hex inverter and Schmitt trigger, but the only part I have that comes close is a National Semiconductor MM74HC02N quad 2-input NOR gate. Datasheet says it has a maximum propagation delay of 18ns at 25°C and VDD = 4.5V. Maximum rise and fall time = 15ns at 25°C and VDD = 4.5V.  With those specs, it's easy to see that the 74HC line is ultrafast compared to the jurassic 4000 series. However, its transition time to propagation delay time ratio isn't good enough to produce square waves. Actually the output is close to a sine wave. In fact, as can been seen in the scope readings, its rise and fall times aren't even short enough for the output to reach VDD or ground.



At pin 10:

At pin 13:

Friday, September 16, 2011

A very noisy table lamp

Using the ATX switching power supply I was testing a circuit consisting of a PIC12F1822 and SN75176 transceiver, plus a couple of LEDs. The circuit has 10uF filter caps and the MCU has a 0.1uF bypass cap. Much to my chagrin the fluorescent lamp on my bench was affecting the circuit--the MCU would sometimes do a power-on reset when I turned the lamp on or off. The desk lamp has an electronic ballast/starting circuit and has an 18-watt circular fluorescent tube. Adding more caps--100pF, 1nF, 10nF, 100uF--were for naught.

To find out how what the heck was happening I hooked up the oscilloscope to the power rails. I was horrified by what I saw.






The transient would sometimes reach 20V peak to peak! Fortunately it would last for less than 20us. To determine the frequency, I turned on the FFT. As you can see below the range is between 20 to 100Mhz.








I wondered whether a linear power supply would be immune to the transients. I hastily cobbled up one using a 220VAC to 12VAC transformer, W01M bridge rectifier, 470uF filter cap, 78L05 5VDC voltage regulator and a 200-ohm resistor as load. Here are scope readings:







Most of the noise is in the range <40Mhz. The amplitude of the transients seem less than for the ATX supply. However, this supply wasn't connected to the MCU circuit. That may have had an effect.

Friday, September 9, 2011

MCU linear regression implementation

Due to noise in the circuit and real-time fluctuations in the phenomenon being measured the readings from a sensor are unsteady and would jump around from millisecond to millisecond just like the day to day up and down variations in the index of trading bourses. However, in the long run the value does show a trend as the variable being measured increases or decreases or remains relatively steady. Thus I'm trying out linear regression--fitting a line through the mess of data points--to tease out this trend. I've used the least squares method since that's what I'm familiar with (actually it's been years and had to hit the math textbooks to refresh my memory!).

What I need to know during every sensor read is the trend at that point. But of course I need some historical readings to compute for it. So I take the last n readings and use those to derive the line of best fit through the n data points. I only need to know the slope of the line (the y-intercept, i.e., the b in ax+b, is irrelevant). If the slope is positive then this implies the value being sensed is increasing, if it's negative it's decreasing, and if it's very close to zero then it's plateaued.

In the application that I have sensor readings are taken at fixed time intervals. The last n sensor readings are stored in an array. During every sensor read the slope is calculated. Because we're always taking the last n readings every time we compute for the slope what we're doing is analogous to computing for a moving average. In this case we can call it a moving linear regression. 

The slope of the line of best fit is given by

(nΣxy - ΣxΣy) / [nΣx2 - (Σx)2]
where

x = point in time
y = sensor reading

y is easy enough to understand. That's just the ADC reading of the analog sensor output. x, as I'm using it here, needs a little more clarification. Let's say our oldest reading of n readings is in cell y[1] and the latest reading is in y[n]. y[i] was taken at time x[i] . But x[i] does not store actual clock time, but rather normalized time. Thus x[1] = 1, x[2] = 2, ...., x[n] = n. The values of x are fixed even as we discard the old y value and shift in the latest. Moreover, the actual time interval between reads isn't or need not be reflected in x as well. Thus the actual elapsed time between two readings may be 5ms, 48ms, 100ms, 2000ms or what have you. As long as that time interval is fixed for all readings then we're good.

Because the values of x never change, the above equation can be greatly simplified. The formula for an arithmetic progression Σx = n(n+1)/2. Hence the least squares equation can be rewritten as

[nΣxy - n(n+1)(Σy)/2] / [nΣx2 - n2(n+1)2/4]

n is common to both the numerator and denominator and so cancel out. We're left with

[Σxy - (n+1)(Σy)/2] / [Σx2 - n(n+1)2/4]

At this point we can provide the firmware the value of n and let it do the calculations, but I'm using an MCU with only 2K of flash. And because I don't want to slow the processor down with unnecessary math computations--whose answers we already know beforehand because n is specified in the defines--I've simplified the formula further still.

Because the 8-bit PICs have very limited RAM and since the rest of the firmware also needs a lot of memory, I settled on n = 15 (I initially tried n = 31 but ran out of RAM). This number is based on the criterion n = 2i- 1, where i = integer, so that n+1 = 2i. The rationale for this constraint is that multiplying by 2i requires nothing more than left shifting the register bits. This reduces computing time and may also reduce code length. With n = 15 the slope of the line simplifies to

[Σxy - (15+1)(Σy)/2] / [Σx2 - 15(16)2/4]

[Σxy - 8(Σy)] / [Σx2 - 960]

Because x = 1, 2, ... n, Σx2 = 1 + 4 + 9 + .... + 225 = 1,240. So the above further simplifies to

[Σxy - 8(Σy)] / [1,240 - 960]

(Σxy - 8Σy) / 280

Keep in mind the above equation is valid only for n = 15. For other values of n the constants will be different.

Here a C implementation of the above equation. It's in mikroC v.5.0.0. Because there are type conversions--integer to floating point and back--it's important to get type casting correctly or you'll get garbage. If in doubt cast the variables explicitly.

Given n = 15, the latest sensor reading is stored in Y[15]. The 15 historical readings are in Y[0] to Y[14]. These 15 values are the ones used in the equation. Y[15] will be copied into Y[14] and used in the next cycle through the state machine (not shown below). Because I want to see the value of the slope, I've added  variable INTSLOPE. To reduce complications of deriving this from the floating point variable SLOPE when it's negative, the firmware computes for (Σxy - 8Σy) such that it's always positive. Because the slope can be and may often lie between -1 and +1, SLOPE is multiplied by 1000 before it's converted to an integer type and stored in INTSLOPE. This provides a resolution of 3 decimal places. For instance if INTSLOPE = 3571 then the actual slope = 3571/1000 = 3.571. The 16-bit INTSLOPE and the sign (plus or minus) of the slope are then transmitted out of the EUSART TX pin so I can view the values on a logic analyzer.



// MCU = PIC12F18xx or PIC16F18xx
// compiler = mikroC v5.0.0
// September 2011


#define  n                   15        // number of data points for linear regression
#define  positive            1         // sign of slope
#define  negative            0         // sign of slope

void LinReg()
{
  unsigned char i;           // counter
  unsigned int Y[n+1];       // newest reading is temporarily stored in Y[n]
                             // and then copied to Y[n-1]
                             // oldest reading is in Y[0] 
  unsigned int SUMY;         // sum of all Y
  unsigned int SUMXY;        // sum of all X*Y
  bit   sign;                // 1 = slope is positive; 0 = slope is negative
  float SLOPE;               // linear regression value of the slope
  unsigned int INTSLOPE;     // integer version of SLOPE. Actually equal to 1000*SLOPE

  Y[n] = CURR;               // CURR = latest sensor reading
  SUMXY = SUMY = 0;
  for (i=0; i<n; i++)
  {
    SUMXY += Y[i]*(i+1);
    SUMY += Y[i];
    Y[i] = Y[i+1];           // discard oldest reading and left-shift all readings including latest one
  }

  SUMY *= 8;
  if (SUMXY >= SUMY)
  {
    SUMXY -= SUMY;
    sign = positive;
  }
  else
  {
    SUMXY = SUMY - SUMXY;
    sign = negative;
  }
  
  SLOPE = SUMXY/280.0;       // this particular equation is valid only for n = 15
                             // SLOPE will always be positive.
                             // Check variable "sign" to determine if slope is negative or positive
  INTSLOPE = SLOPE*1000.0;   
  
  // transmit 16-bit slope and its sign via EUSART
  // EUSART is set up in a separate initialization routine
  while (!PIR1.TXIF);
  TXREG = sign;              // sign byte; 1 = positive slope, 0 = negative slope

  asm {nop}                  // datasheet says TXIF will give false value if read right after loading TXREG
  while (!PIR1.TXIF);
  TXREG = INTSLOPE >> 8;     // high byte

  asm {nop}                  // datasheet says TXIF will give false value if read right after loading TXREG
  while (!PIR1.TXIF);
  TXREG = INTSLOPE;          // low byte
}

----


IMPORTANT ERRATA
September 10 2011

I was fiddling with the circuit and found the following needed to be changed:

unsigned int SUMY;         // sum of all Y
unsigned int SUMXY;        // sum of all X*Y

to

unsigned long SUMY;         // sum of all Y
unsigned long SUMXY;        // sum of all X*Y

16 bits isn't enough when using a 10-bit ADC. SUMXY can exceed 0xFFFF. While Σy will not exceed 16 bits, 8Σy may. So to make sure, I changed both to 32-bit integers.

For a 10-bit ADC, each Y[i] will not exceed 16 bits of course. However, I found out after hours of going nuts that mikroC does not like the following expression/assignment

SUMXY += Y[i]*(i+1);

because, as far as I can tell, it goes bonkers due to the fact that SUMXY is 32 bits while Y[i] is 16 bits and i is 8 bits. To prevent SUMXY from ending up with garbage I had to change the above to

SUMXY = SUMXY + Y[i]*(i+1);

Friday, September 2, 2011

Gear trivia for not so trivial protection

1. All the DMM probes I own have standard exposed metal rods around 2cm long. When doing hot checks on boards or high voltage AC what-have-you I always have to beware of shorting connections and even the probes and such booboos. To minimize inadvertent and unwanted contacts which could have disastrous consequences, I insulated one set of probes with heat shrink tubing, leaving only the conical tip bare. Now they're ultra safe to use.

2. I don't have a purchased ESD wrist strap. I figure I don't need one if the principle is to ground me to earth potential. What I've been using for years now is this. I have a wire that's connected to a copper stake that's been driven into the soil (earth). A 1 Mohm resistor is soldered in series. This resistor limits the current that may possibly go through you know who. At the other end of the wire is an alligator clip. Since I don't particularly like gators biting me, I wear my watch which has a metal strap to which I clip the alligator onto. When not using it on my wrist, the alligator clips onto a metal sheet I have on the bench. When I can't find my watch or am just too lazy to even put it on, I touch and wipe my hands on the sheet every so often and hope to Thor I won't zap any ICs.