Week 08 ~ input devices
Capacitive sensing
For my final project I wanto to make actuated velcro-like surfaces and it would be great if they had feedback about
how far they have actuated/whether they have grabbed onto another surface.
Capacitive sensing sounds like it makes sense - I could add an extra conductive layer (copper tape) to the
material and measure the change in capacitance as the surface is folded or as another surface approaches. I also got reminded of this
research paper on integrating capacitive sensing into 3D printed metamaterials.
It looks like there are a range of analog approaches to capacitive sensing, although the simplest approach using a microcontroller seems to be an RC circuit
where you measure the time it takes for a circuit to respond to an input voltage, via the time constant t = RC. This can be done via two pins
(one for sending the pulse, the other for reading the response of the circuit).
Test weith two surfaces (video).
#include
CapacitiveSensor cs_4_2 = CapacitiveSensor(4,2); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
// Variables
float reading = 0;
float tare = 0;
// Variables for Averaging
const int totalSamples = 10;
int index_avg = 0;
int value = 0;
float sum = 0;
int readings[totalSamples]; // create an empty array of size totalSamples
// Variables for Low Pass
float filteredOutputPrevious = 0;
const float RC = 0.100;
const float dT = 0.01; // time in seconds
const float C1 = dT/(RC+dT); // coefficient 1
const float C2 = RC/(RC+dT); // coefficient 2
float capsensor_output;
void setup()
{
cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF); // turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
long total1 = cs_4_2.capacitiveSensor(30);
Serial.print(millis() - start); // check on performance in milliseconds
Serial.print("\t"); // tab character for debug windown spacing
capsensor_output = total1;
// Serial.println(total1); // print sensor output 1
//delay(10); // arbitrary delay to limit data to serial port
//float filtered_reading = batchAverageRead() - tare; // Batch average reading
//float filtered_reading = movingAverageRead() - tare; // Moving average read
float filtered_reading = lowPassRead() - tare; // Low pass read
Serial.println(filtered_reading); // send our reading over USB to the computer
delay(dT*1000); // delay between reads in miliseconds (necessary for low pass)
}
// Batch Averaged sensor reading ----------------------------------------------------
float batchAverageRead(){
sum = 0;
for (int i = 0; i < totalSamples; i++){
sum = sum + capsensor_output; // sum totalSamples readings
delay(dT*1000); // wait for every reading! This is bad :(
}
return sum / totalSamples;
}
// Moving Average sensor reading ----------------------------------------------------
float movingAverageRead(){
sum = sum - readings[index_avg]; // Remove the oldest entry from the sum
value = capsensor_output; // Read the next sensor value
readings[index_avg] = value; // Add the newest reading to the window
sum = sum + value; // Add the newest reading to the sum
index_avg = (index_avg+1)%totalSamples; // Increment the index, and wrap to 0 if it exceeds the window size
return sum/(float(totalSamples)); // Divide the sum of the window by the window size for the result
}
// Low Pass Filter sensor reading -------------------------------------------------
float lowPassRead(){
float filteredOutput = capsensor_output*(C1) + filteredOutputPrevious*(C2); // All we need to do here is to measure once and do some fast multiplication with our coefficients! This is great :)
filteredOutputPrevious = filteredOutput; // And store our output for next time
return filteredOutput;
}