Gordy_website_02.jpg  Colleen_website_02.jpg   MENU.jpgMenu_Icon_03.jpgABOUT US.jpgOUR LOCATION.jpgClock_IMG_20151023_211824096_HDR_C_1_02.jpg PIR_20190702_144702_02.jpg TV_IMG_3118_03.jpg Gardena_R80Li_pic_02.jpg Electric_Fence_Energiser_02_IMG_0079.jpg Seeed XIAO 05.jpg Great Cow 02.jpg ConcreteCMS_Logo_02.jpg                                           

Capacitive Level Sensing

Key words: Capsense CPS Touch Sensing Capacitive Level Sensing PIC12F1840 Microchip GCBasic Compiler GCStudio PICKit 2 Serial Debug

My project started with this spec for a fuel level teaching aid:

Is it possible to make a buzzer circuit, perhaps with a 9v battery... some sort of basic resonance that uses a coil and capacitor?

But to replace the capacitor with two parallel wires or two strips of 5mm x 100mm stainless steel a few millimetres apart... then dip the wires/strips/plates into a glass of water and listen for the frequency go up and down as the plates go further into the water, etc?

The reason I ask, is that the fuel quantity measuring systems in big aircraft and the ones here use a capacitance system.

I'd just like the students to hear the buzzer frequency change as I dip two plates into water.

22 September 2025

So - in for a challenge - maybe the spec writer had a spur of the moment idea and hadn't given any thought to electrical water losses, low Q resonant circuits and frequency translation from measurement to audible output.

Microchip PIC12F1840 microcontroller to the rescue - my favourite chip which I have used in many projects.

Software created with GCBasic Compiler.

I was a little dissappointed that GCBasic did not have an instruction or command  to access the Capacitive Sensing built into this chip.

So, I decided to write my own code.

 

Prototype PCB:

03.jpg

 

Plate assembly:

Assembly with 3 aluminium plates 120 x 20mm with spacing 6mm.

Centre plate is covered with clear heat shrink sleeving to insulate it from

water used in the demo. The outer plates provide some measure of shielding

from external influences. Plates gave a capacitance of approx 200pF when

immersed in water to 100mm and gave a measured count of 40,000.

Calculated capacitance was 427pF with the plates immersed in water

to 100mm. Reduced measured results were likely because one plate

was covered in heat shrink sleeving.

Plates in air gave a measured count of approx 6000.

04.jpg

05.jpg

01 Cap Sense Block diagram.jpg

Schematic:

02 Schem 0304.jpg

Programmer:

A PICkit 2 was used to program and debug the code as it provided serial output for monitoring data.

Trying to use a later model PICkit with GC Studio and MPLab 6.25 wasted 3 days.

06.jpg

 

Test Capacitors:

After initial tests with water, several test cables were made using RG178 coax to provide capacitors.

RG178 has a capacitance of approximately 100pF per metre.
A 2m cable was made to represent the plates immersed in water to 100mm

07.jpg

 

The test code:

;Chip Settings
#chip 12F1840,4
#config OSC=INTOSC, CLKOUTEN=OFF, MCLRE=OFF, WDTE=OFF, BOREN=OFF
#option Explicit
'
' Capsens PIC12LF1840
' Capsens PIC12F1840 05 GCB Project
' 19 September 2025
'
' To use PIC12F1840 timers
' Use TMR0 to count CPSCLKs
' Use TMR1 to count Fosc/4 clocks
' Use TMR0 overflow for gate control of the number Fosc/4 counts
'
' Therefore:
' with low CPSCLK speed (higher capacitance) more Fosc/4 counts will be accumulated in TMR1
' with high CPSCLK speed (lower capacitance) a smaller number of Fosc/4 counts will be accumulated in TMR1
'
' Further:
' Timer0 provides a variable time based on the number of CPSCLKs received and so gates varying numbers of Fosc/4 counts into Timer1.
' Lower capacitance - shorter gate time - fewer counts in Timer1
' Higher capacitance - longer gate time - larger number of counts in Timer1
' Low capacitance - low number of counts in Timer1
' High capacitance - high number of counts in Timer1
'
'
;Defines (Constants)    UART in PICKIT 2 used for debugging
'
#define USART_BAUD_RATE 9600
#define USART_TX_BLOCKING
'
;Variables
Dim acount As byte
Dim bcount As byte
Dim ccount As byte
Dim bitcount As byte
Dim tempword As word
Dim bytecount As byte
DIM tempL as byte
DIM tempH as byte
DIM TMR1value as Word
'
' RA0
' RA1
' RA2
' RA3 LED and SKR output
' RA4 Capsens input CPS3
' RA5
'
'==== Main routine =====================================================
'
Start:
'
' All bits input
dir porta in
dir porta.2 out
'
' flash LED on startup
for acount = 1 to 10
  set porta.2 1
  wait 100 ms
  set porta.2 0
  wait 100 ms
next
'
wait 100 ms
'
CPSsetup
getTMR1value
'
' do some debugging checks
'
HserPrint "tempH "
HserPrint tempH
HserPrint "    tempL "
HserPrint tempL
HserPrint "    TMR1value "
HserPrint TMR1value
HserPrintCRLF
'
wait 100 ms
'
goto Start
'
' ==== End of Main routine ==============================================
'
'==== Subroutines ============================================
'
sub CPSsetup
'
TRISA =   0b00111011      ' pin RA2 output, pin RA4 to input.
ANSELA  = 0b00010000      ' CPS3 input to pin RA4
CM1CON1 = 0b00000000      ' Disable all comparator interrupts
'
CPSCON0 = 0b00000101      ' bit7 CPS disabled=0, bit6 CPSRM Fixed VRef=0, bit 54 xx, bit32 Osc Low current 01, bit1 CPSOut status, bit 0 TMR0CS clock source is CPSCLK = 1
CPSCON1 = 0b00000011      ' CPS3 - input on pin RA4
'
INTCON =  0b00000000      ' clear all interrupts
OPTION_REG = 0b11100001   ' All weak pullups disabled, Int Edge rising, TMR0CS T0CK1, TMR0SE T0CKI pin 0, PSA prescaler assigned = 0, TMR0 prescaler = 001 = 4
T1CON =   0b00110000      ' TMR1CS CLK source Fosc/4, T1CKPS Prescale 1:8, T1OSCEN 0, -T!SYNC 0, x, TMR1ON 0
T1GCON =  0b10000001      ' TMR1ON gate on=1, T1GPOL low=0, T1GTM Gate Cntrl disabled=0, T1GSPM single pulse disabled=0, T1GGO/-done Status 0, T1GVAL State bit, T1GSS TMR0 overflow=01
'
end sub
'
'============================================================
'
sub getTMR1value
'
tempH = 0
tempL = 0
TMR1value = 0
'
' disable TMR1
T1CON.TMR1ON = 0
' disable TMR0
CPSCON0.CPSON=0
'
' clear TMR1
TMR1H=0
TMR1L=0
' clear TMR0
TMR0=0
'
'clear TMR0IF
INTCON.TMR0IF =0
'
'''''''''''''''''''''''''''''''''''''''''''
'
' enable TMR1
T1CON.TMR1ON = 1
' enable TMR0
CPSCON0.CPSON=1
'
' wait for TMR0 overflow
Do until INTCON.TMR0IF=1
Loop
'
' disable TMR1
T1CON.TMR1ON = 0
' disable TMR0
CPSCON0.CPSON = 0
'
' get TMR1L
' get TMR1H
'
tempL=TMR1L
tempH=TMR1H
'
TMR1value_H = tempH
TMR1value = TMR1value + tempL
'
end sub
'

========================================================================================

 

23 September 2025

I carried out some sweeping frequency speaker tests, from 400Hz to 4kHz. Dissapointed - all complicated by square wave drive, harmonics and large changing speaker amplitude resonse at different frequencies.

Next I measured the time taken to make a Capsens measurement. High level 328ms. Low level 53ms. Quite a big gap in trying to produce a contiuous audible tone. The PIC12F1840 ties up the only timers in making the Capsens measurement - No timers available to make a continuous tone.

Next I tried a chirp audible output. A 1kHz 10ms pulse between every Capsens measurement. Good result.

https://www.youtube.com/shorts/hrb1BR12v60

See on Youtube:

Video snap 01.jpg

 

Next - I am waiting for a JDY-23 Bluetooth module to arrive so that I can send data to a phone and make a bargraph display.