# C-field driver - again¶

After some work I have designed at this C-field driver:

The main change since first version a couple of extra resistors supply the stable current for the buried zener in the LM399 voltage reference.

I’ve run a monte-carlo analysis for the tempco of the components over a ±10 {K} temperature range.

## VCC & R4¶

VCC is the +20V regulated supply, which I allowed to vary ±0.5 {V}

If R4 is 1M with 100 {ppm/K} tempco, the frequency noise is 6.5e-17 {s/s}.

If R4 is 100k with 100 {ppm/K} tempco, the frequency noise is 5.7e-16 {s/s}.

I have not checked how small R4 needs to be to ensure startup, but given the low offset voltage of U1, I don’t expect problems.

## R2 & R3¶

The voltage over these is the same (± U1’s Vos) and their ratio sets the U2 zener current relative to the C-field current.

With 50 {ppm/K} each of them contributes 6.7e-17 {s/s} frequency noise.

## U1¶

LT1007 has a guaranteed max drift with temperature of 0.6 {µV/K}, which contributes 1.1e-15 {s/s} frequency noise.

There is no need to trim the offset of U1.

## R1 & U2¶

R1 is a Vishay Z201 with a *typical* tempco of ±0.2 {ppm/K}

U2 is a LM399 (without -A suffix) with a *typical* tempco 0.3 {ppm/K}

If we use these typical tempcos, the frequency noise is 4.3e-15 {s/s}

If we use the max tempco, 2 {ppm/K}, for the LM399 and the typical for R1, the noise rises to 2.4e-14 which is above my 1e-14 {s/s} goal.

There is no max tempco specified for the Z201, and the datasheet doesn’t give me high confidence that the typical is very typical after all.

## Temperature¶

The limiting factor is R1 and U2, and all in all there is about 1.5 {ppm/K} tempco to share between them.

Of course ±10 {K} is a pretty brutal condition for a device which presumably lives in a somewhat civilized laboratory.

If we can keep the excursions to ±2{K}, then R1 can have 3 {ppm/K} tempco and still stay below target.

## Tunable C-field current¶

Mechanical trimmers have two digit tempcos, and since they would go between U2 and U1, math isn’t even necessary.

A digital solution *may* be possible, there are special DACs for
driving 4-20 {mA} industrial circuits, for instance Analog’s AD5422,
which could possibly be beaten into submission, given a good
external reference.

That would be neat, since it would open the way for a GPS discipline implementation, but that is a project for another day.

Right now I just want to get the Fluke 732A and the long wire out of the picture.

## Monte-Carlo Code¶

Here is my monte-carlo simulation in python:

```
#!/usr/bin/env python
#
#
# VCC
# |
# |
# R4
# | |\
# *--------------| \
# | | >--- L1 --+
# | +--| / |
# | | |/ |
# | | |
# *---- R3 -------+-----------+
# | | |
# | | R2
# | | |
# D1 +---*
# | |
# | R1
# | |
# GND GND
#
from __future__ import print_function
import random
import math
def calc(comp):
d = dict(comp)
for i in range(5):
d["vr1"] = d["D1"] + d["U1"]
d["ir1"] = d["vr1"] / d["R1"]
d["vr2"] = d["ir1"] * d["R2"]
d["vl1"] = d["ir1"] * d["L1"]
d["vout"] = d["vl1"] + d["vr2"] + d["vr1"]
d["vr3"] = d["vr1"] + d["vr2"] - d["D1"]
d["ir3"] = d["vr3"] / d["R3"]
d["ir4"] = (d["VCC"] - d["D1"]) / d["R4"]
d["id1"] = d["ir3"] + d["ir4"]
d["D1"] = comp["D1"] + d["id1"] * .66
return d
def show(d):
l = d.keys()
l.sort()
for i in l:
print("%s\t%17.9f" % (i, d[i]))
def ppm(n):
r = random.uniform(-n, n)
r *= 1e-6
r += 1.0
return r
comp0 = {
"R1": 5000./3, # Ohm
#"R1": 1000., # Ohm
"R2": 500, # Ohm
"R3": 2000, # Ohm
"R4": 1e5, # Ohm
"D1": 6.9, # Volt
"L1": 12.0, # Ohm
"U1": 0.0, # Volt
"VCC": 20.0, # Volt
}
d = calc(comp0)
show(d)
iref = d["ir1"]
sy = 0.0
syy = 0.0
n = 0.0
for i in range(1000):
x = dict(comp0)
dt = 10
# 2.4e-15 @ 2ppm (LM399), +/- 10K
x["D1"] *= ppm(2 * dt)
# 2.5e-15 @ .2ppm (Z201 TYP!), +/- 10K
x["R1"] *= ppm(3.0 * dt)
# 1.1e-15 @ .6PPM/K (LT1007A), +/- 10K
x["U1"] = 1e-6 * random.uniform(-.6 * dt, .6 * dt)
# 6.7e-17 @ 50pmm, +/- 10K
x["R3"] *= ppm(50 * dt)
# 6.7e-17 @ 50ppm, +/- 10K
x["R2"] *= ppm(50 * dt)
# 6.5e-17 @ 100ppm, +/- 10K, 19.5-20.5 VCC
x["VCC"] = random.uniform(19.5, 20.5)
x["R4"] *= ppm(100 * dt)
d = calc(x)
df = (d["ir1"] - iref) * 5e-7
sy += df
syy += df * df
n += 1.0
avg = sy / n
stddev = math.sqrt((syy - sy * sy / n) / (n - 1))
print("%.1e" % stddev)
```

*phk*