Hello to all! I've been experimenting lately with capacitive sensing for triggering mp3s and for midi control.
I have used a few different libraries for this but have found them unreliable due to hardware and earthing issues. However, the ADCTouchSensor.h library works very well and doesn't require hardware, resistors etc and only needs a single analog pin!
The issue I face now is the need for more inputs so I've turned to using the 74HC4067 multiplexer as I have a bunch of them already.
Firstly, is it possible to use a multiplexer in this way?
The code I want to adapt uses arrays for connected sensors and midi notes to be played accordingly.
This sketch is from the Arduino IDE, CapacitivePiano
#include <ADCTouchSensor.h>
#define USB_MIDI
#include <USBMIDI.h> // https://github.com/arpruss/USBHID_stm32f1
//
// On the stm32f1, this requires this branch of the stm32f1 core: https://github.com/arpruss/Arduino_STM32/tree/addMidiHID
//
#ifdef ADCTOUCH_INTERNAL_GROUNDING
# define GROUNDED_PIN -1
#endif
#ifdef ARDUINO_ARCH_AVR
# define SLOW_SAMPLING
# undef FAST_SAMPLING
# undef MEDIUM_SAMPLING
// slow mode: 9 ms per scan of 8 buttons
// medium mode: 5 ms per scan of 8 buttons
// fast mode: 2 ms per scan of 8 buttons
#define LED_OFF 0
#if defined(PIN_A7)
int pins[] = {A0,A1,A2,A3,A4,A5,A6,A7};
#else
int pins[] = {A0,A1,A2,A3,A4,A5};
#endif
#else // STM32F1
#define LED_BUILTIN PB12 // adjust to your board
#define LED_OFF 1
int pins[] = {PA0,PA1,PA2,PA3,PA4,PA5,PA6,PA7};
#ifndef ADCTOUCH_INTERNAL_GROUNDING
# define ADCTOUCH_INTERNAL_GROUNDING PA8
#endif
#endif
// C D E F G A B C C# D# F# G# A#
const uint8_t notes[] = {60, 62, 64, 65, 67, 69, 71, 72, 61, 63, 66, 68, 70};
const int numPins = sizeof(pins)/sizeof(*pins);
const uint8_t NOTE_ON = 0b10010000;
const uint8_t NOTE_OFF = 0b10000000;
int ref[numPins];
uint8_t prev[numPins];
ADCTouchSensor* sensors[numPins];
void setup()
{
#if defined(ARDUINO_ARCH_AVR)
// default: divide clock by 128
#ifdef FAST_SAMPLING
ADCSRA = (ADCSRA & ~0b111) | 0b100; // divide clock by 16
#else
#ifdef MEDIUM_SAMPLING
ADCSRA = (ADCSRA & ~0b111) | 0b110; // divide clock by 64
#endif
#endif
#endif
#ifndef USB_MIDI
Serial.begin(115200);
#else
USBMIDI.begin();
#endif
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, 1^LED_OFF);
for (int i=0; i<numPins; i++) {
sensors[i] = new ADCTouchSensor(pins[i]);
sensors[i]->begin();
prev[i] = 0;
}
digitalWrite(LED_BUILTIN, 0^LED_OFF);
// uint32_t t = micros();
// ADCTouch.read(A0, 10000);
// t = micros() -t;
// Serial.println(t);
}
void midiNote(uint8_t status, uint8_t note, uint8_t velocity) {
#ifdef USB_MIDI
if (status == NOTE_ON)
USBMIDI.sendNoteOn(0, note, velocity);
else if (status == NOTE_OFF)
USBMIDI.sendNoteOff(0, note, velocity);
#else
Serial.write(status);
Serial.write(note);
Serial.write(velocity);
#endif
}
void loop()
{
uint8_t pressed = 0;
for (int i=0; i<numPins; i++) {
if (sensors[i]->read() > 25) {
pressed = 1;
if(!prev[i]) {
midiNote(NOTE_ON, notes[i], 127);
prev[i] = 1;
}
}
else {
if(prev[i]) {
midiNote(NOTE_OFF, notes[i], 127);
prev[i] = 0;
}
}
}
digitalWrite(LED_BUILTIN, pressed^LED_OFF);
}
And this is the code I have for using the multiplexer
/**
* This example demonstrates how to read analog signals
* It assumes there are potentiometers connected
* to the 16 channels of the 74HC4067 mux/demux
*
* For more about the interface of the library go to
* https://github.com/pAIgn10/MUX74HC4067
*/
#include "MUX74HC4067.h"
// Creates a MUX74HC4067 instance
// 1st argument is the Arduino PIN to which the EN pin connects
// 2nd-5th arguments are the Arduino PINs to which the S0-S3 pins connect
MUX74HC4067 mux(7, 8, 9, 10, 11);
void setup()
{
Serial.begin(9600); // Initializes serial port
// Waits for serial port to connect. Needed for Leonardo only
while ( !Serial ) ;
// Configures how the SIG pin will be interfaced
// e.g. The SIG pin connects to PIN A0 on the Arduino,
// and PIN A0 is a analog input
mux.signalPin(A0, INPUT, ANALOG);
}
// Reads the 16 channels and reports on the serial monitor
// the corresponding value read by the A/D converter
void loop()
{
int data;
for (byte i = 0; i < 16; ++i)
{
// Reads from channel i. Returns a value from 0 to 1023
data = mux.read(i);
Serial.print("Potentiometer at channel ");
Serial.print(i);
Serial.print(" is at ");
Serial.print((double)(data) * 100 / 1023);
Serial.println("%%");
}
Serial.println();
delay(1500);
}
I have tried a few things to incorporate the multiplexer code with the Capacitive piano code but the issue seems to be how to read the same analog input for sensing as well as multiplexing. Very confused but hope someone can throw a few ideas my way!
Thanks ![]()