A C Example for measuring sub 2pF capacitance change using a LPC804 chip

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

A C Example for measuring sub 2pF capacitance change using a LPC804 chip

194 Views
joeatrainamp
Contributor II

Here is an Example of measuring sub 2pF Capacitance change using a LPC804.

A few questions:

  • What is process to get an example like this added to the examples in the SDK?
  • What is best way to learn to port this to use the PLU instead of explicit C Code?
  • What is the best process for sharing content like this with other LPC users?
  • Is it worth porting to use Analog comparator rather than gate logic transition threshold? What benefit will we likely gain?
  • Does anybody see a way to increase true resolution by a factor of 10 with clever circuit changes. This would allow either less jitter or less oversampling both of which could save power.

 

 

 

 

/*
 * Copyright 2024 RainAmp.Com
 * All rights reserved.
 *
 * License MIT but please pay for enhancements.
 * or custom engineering  info@RainAmp.com
 */

/**
 * @file    LPC804_read_variable_capacitor_logic_level_transition
 *
 * @brief   Measures Variable Capacitance such as water level changing
 *          between two electrodes by measuring changes in time required for
 *          charge to drop from charge level to gate transition voltage.
 *          This version works on any CPU with sufficient speed even if
 *          they do not have analog comparator or an accurate timer.
 *
 *          CIRCUIT Information:
 *            IO21 = SENSE PIN  (NET SENSE)
 *              Configure as Input with pullup inactive
 *            IO28 = Drive PIN  (NET DRIVE)
 *              Configure as output with default low
 *            IO25 = LED PIN
 *              Configure as output with default low
 *
 *            LED PIN -> 4.7K resistor -> GND
 *            NET-DRIVE -> 28M resistor (R1) -> NET-SENSE
 *            NET-DRIVE -> Diode (D1) -> NET-SENSE
 *            NET-SENSE -> 100pf CAP (C1) -> GND
 *            NET-SENSE -> Variable Cap Positive Electrode
 *            GND -> Variable CAP Negative Electrode
 *            Output on standard Pins at 9600 baud.
 *
 *            NOTES:
 *              Diode D1 current flow from Net-Drive to Net->Sense to allow fast
 *              charging of sense pin.
 *
 *              Discharge of variable capacitor + CAP(c1) circuit is through
 *              resistor R1 into IO25 (DRIVE)
 *
 *              Capacitor C1 is required to be this large on LPC chip to
 *              overcome some leakage on the pin it self. Other chips may
 *              require a larger or smaller level.
 *
 *              This is optimized to sense relatively small capacitance changes
 *              where a 1% change in fluid level may only yield a sub 1pf change
 *              in capacitance. When using larger capacitors will need to reduce
 *              size of 28M resistor. For very large capacitors will need to use
 *              Drive pin to activate a external switch to drive charge cycle or
 *              it could draw excess current from IO28. When using larger variable
 *              capacitors then add a 4.8K resistor between DRIVE and Diode to
 *              limit current drawn from pin to safe level.
 *
 *              This CPU is at the lower end of speed necessary to sense capacitance
 *              changes this small using this technique.  A better
 *              approach is to use VSS such as 12V with an Analog comparator where
 *              we drive two output pins from analog comparator PHigh is high when
 *              SenseCircuit is above VSS * 0.9  and PLOW is high when SenseCircuit
 *              is below VSS * 0.1.  Then use a switch driven by NET-DRIVE to
 *              charge the circuit and discharge to ground through a High Resistance
 *              bleed resistor.   Then we cycle the pins between high and low as
 *              fast as we can with reasonable de-bounce and measure how many cycles
 *              can be accomplished in a defined time such as 1ms. It requires adding
 *              an analog comparator or opAmp with two circuits but the larger switch
 *              of VSS provides longer transition times that slower CPU can better deal
 *              with. This version requires accurate  time keeping.
 *
 *              Next step convert this to use the LPC804 on-board analog comparator
 *              rather than logic level transitions. Also see if we can duplicate
 *              the logic using the PLU rather than explicit looping in C.
 *
 *           ---------
 *           Readings
 *           ---------
 *            Please note after taking these readings I changed
 *            the algorithm to increase scale by 100 which allowed
 *            access to finer resolution of data at expense of greater
 *            jitter.  Please multiply all these numbers by 100 until
 *            until we update the measurements.
 *
 *            No 100 pf capacitor in circuit - 1
 *
 *            With 100pf capacitor in circuit - 27
 *
 *            Water bottle with + and - electrodes on
 *              electrodes on outside opposite side
 *              of 1 liter bottle. bottle
                Change from 0% to 70% = 103 - 35 = 68
                Average change per % of fluid change = 0.9814
                  count units

                due to changing shape of bottle and electrode
                the most accurate  approximation would be from
                10% full to 70% full.  103 - 49 = 54.
                54 units / 60% change = 0.9 count units per 1% water
                level change. Could use approximation between points to
                get more accurate estimation with variable shaped
                tanks.

 *              Empty bottle - 35
 *              Bottle with 10ml fluid - 38
 *              Bottle with 20ml fluid - 41
 *              Bottle with 100ml fluid - 49
 *              Bottle with 200ml Fluid - 58
 *              Bottle with 300ml Fluid - 68
 *              Bottle with 400ml fluid - 76
 *              Bottle with 500ml fluid - 86
 *              Bottle with 600ml fluid - 93
 *              Bottle with 700ml fluid - 103*
 *              Bottle 100% full - 127
 *              Human touch positive electrode full bottle - 775
 *              Human touch both electrodes full bottle - 1378
 *              Human touch positive electrode empty bottle - 532
 *              Human touch both positive and neg electrodes empty bottle - 1454
 *              0.047 uF capacitor instead of water bottle of - 24776
 *                 capacitor was 5% rated but 10 years old ceramic.
 *                 A change of 24776 -27 =  change of 24749 or
 *                 a change of 526574.46 per uf or 0.00000189906 uf per
 *                 count unit.  This converts to 1.89906 pF per count
 *                 unit.  A 5% variation in capacitor would yield
 *                 a range of 1.804 to 1.994013 pF per count unit.
 *
 *              0.01 uF capacitor instead of water bottle - 5664
 *                Capacitor was 5% rate but 10 year old ceramic
 *                a change of 5664 - 27 = 5637 or 563700 count units per
 *                uF or 0.00017739932 uF per count unit or 1.774 pF
 *                per count unit.   A 5% variation in capacitor
 *                would put this in the range of 1.6853pf to 1.8627 pF
 *                per count unit.
 *
 *              Using an average of our two reference capacitors
 *              yields  1.83 pF per count unit and we know our average
 *              per 1% change in water was 0.9 so we can determine
 *              that a 1% change in water level yields a 1.653pF
 *              change in capacitance.
 *
 *              Please Note these tests were ran with Debug mode
 *              compilation and ran without the debugger running.
 *
 *
 *          Application entry point.
 */
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "LPC804.h"
#include "fsl_debug_console.h"
//#undef PRINTDELAY
#define PRINTDELAY

#define posCntDeBounce 125
#define  negCntDeBounce 25
const int chargeFor = 25;
const int numReadPass = 150;
const int maxWaitCnt=1000000;

int readCap(int numRead, int chargeCycles) {
  volatile int totWait=0;
  volatile int waitedFor=0;
  volatile int ar;
  for (int pn=0; pn < numRead; pn++) {
     // Wait for capacitor to Charge
	 GPIO_PinWrite(PIN_p28_GPIO , PIN_p28_PORT, PIN_p28_PIN, 1);
     volatile short posCnt=0;
     volatile int xx = 0;
     while((xx < chargeCycles) || (posCnt < posCntDeBounce)) {
    	xx++;
		ar = GPIO_PinRead(PIN_ACIN_GPIO, PIN_ACIN_PORT,PIN_ACIN_PIN);
		if (ar == 1) {
			posCnt++;
		} else  {
			posCnt--;
		}
     }

	 waitedFor=0;
	 // Set our Drain Pin to drain mode drawing power off the
	 // capacitor until it crosses Logic-0 threshold.
	 GPIO_PinWrite(PIN_p28_GPIO , PIN_p28_PORT, PIN_p28_PIN, 0);
	 volatile short negCnt=0;
	 while((waitedFor < maxWaitCnt)) {
		waitedFor++;
		ar = GPIO_PinRead(PIN_ACIN_GPIO, PIN_ACIN_PORT,PIN_ACIN_PIN);
		if (ar == 0) {
			negCnt++;
			if (negCnt > negCntDeBounce) {
				break;
			}
		} else {
			negCnt--;
		}
	 }
	 totWait += waitedFor;
  }

  return (( totWait * 100) /  numRead) -  (negCntDeBounce * 100);
}

#ifdef PRINTDELAY
#define PRINTEVERY 50000
#else
#define PRINTEVERY 0
#endif

/*
 * @brief   Application entry point.
 */
int main(void) {

    /* Init board hardware. */
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
    /* Init FSL debug console. */
    BOARD_InitDebugConsole();
#endif


    PRINTF("LCP804 Capacitance Test\n");
    GPIO_PinWrite(PIN_LED_GPIO , PIN_LED_PORT, PIN_LED_PIN, 0);

	volatile int x=0;
    /* Enter an infinite loop, just incrementing a counter. */
    while(1) {
	   x++;
	   if (x > PRINTEVERY) {
		  x = 0;
		  GPIO_PinWrite(PIN_LED_GPIO , PIN_LED_PORT, PIN_LED_PIN, 1);
		  int capr = readCap(numReadPass, chargeFor);
		  #ifdef PRINTDELAY
		     PRINTF("%d\n", capr);
          #endif
		  GPIO_PinWrite(PIN_LED_GPIO , PIN_LED_PORT, PIN_LED_PIN, 0);

	   }
       /* 'Dummy' NOP to allow source level single stepping of
            tight while() loop */
        __asm volatile ("nop");
    }
    return 0 ;
}

 

 

 

 

After increasing scale of returned number from over sampling by a factor of 100 it largely solved my concerns about sensitivity and I can now see material reading increases as my hand approaches the sensor solenoid starting at about 6" away.   Still not as sensitive as what I am seeing out of 240Mhtz CPU but usable for a lot less power.



Tags (1)
0 Kudos
3 Replies

150 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Q1)What is process to get an example like this added to the examples in the SDK?

>>>>>>There is example in SDK, pls go to the directory:

C:\nxp\MCUXpressoIDE_11.8.0_1165;

open the MCUXPresso_IDE_UserGuide.pdf and check the Chapter 6 6. Importing Example Projects (from installed SDKs)

Q2)What is best way to learn to port this to use the PLU instead of explicit C Code?

>>>>>The PLU module function is the same as PLD or FPGA, which can implement the combination or sequential(has 4 D flip-flop) circuit, I do not think your application needs it.

Q3)What is the best process for sharing content like this with other LPC users?

>>>>>>>

Q4)Is it worth porting to use Analog comparator rather than gate logic transition threshold? What benefit will we likely gain?

>>>>I suppose that gate logic transition threshold is gate by gate, chip by chip, but the ACMP has fixed threshold.

Q5)Does anybody see a way to increase true resolution by a factor of 10 with clever circuit changes. This would allow either less jitter or less oversampling both of which could save power.

>>>>>>If the capacitance varies  1% with the full water level range, it is a difficult work.

Hope it can help you

BR

XiangJun Rong

0 Kudos

143 Views
joeatrainamp
Contributor II

Your answer for Q1 doesn't answer my question.   I want to know the process to submit content so it can be made available to other users as sample code when they download the SDK.

0 Kudos

99 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

At the time being, SDK is developed by NXP dedicated software team, there is not any channel for external user code to be embedded in SDK package.

If you have recommendation to add code for a general application field, you can submit request, I can submit it to SDK team.

Thanks

BR

XiangJun Rong

0 Kudos