Dear all,
I have some issue with capacitive sensor.
I made a capacitive sensor using a capacitive sensing library (Arduino Playground - CapacitiveSensor). I also implemented a SD card module so that I can store data without a laptop (SD - Arduino Reference). The purpose of this sensor is to measure/count mouse licking behavior.
It worked well during my test, where I powered my arduino with an 1000mA 12V AC/DC power adapter. Normally, mouse licks to drink at a rate of ~10 times/second. Sensor values nicely oscillated quickly when a mouse was licking.
To make the sensor portable, I connected it with 2 x 3.7V batteries. The sensor seemed to work fine with my finger touch. However, during my "real-experiment-like" test, I observed weird measurements: Sometimes, the sensor values were high all the time, even though mouse licked multiple times (within a short time window). Sometimes, the values looked good as expected.
I wished to upload figures, but I am not allowed because I am a new user.
Yes! The below is my code. Several things are mixed so my code is not neat (e.g. sd writing/file naming, LED, push button, and dual capacitive sensors). Yet, I hope things make sense.
#include <SPI.h> // library for sd
#include <SD.h> // library for sd
#include <CapacitiveSensor.h> // library for capacitive sensor
// Define variables
File myFile; // Variable to a file.
long i = 0; // it counts up the number of cycles.
long cycles = 432000 //10ms 24hr: 8640000; //how many readings? With `waittime = 25`, "576000 => 4-hour run"
int waittime = 25; //wait time in "milliseconds" for each loop. [Total time = `cycles` x `waittime`] e.g. cycle = 400; waittime = 50; then it is 20-second recording.
int timeoutDelay = waittime;
String fn = "AR01"; //variables for filename
String newfn = fn; //variables for filename
char ind[50]; //variables for filename
int k = 1; //variables for filename
int buttonInputPin = 2; // receiver pin from button press
int switchState = 0; //stores button state
CapacitiveSensor sensor1 = CapacitiveSensor(6,7); //(the port connected to the sensor, receipiant port) (red)
CapacitiveSensor sensor2 = CapacitiveSensor(9,8); //(the port connected to the sensor, receipiant port) (green)
long mm; //will store total run time.
int ledpin = 10; // LED pin; it is PWM pin so that we can use analogWrite.
int ledpower = 50; // between 0 - 255. LED power when recording
void setup()
{
// LED light
pinMode(ledpin, OUTPUT);
//button setup
pinMode(buttonInputPin, INPUT);
// Open serial communication and wait for port to open;
Serial.begin(9600);
// while (!Serial) { ////////// This will be deleted when battery is used.
// ; //wait for serial port to connect. Needed for native USB port only
// }
//
// initialize SD card
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization faild!");
while (1);
}
Serial.println("initialization done.");
// Update filename if the same filename exists
while (SD.exists(newfn+".csv")) {
sprintf(ind, "_%03d", k);
newfn = fn+String(ind);
//newfn = fn+k;
k=k+1;
}
fn = newfn + ".csv";
Serial.println(fn);
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
myFile = SD.open(fn, FILE_WRITE);
// Write data information in the first row.
if (myFile) { // In the sd card, the first row will show the number of cycles and the wait time (or time per cycle).
Serial.print("Writing to ");
Serial.print(fn);
Serial.println("...");
Serial.print(cycles);
Serial.print("\t");
Serial.println(waittime);
myFile.print("cycles:");
myFile.print(cycles);
myFile.print("\t");
myFile.print("waittime:");
myFile.println(waittime); //This is to mark the start of the recording.
}
// Initialize capacitive sensor
// Disable the automatic re-calibration feature of the
// capacitive sensor library
sensor1.set_CS_AutocaL_Millis(0xFFFFFFFF);
sensor2.set_CS_AutocaL_Millis(0xFFFFFFFF);
// Set up time out so that each recording is not longer than `timeoutDelay`.
// If time is delayed more than `timeoutDelay`, the value will become -2
sensor1.set_CS_Timeout_Millis(timeoutDelay);
sensor2.set_CS_Timeout_Millis(timeoutDelay);
mm = millis(); // It will be used at the end to calculate the total run time.
}
void loop()
{
long current_millis = millis();
long capacitance1 = sensor1.capacitiveSensor(30); // 30 samples
long capacitance2 = sensor2.capacitiveSensor(30);
// Print the result of the sensor reading
// Note that the capacitance value is an arbitrary number
// See: https://playground.arduino.cc/Main/CapacitiveSensor/ for details
switchState = digitalRead(buttonInputPin);
if (myFile) {
if (switchState == 0 && i <= cycles){// Note `i <= cycles`. Somehow the first recording is always 0, so do not use the first recording; and record one more time.
Serial.print(capacitance1); // display in the window
Serial.print("\t");
Serial.println(capacitance2);
myFile.print(capacitance1); //store in the sd card
myFile.print("\t");
myFile.println(capacitance2);
i = i+1;
analogWrite(ledpin, ledpower); //value should be in between 0 and 255. LED brightness might not be linear. With 10K ohm, `50` shows dimm LED.
}
else if (switchState == 0 && i > cycles) { //Stop recording by the end of "cycle".
myFile.close();
Serial.println("Recording done.");
Serial.println(mm - current_millis); // Print total run time.
analogWrite(ledpin, 0);
while (1);
}
else { //Stop recording by button press.
myFile.close();
Serial.println("Button pressed.");
Serial.println("Done.");
analogWrite(ledpin, 0);
while (1);
}
} else { // if the file didn't open, print an error:
Serial.print("error opening "+fn);
while (1);
}
// Wait for `waittime` milliseconds
while(millis() - current_millis < waittime);
}
The grounding of the Arduino board is very important in capacitive sensing. The board needs to have some connection to ground, even if this is not a low-impedance path such as a wire attached to a water pipe.
Capacitive sensing has some quirks with laptops unconnected to mains power. The laptop itself tends to become sensitive and bringing a hand near the laptop will change the returned values.
Connecting the charging cord to the laptop will usually be enough to get things working correctly. Connecting the Arduino ground to an earth ground (for example, a water pipe) could be another solution.
Another solution that seems to have worked well on at least one installation, is to run a foil ground plane under the sensor foil (insulated by plastic, paper, etc.), and connected by a wire to ground. This worked really well to stabilize sensor values and also seemed to dramatically increase sensor sensitivity.
Yes, I saw the comments, but I wasn't sure how to.
There, one solution is to connect arduino ground to the earth ground. Does it mean to connect the arduino GND pin to the earth ground? Any caution? Would you think it solves the issue I have?
While waiting other thoughts, I will try grounding later today and update the results here.