Hi there
I have written some code based on 'capsense' which I am using to check the water levels in an aquaculture system. My sensor consists of a length of aluminium tube with two long plastic-laminated aluminium foil 'sensors' fixed to the tube with contact adhesive. It works like a charm! I think the aluminium tube effectively creates two capacitors in serial, with a total value of about 200 pF at 'half-tide' as it were. This is connected to the MCU by 10 meters of shielded stereo cable - one core attached to each 'sensor', one core to pin 9, a 1 M resistor between 8 & 9. the other sensor lead goes to ground, and the coax shielding attached to the 5V power pin to minimise interference. Note the coax shielding is not attached to anything at the sensor end. This works very well, although I cannot use my scope to check for interference and waveforms as the impedance of the scope is too low and stops the output from the sketch. Would it help to use an LM358 as a voltage follower and read the scope from the output of one or both opamps?
You can test out the sketch by using small fixed capacitors between pin 9 and ground and changing the 'smin' and 'smax' values. There is a linear relationship between capacitance value and the mapped output.
The code is quite short, but I have complicated the situation by using a while loop to 'settle' the output. This is because I don't really understand the
fout = (fval * (float) readup )+ ((1-fval)* accum); line, which is a smoothing filter. It seems I might be creating a more complicated sketch than I need to, to do the job.
Note that water level sensors do not generally need fast response - seconds, not millis.
As I have noted in //comments a sample could be taken by using an external RTC to trigger an interrupt. This is because the MCU will need to monitor several depth sensors (at intervals), as well as control valves and monitor flow and temperature. There seem to be be enough inputs and outputs to do all this, but distributing processor time looks like the major problem to me.
One thing at a time, however. Any comments or ideas on the sketch itself, or about processor control in this context would be much appreciated.
This is the sketch:
//derived from CapSense.pde // Paul Badger 2007 //see my file pbtemp.cpp for PB commentary
//JB 2010
int mappedval;
float accum, fout, fval = .03;
void setup()
{
// DDRB=B101; see temp.cpp for exp
pinMode(8, OUTPUT); // output pin
pinMode(9, INPUT); // input pin
Serial.begin(9600);
}
void loop(){
//every so often
settler();
// do other tasks
// and others
delay(100); // For the demo. but use interrupts
// and RTC for tasks instead of calling delay
}
void settler() {
boolean counted = false;
int cnt = 0, temp = 0;
Serial.println("settling ...");
while (!counted)
{
senselevel();
temp = mappedval;
if (temp == mappedval) {
cnt += 1;
if (cnt > 666) { //we have a stable value
counted = true;
}
}
}
counted = false;
Serial.println(fout); //for calibration
Serial.println(mappedval);
}
void senselevel()
{
unsigned int readdown = 0, readup = 0 ; //higher values when deeper
long smin = 5200, smax = 6600;
// the fast stuff
for (int i=0; i < 4 ; i++ ){
PORTB = PORTB | 1;
while ((PINB & B10) != B10) {
readup ++;
}
PORTB = PORTB & 0xFE;
while((PINB & B10) != 0 ){
readdown ++;
}
}
fout = (fval * (float) readup )+ ((1-fval)* accum);
accum = fout;
mappedval = map((long) fout, smin, smax, 0, 20);
} //end senselevel