I'm making a synthesizer using copper strips as capacitive touch sensors for the input with the arduino mega. I made a quick circuit (following this tutorial) and loaded the following code into my mega:
#include <CapacitiveSensor.h>
/*
* CapitiveSense Library Demo Sketch
* Paul Badger 2008
* Uses a high value resistor e.g. 10M between send pin and receive pin
* Resistor effects sensitivity, experiment with values, 50K - 50M. Larger resistor values yield larger sensor values.
* Receive pin is the sensor pin - try different amounts of foil/metal on this pin
*/
CapacitiveSensor q1 = CapacitiveSensor(22,26); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapacitiveSensor q2 = CapacitiveSensor(22,30); // 10M resistor between pins 4 & 6, pin 6 is sensor pin, add a wire and or foil
CapacitiveSensor q3 = CapacitiveSensor(22,34); // 10M resistor between pins 4 & 8, pin 8 is sensor pin, add a wire and or foil
void setup()
{
// turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
long t1 = q1.capacitiveSensor(30);
long t2 = q2.capacitiveSensor(30);
long t3 = q3.capacitiveSensor(30);
Serial.print(t1);
Serial.print("\t");
Serial.print(t2);
Serial.print("\t");
Serial.print(t3);
Serial.print("\t");
if (t1 > 200) {
Serial.println("A");
}
else if (t2 > 200) {
Serial.println("B");
}
else if (t3 > 200) {
Serial.println("C");
}
else {
Serial.println("NONE");
}
delay(10); // arbitrary delay to limit data to serial port
}
The code is an example program from the capsense library that I made a few changes to. All it does is monitor three sensors and print out the either "A", "B", "C", or "NONE", depending on which sensor is currently being touched (I plan to use this code to play different notes depending on which key is being pressed, but for now it's just a proof of concept).
The only problem happens when I touch 2 or more sensors at the same time. I'd like to make it so that the arduino prints the letter corresponding to whichever key was pressed more recently. For instance, if you touch key A with your index finger, the arduino should print out "A". If you then press key B with your middle finger but forget to take your index finger off the A key, the arduino should update and print out "B". This is important because my synth will only be able to play one note at once, so if you're playing a song and accidentally press one key while still holding down another, the synth won't be playing the note you want it to.
Basically, in the event that two keys are pressed at once, is there any way for the arduino to remember which one was pressed first? I've been looking online for hours and still haven't found anything useful.
When a switch is pressed, put that switch identifier in a variable.
When the second switch is pressed, put that identifier in the same variable.
Hence, the variable contains the latest switch data.
Your code is not losing the state of the inputs, your print statements just stop showing you those states after the first one. Drop the nested ifs.
#include <CapacitiveSensor.h>
/*
* CapitiveSense Library Demo Sketch
* Paul Badger 2008
* Uses a high value resistor e.g. 10M between send pin and receive pin
* Resistor effects sensitivity, experiment with values, 50K - 50M. Larger resistor values yield larger sensor values.
* Receive pin is the sensor pin - try different amounts of foil/metal on this pin
*/
CapacitiveSensor q1 = CapacitiveSensor(22,26); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapacitiveSensor q2 = CapacitiveSensor(22,30); // 10M resistor between pins 4 & 6, pin 6 is sensor pin, add a wire and or foil
CapacitiveSensor q3 = CapacitiveSensor(22,34); // 10M resistor between pins 4 & 8, pin 8 is sensor pin, add a wire and or foil
void setup()
{
// turn off autocalibrate on channel 1 - just as an example
Serial.begin(9600);
}
void loop()
{
long start = millis();
long t1 = q1.capacitiveSensor(30);
long t2 = q2.capacitiveSensor(30);
long t3 = q3.capacitiveSensor(30);
Serial.print(t1);
Serial.print("\t");
Serial.print(t2);
Serial.print("\t");
Serial.print(t3);
Serial.print("\t");
if (t1 > 200) {
Serial.print("A\t");
}
if (t2 > 200) {
Serial.print("B\t");
}
if (t3 > 200) {
Serial.print("C");
}
Serial.println();
delay(10); // arbitrary delay to limit data to serial port
}
wzaggle:
Your code is not losing the state of the inputs, your print statements just stop showing you those states after the first one. Drop the nested ifs.
Sorry, my post wasn't very clear. From what I understand, your code would print the values of all the activated sensors at once. What I need it to do is keep track of the order in which the sensors are touched so that, in the event that two or more sensors are being touched at the same time, the arduino only prints the value of whichever key was pressed last.
Either that or it would have to only keep track of state changes so that, when a new key is pressed, the arduino ignores the input from any keys which were pressed before. This way, it would only print the value of the most recently pressed key and not the values of the keys which were already on before.
Either that or it would have to only keep track of state changes so that, when a new key is pressed, the arduino ignores the input from any keys which were pressed before. This way, it would only print the value of the most recently pressed key and not the values of the keys which were already on before.
wzaggle:
I think you answered your own question....
Is there a way to do that? I'm really new to coding so if there's a tutorial you can link to that talks about how to track changes in state that'd be really helpful.
Of course there is a way... This short example will only go back to one previously "held" touch point. More and you would need to turn the last touch history (plastTouch) into an array acting as a LIFO stack.
Sampling, tracking and managing "states" of different things and applying logic to those states in order to adjust the "states" of other things is a big part of what these small processors do best. It is a good thing to be able to understand.
You basically just have "touch" buttons. You could have used any push button.
Thanks! I wrote a version of the code, here it is if anyone wants to reference it:
#include <CapacitiveSensor.h>
CapacitiveSensor q1 = CapacitiveSensor(22,26);
CapacitiveSensor q2 = CapacitiveSensor(22,30);
CapacitiveSensor q3 = CapacitiveSensor(22,34);
const int tOn = 130;
int keySt8[3]{0,0,0};
int lastkeySt8[3]{0,0,0};
int noetSet[6]{0,0,0,0,0,0};
void setup()
{
Serial.begin(9600);
}
void loop()
{
long start = millis();
long keyTime[3]{q1.capacitiveSensor(30),q2.capacitiveSensor(30),q3.capacitiveSensor(30)};
for(int i = 0; i < 3; i++){
if (keyTime[i] > tOn){
lastkeySt8[i] = keySt8[i];
keySt8[i] = 1;
}
else {
lastkeySt8[i] = keySt8[i];
keySt8[i] = 0;
}
if (keySt8[i] != lastkeySt8[i] && keySt8[i] == 1){
for(int j = 3; j >= 0; j--){
noetSet[(j + 1)] = noetSet[j];
}
noetSet[0] = (i + 1);
}
if (keySt8[i] != lastkeySt8[i] && keySt8[i] == 0 && noetSet[0] == (i + 1)){
for(int j = 0; j <= 4; j++){
noetSet[j] = noetSet[(j + 1)];
}
}
if (keySt8[0] == 0 && keySt8[1] == 0 && keySt8[2] == 0){
noetSet[0] = 0;
}
Serial.print(keyTime[i]);
Serial.print("\t");
}
for(int i = 0; i <= 4; i++){
Serial.print(noetSet[i]);
Serial.print("\t");
}
Serial.println();
delay(10);
}
The main difference is that this version uses for loops instead of conditionals, that way I can add more keys without having to change it too much. Also, it prints out numbers instead of letters.
And yeah, they're basically just acting as switches. I just like touch sensors better since the push buttons I have are super finicky and would be a pain in the ass to play with. Plus, the class I'm doing this for offers extra credit for every sensor we incorporate and push buttons don't count as sensors.