The timekeeping gets an unplanned second part, for a fifth variant.
Fifth time is lucky, right ? :-)

http://downloads.qi-hardware.com/people/werner/anelok/tmp/time-backup-20160328.pdf

All the circuits presented so far have the issue that a voltage
above Vcc is present at the MCU's GPIO(s) when Vc1 > Vcc. This
is outside the chip's specification and may or may not cause
trouble.

Joerg suggested another variant, on page 5: the diode is now at
the MCU and thus clamps Vadc to Vcc. A standard diode with Vf
around 0.3 V at 1 uA (e.g., Panasonic DA2J10100L) should work
nicely for this.

One issue with the circuit is that the leakage current of the
ADC pin flows through the 3.3 MOhm resistor, which may cause a
voltage offset that is as large as the whole measurement range.
The magnitude of the leakage should depend largely on the chip
temperature.

Joerg suggested an algorithm that may help there, too. To take
a sample of the unknown Vc1, we would do something like this:


static void pulse(float duty)
{
        output(1);
        sleep(INTERVAL * duty);
        output(0);
        sleep(INTERVAL * (1 - duty));
        output(Z);
}


float measure_vc1(void)
{
        unsigned s0;    // initial ADC reading, in ADC counts
        unsigned st;    // further ADC readings
        float duty;     // duty cycle, 0 <= duty <= 1
        unsigned i;     // change detection timeout

        s0 = adc();                     // sample Vadc = Vc1 + Ileak(t0) * R1,
                                        // in ADC counts
        duty = s0 / ADC_RANGE;          // fraction of Vcc

        while (1) {

                // PWM at "duty" * 100%

                i = SAMPLES;
                do {
                        pulse(duty);    // emit pulse
                        st = adc();
                        if (!i--)       // Vc1 is stable
                                return duty * 3.3;
                } while (abs(st - s0) <= NOISE);

                // correct Vc1

                if (st > s0) {  // we were too high - pull down
                        do pulse(0);
                        while (adc() > s0);
                        duty -= INCREMENT;
                } else {        // we were too low - pull up
                        do pulse(1);
                        while (adc() < s0);
                        duty += INCREMENT;
                }
        }
}


This basically implements a PWM with variable duty cycle. We start
with a first guess based on the ADC value we obtain. Then the PWM
pulls Vc1 towards 3.3 V * duty. This voltage is not affected by
GPIO leakage.

During all this, we read back Vc1 with the ADC (which is affected
by leakage). If the values read back stay long enough within the
expected noise bounds, our duty cycle matches the correct Vc1
voltage.

If our measurements indicate that Vc1 drifts away, we emit 0% or
100% pulses until it goes back to the original value, and we adjust
the duty cycle up or down, accordingly.

For faster convergence, INCREMENT should be a function of the time it
took to pull Vc1 back to the original value.


This seems to look pretty decent, and is easy on the hardware.
Thanks a lot, Joerg !

- Werner

_______________________________________________
Qi Hardware Discussion List
Mail to list (members only): discussion@lists.en.qi-hardware.com
Subscribe or Unsubscribe: 
http://lists.en.qi-hardware.com/mailman/listinfo/discussion

Reply via email to