Difference between revisions of "Touch Board"
(12 intermediate revisions by 2 users not shown) | |||
Line 23: | Line 23: | ||
* [https://www.youtube.com/watch?v=uS_EIPG1Q6M The bare board] | * [https://www.youtube.com/watch?v=uS_EIPG1Q6M The bare board] | ||
* [https://www.youtube.com/watch?v=a5QXYZj0wGc Interactive sound wall] | * [https://www.youtube.com/watch?v=a5QXYZj0wGc Interactive sound wall] | ||
+ | * Touchboard holder:[[https://interactionstation.wdka.hro.nl/wiki/File:Cut-touchboard.zip]] | ||
=Use the Touch Board to play sounds= | =Use the Touch Board to play sounds= | ||
Line 177: | Line 178: | ||
*Digital Pins 5,6,7,8,9 (only if you are not using the MP3 function) | *Digital Pins 5,6,7,8,9 (only if you are not using the MP3 function) | ||
==Adding an extra capacitive sensor== | ==Adding an extra capacitive sensor== | ||
− | Sometimes you want to use the same TouchBoard functionalities but add a couple of sensors. To do so you can add and program external capacitive sensors. | + | Sometimes you want to use the same TouchBoard functionalities but add a couple of sensors. To do so you can add and program external capacitive sensors. <br> |
− | You can follow [https://www.bareconductive.com/blogs/resources/make-a-basic-capacitive-sensor-with-electric-paint-and-arduino?srsltid=AfmBOoonCrtXdl4H0WSuAYeuSYUIlz1rfkKDb2qsZFdfGwGpJY0BfPTZ this guide] to add extra capacitive sensors. | + | You can follow [https://www.bareconductive.com/blogs/resources/make-a-basic-capacitive-sensor-with-electric-paint-and-arduino?srsltid=AfmBOoonCrtXdl4H0WSuAYeuSYUIlz1rfkKDb2qsZFdfGwGpJY0BfPTZ this guide] to add extra capacitive sensors.<br> |
− | + | [[File:Bradboardcapacitive.jpg | 400 px]]<br> | |
− | + | <div style="font-family:monospace;color:blue;"> | |
− | ===Read sensors and link it to a key press== | + | Wiring:<br> |
+ | For one sensor you will need:<br> | ||
+ | Breadboard<br> | ||
+ | 3x Jumper wires<br> | ||
+ | 1x 1M ohm resistor<br> | ||
+ | <br> | ||
+ | 1. Look for two Digital Pins of the TouchBoard that are available to use (see the TouchBoard Pins image above)<br> | ||
+ | 2. Connect each Pin to two separate rows on the breadboard using two Jumper wires<br> | ||
+ | 3. Place a 1M ohm resistor in between the two <br> | ||
+ | 4. Add a Jumper wire on the second pin end: this is going to be your sensor. You can later connect it to a touching pad or similar. | ||
+ | </div> | ||
+ | [[File:TBandextrasensors.jpg | 400 px]]<br> | ||
+ | ===Read sensors and link it to a key press=== | ||
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
#include <CapacitiveSensor.h> | #include <CapacitiveSensor.h> | ||
Line 216: | Line 229: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | ===Add the new keys to the other 12=== | ||
+ | Let's add our new keys to the HID_KEYBOARD sketch: | ||
+ | <syntaxhighlight lang="c"> | ||
+ | //CAPACITIVE SENSORS using 10-11 and 12-13 pins | ||
+ | //check wiring here https://www.bareconductive.com/blogs/resources/make-a-basic-capacitive-sensor-with-electric-paint-and-arduino?srsltid=AfmBOoonCrtXdl4H0WSuAYeuSYUIlz1rfkKDb2qsZFdfGwGpJY0BfPTZ | ||
+ | //**************************** | ||
+ | #include <CapacitiveSensor.h> | ||
+ | CapacitiveSensor cs_10_11 = CapacitiveSensor(10, 11); // sensor1 | ||
+ | CapacitiveSensor cs_12_13 = CapacitiveSensor(12, 13); // sensor2 | ||
+ | //**************************** | ||
+ | |||
+ | // compiler error handling | ||
+ | //#include "Compiler_Errors.h" | ||
+ | |||
+ | // touch includes | ||
+ | #include <MPR121.h> | ||
+ | #include <MPR121_Datastream.h> | ||
+ | #include <Wire.h> | ||
+ | |||
+ | // keyboard includes | ||
+ | #include <Keyboard.h> | ||
+ | |||
+ | // keyboard variables | ||
+ | char key; | ||
+ | |||
+ | // keyboard behaviour constants | ||
+ | const bool HOLD_KEY = true; // set this to false if you want to have a single quick keystroke, true means the key is pressed and released when you press and release the electrode respectively | ||
+ | //const char KEY_MAP[12] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'}; | ||
+ | const char KEY_MAP[12] = {'M', 'R', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X'}; | ||
+ | // const char KEY_MAP[12] = {KEY_LEFT_ARROW, KEY_RIGHT_ARROW, KEY_UP_ARROW, KEY_DOWN_ARROW, ' ', KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_PAGE_UP, KEY_PAGE_DOWN}; // more keys at http://arduino.cc/en/Reference/KeyboardModifiers | ||
+ | //const char KEY_MAP[12] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'h', 'j'}; // for memory game | ||
+ | //9 | ||
+ | // touch constants | ||
+ | const uint32_t BAUD_RATE = 115200; | ||
+ | const uint8_t MPR121_ADDR = 0x5C; | ||
+ | const uint8_t MPR121_INT = 4; | ||
+ | |||
+ | // MPR121 datastream behaviour constants | ||
+ | const bool MPR121_DATASTREAM_ENABLE = false; | ||
+ | |||
+ | void setup() { | ||
+ | Serial.begin(BAUD_RATE); | ||
+ | pinMode(LED_BUILTIN, OUTPUT); | ||
+ | |||
+ | if (!MPR121.begin(MPR121_ADDR)) { | ||
+ | Serial.println("error setting up MPR121"); | ||
+ | switch (MPR121.getError()) { | ||
+ | case NO_ERROR: | ||
+ | Serial.println("no error"); | ||
+ | break; | ||
+ | case ADDRESS_UNKNOWN: | ||
+ | Serial.println("incorrect address"); | ||
+ | break; | ||
+ | case READBACK_FAIL: | ||
+ | Serial.println("readback failure"); | ||
+ | break; | ||
+ | case OVERCURRENT_FLAG: | ||
+ | Serial.println("overcurrent on REXT pin"); | ||
+ | break; | ||
+ | case OUT_OF_RANGE: | ||
+ | Serial.println("electrode out of range"); | ||
+ | break; | ||
+ | case NOT_INITED: | ||
+ | Serial.println("not initialised"); | ||
+ | break; | ||
+ | default: | ||
+ | Serial.println("unknown error"); | ||
+ | break; | ||
+ | } | ||
+ | while (1); | ||
+ | } | ||
+ | |||
+ | MPR121.setInterruptPin(MPR121_INT); | ||
+ | |||
+ | if (MPR121_DATASTREAM_ENABLE) { | ||
+ | MPR121.restoreSavedThresholds(); | ||
+ | MPR121_Datastream.begin(&Serial); | ||
+ | } else { | ||
+ | MPR121.setTouchThreshold(40); | ||
+ | MPR121.setReleaseThreshold(20); | ||
+ | } | ||
+ | |||
+ | MPR121.setFFI(FFI_10); | ||
+ | MPR121.setSFI(SFI_10); | ||
+ | MPR121.setGlobalCDT(CDT_4US); // reasonable for larger capacitances | ||
+ | |||
+ | digitalWrite(LED_BUILTIN, HIGH); // switch on user LED while auto calibrating electrodes | ||
+ | delay(1000); | ||
+ | MPR121.autoSetElectrodes(); // autoset all electrode settings | ||
+ | digitalWrite(LED_BUILTIN, LOW); | ||
+ | |||
+ | Keyboard.begin(); | ||
+ | } | ||
+ | |||
+ | void loop() { | ||
+ | MPR121.updateAll(); | ||
+ | |||
+ | for (int i=0; i < 12; i++) { // check which electrodes were pressed | ||
+ | key = KEY_MAP[i]; | ||
+ | |||
+ | if (MPR121.isNewTouch(i)) { | ||
+ | digitalWrite(LED_BUILTIN, HIGH); | ||
+ | Keyboard.press(key); // press the appropriate key on the "keyboard" output | ||
+ | |||
+ | if (!HOLD_KEY) { | ||
+ | Keyboard.release(key); // if we don't want to hold the key, immediately release it | ||
+ | } | ||
+ | } else { | ||
+ | if (MPR121.isNewRelease(i)) { | ||
+ | digitalWrite(LED_BUILTIN, LOW); | ||
+ | if (HOLD_KEY) { | ||
+ | Keyboard.release(key); // if we have a new release and we were holding a key, release it | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | //add the extra sensors with the extra keys | ||
+ | //**************************** | ||
+ | long sensorValue1 = cs_10_11.capacitiveSensor(30); | ||
+ | long sensorValue2 = cs_12_13.capacitiveSensor(30); | ||
+ | |||
+ | // Check if the existing sensor is touched | ||
+ | if (sensorValue1 > 1000) { | ||
+ | Keyboard.press('Y'); // Example key for existing sensor | ||
+ | delay(10); | ||
+ | } else { | ||
+ | Keyboard.release('Y'); | ||
+ | } | ||
+ | |||
+ | // Check if the new sensor 1 is touched | ||
+ | if (sensorValue2 > 1000) { | ||
+ | Keyboard.press('Z'); | ||
+ | delay(10); | ||
+ | } else { | ||
+ | Keyboard.release('Z'); | ||
+ | } | ||
+ | |||
+ | //**************************** | ||
+ | |||
+ | if (MPR121_DATASTREAM_ENABLE) { | ||
+ | MPR121_Datastream.update(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
[[Category:TouchBoard]][[Category:Sound]] | [[Category:TouchBoard]][[Category:Sound]] |
Latest revision as of 15:32, 10 October 2024
What is the Touch Board?
The Touch Board is a microcontroller (like Arduino for instance), with already build in capacitive sensors (also known as touch sensors) as well as an audio socket. This set up makes the board really convenient for projects having interaction through touch (or proximity) and a sound output.
In detail, the Touch Board has:
- 12 CAPACITIVE ELECTRODES
The Touch Board has 12 capacitive electrodes that respond to a touch. These electrodes can be extended with conductive materials, like Electric Paint,
- MP3 PLAYER AND MIDI SYNTHESIZER
The Touch Board has on-board MP3 playback and a MIDI synthesizer. This means you can either play MP3 files or simulate a MIDI instrument by touching the electrodes.
- 3.5MM AUDIO SOCKET
In order to hear the sounds coming from the Touch Board simply connect either headphones or speakers to the 3.5mm audio socket.
- MICROSD CARD READER
Upload MP3 files onto the supplied microSD card and change it without having to reprogram the Touch Board.
- USB SERIAL, MIDI INTERFACE AND MOUSE AND KEYBOARD
When plugged into a computer, the Touch Board can act as a USB serial device, USB MIDI interface or as a USB mouse or keyboard. Use the data from the electrodes as an input for software that utilises either serial, MIDI or keyboard strokes.
You can also have a look at the Technical Data Sheet [here].
Some links about it
- close up
- the kickstarter project
- Kitchen drums
- The bare board
- Interactive sound wall
- Touchboard holder:[[1]]
Use the Touch Board to play sounds
The Touch Board has a practical SD card reader, enabling us to upload sounds in MP3 format.
You can follow Changing the sounds of the board this instructions to change the sounds on the board.
You can use your own sounds, or look for free to use sound material online.
Here you can find a list of websites where you can find copyright free and ready to use sounds:
- https://freesound.org/
- https://www.nasa.gov/connect/sounds/index.html
- archive.org https://archive.org/details/audio
- youtube.com/audiolibrary - https://support.google.com/youtube/answer/3376882?hl=en-GB
- https://sound-effects.bbcrewind.co.uk/
- https://soundbible.com
- https://www.soundjay.com/
- https://free-loops.com/
- https://www.freesoundslibrary.com/
- https://sound-effects.bbcrewind.co.uk/
NB. Files can be converted by VLC or online, in case they are not in mp3 format.
Setting up your Touch Board with the Arduino Installer
The touch board can be programmed on the Arduino IDE software.
In order to do so it is first required to install some dependencies that make you able to work with the Touch Board. You can find the instructions here.
Once you completed the instructions you can check whether the library has been installed correctly by opening your Arduino IDE and go to:
File --> Sketchbook --> Touch Board Examples
You should be able to find already a bunch of example code you can use and modify to make it your own.
To play MP3 files from the SD card when touching the sensors you can use Touch_MP3. You can also use the touch board as a keyboard with the HID_keyboard sketch.
Making Distance Sensors: Trigger the Touch Board with proximity
Maybe you might want to use the touch board sensor in a different way, maybe without actual touching happening but only by proximity to the sensor. The board allows you to modify the sensitivity of the sensor to be able to detect presence without any touching. to do so you can follow the instructions here.
Other options (not in the example folder)
Hold electrode to play sound or Play only when touched
Here you can find an already made example code that allows you to play a track only while the sensor is touched. The sound will stop when releasing the sensor.
Hold To Play Code
Download this library
Play new track only when last one is over
This code is a variant on the Touch_MP3 example but instead of starting a the corresponding track when another sensor gets triggered it forces the board to finish to play the previous file. If you press another sensor while the last track it still playing it will ignore the touch. You will be able to trigger another file only when the previous one is over.
//#include "Compiler_Errors.h"
#include <MPR121.h>
#include <Wire.h>
#include <SPI.h>
#include <SdFat.h>
#include <FreeStack.h>
#include <SFEMP3Shield.h>
const uint32_t BAUD_RATE = 115200;
const uint8_t MPR121_ADDR = 0x5C;
const uint8_t MPR121_INT = 4;
const bool WAIT_FOR_SERIAL = false;
uint8_t result;
uint8_t lastPlayed = 0;
bool isTrackPlaying = false; // Flag to track if a track is currently playing
SFEMP3Shield MP3player;
SdFat sd;
// Set your desired touch and release thresholds
const uint8_t TOUCH_THRESHOLD = 40;
const uint8_t RELEASE_THRESHOLD = 20;
void setup() {
Serial.begin(BAUD_RATE);
pinMode(LED_BUILTIN, OUTPUT);
if (WAIT_FOR_SERIAL) {
while (!Serial);
}
if (!sd.begin(SD_SEL, SPI_HALF_SPEED)) {
sd.initErrorHalt();
}
if (!MPR121.begin(MPR121_ADDR)) {
Serial.println("error setting up MPR121");
switch (MPR121.getError()) {
// Handle error cases as before...
}
while (1);
}
MPR121.setInterruptPin(MPR121_INT);
// Set touch and release thresholds
MPR121.setTouchThreshold(TOUCH_THRESHOLD);
MPR121.setReleaseThreshold(RELEASE_THRESHOLD);
// Set other MPR121 configuration parameters as needed...
result = MP3player.begin();
MP3player.setVolume(10, 10);
if (result != 0) {
Serial.print("Error code: ");
Serial.print(result);
Serial.println(" when trying to start MP3 player");
}
}
void loop() {
MPR121.updateAll();
// Only make an action if we have one or fewer pins touched
// Ignore multiple touches
if (MPR121.getNumTouches() <= 1) {
for (int i = 0; i < 12; i++) {
if (MPR121.isNewTouch(i)) {
if (i >= 0 && i <= 11) {
if (!isTrackPlaying) {
// If no track is currently playing, start playing the requested track
MP3player.playTrack(i);
lastPlayed = i;
isTrackPlaying = true;
Serial.print("Playing track ");
Serial.println(i);
}
}
} else {
if (MPR121.isNewRelease(i)) {
// Handle release logic (if needed)
}
}
}
}
// Check if the current track has finished playing
if (isTrackPlaying && !MP3player.isPlaying()) {
isTrackPlaying = false; // Reset the flag
Serial.println("Track finished playing.");
// Blink the LED at the end of the track
digitalWrite(LED_BUILTIN, HIGH);
delay(500); // Adjust the delay as needed
digitalWrite(LED_BUILTIN, LOW);
}
}
When using this code check the Serial Monitor to see when the track is playing/over.
Playing more sounds simultaneously: Polyphonic Playback
As you might have noticed, the Touch Board is not able to play multiple sounds at the same time - or to do what is called Polyphonic playback. You can still achieve this by using your touch board as a keyboard and play sounds with the help of a software. You can find here a guide on how to set up your Touch Board with Soundplant. When using this code check the Serial Monitor to see when the track is playing/over.
Use additional Pins on the TouchBoard
Most of the Pins of the TouchBoard are used for the capacitive sensors and the MP3 functions. There are though some unallocated pins that you can program in case you need to add a new functionality (a light, another sensor or similar).
For this purpose you can use:
- Digital Pins 0,1,10,11,12,13
- Digital Pins 5,6,7,8,9 (only if you are not using the MP3 function)
Adding an extra capacitive sensor
Sometimes you want to use the same TouchBoard functionalities but add a couple of sensors. To do so you can add and program external capacitive sensors.
You can follow this guide to add extra capacitive sensors.
Wiring:
For one sensor you will need:
Breadboard
3x Jumper wires
1x 1M ohm resistor
1. Look for two Digital Pins of the TouchBoard that are available to use (see the TouchBoard Pins image above)
2. Connect each Pin to two separate rows on the breadboard using two Jumper wires
3. Place a 1M ohm resistor in between the two
4. Add a Jumper wire on the second pin end: this is going to be your sensor. You can later connect it to a touching pad or similar.
Read sensors and link it to a key press
#include <CapacitiveSensor.h>
#include <Keyboard.h>
// Define the capacitive sensors
CapacitiveSensor cs_10_11 = CapacitiveSensor(10, 11); // sensor1
CapacitiveSensor cs_12_13 = CapacitiveSensor(12, 13); // sensor2
void setup() {
// Initialize the Keyboard library
Keyboard.begin();
}
void loop() {
long sensorValue1 = cs_10_11.capacitiveSensor(30);
long sensorValue2 = cs_12_13.capacitiveSensor(30);
// Check if the existing sensor is touched
if (sensorValue1 > 1000) {
Keyboard.press('Y'); // Example key for existing sensor
} else {
Keyboard.release('Y');
}
// Check if the new sensor 1 is touched
if (sensorValue2 > 1000) {
Keyboard.press('Z');
} else {
Keyboard.release('Z');
}
delay(10); // Small delay to avoid bouncing
}
Add the new keys to the other 12
Let's add our new keys to the HID_KEYBOARD sketch:
//CAPACITIVE SENSORS using 10-11 and 12-13 pins
//check wiring here https://www.bareconductive.com/blogs/resources/make-a-basic-capacitive-sensor-with-electric-paint-and-arduino?srsltid=AfmBOoonCrtXdl4H0WSuAYeuSYUIlz1rfkKDb2qsZFdfGwGpJY0BfPTZ
//****************************
#include <CapacitiveSensor.h>
CapacitiveSensor cs_10_11 = CapacitiveSensor(10, 11); // sensor1
CapacitiveSensor cs_12_13 = CapacitiveSensor(12, 13); // sensor2
//****************************
// compiler error handling
//#include "Compiler_Errors.h"
// touch includes
#include <MPR121.h>
#include <MPR121_Datastream.h>
#include <Wire.h>
// keyboard includes
#include <Keyboard.h>
// keyboard variables
char key;
// keyboard behaviour constants
const bool HOLD_KEY = true; // set this to false if you want to have a single quick keystroke, true means the key is pressed and released when you press and release the electrode respectively
//const char KEY_MAP[12] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'};
const char KEY_MAP[12] = {'M', 'R', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X'};
// const char KEY_MAP[12] = {KEY_LEFT_ARROW, KEY_RIGHT_ARROW, KEY_UP_ARROW, KEY_DOWN_ARROW, ' ', KEY_ESC, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_PAGE_UP, KEY_PAGE_DOWN}; // more keys at http://arduino.cc/en/Reference/KeyboardModifiers
//const char KEY_MAP[12] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'h', 'j'}; // for memory game
//9
// touch constants
const uint32_t BAUD_RATE = 115200;
const uint8_t MPR121_ADDR = 0x5C;
const uint8_t MPR121_INT = 4;
// MPR121 datastream behaviour constants
const bool MPR121_DATASTREAM_ENABLE = false;
void setup() {
Serial.begin(BAUD_RATE);
pinMode(LED_BUILTIN, OUTPUT);
if (!MPR121.begin(MPR121_ADDR)) {
Serial.println("error setting up MPR121");
switch (MPR121.getError()) {
case NO_ERROR:
Serial.println("no error");
break;
case ADDRESS_UNKNOWN:
Serial.println("incorrect address");
break;
case READBACK_FAIL:
Serial.println("readback failure");
break;
case OVERCURRENT_FLAG:
Serial.println("overcurrent on REXT pin");
break;
case OUT_OF_RANGE:
Serial.println("electrode out of range");
break;
case NOT_INITED:
Serial.println("not initialised");
break;
default:
Serial.println("unknown error");
break;
}
while (1);
}
MPR121.setInterruptPin(MPR121_INT);
if (MPR121_DATASTREAM_ENABLE) {
MPR121.restoreSavedThresholds();
MPR121_Datastream.begin(&Serial);
} else {
MPR121.setTouchThreshold(40);
MPR121.setReleaseThreshold(20);
}
MPR121.setFFI(FFI_10);
MPR121.setSFI(SFI_10);
MPR121.setGlobalCDT(CDT_4US); // reasonable for larger capacitances
digitalWrite(LED_BUILTIN, HIGH); // switch on user LED while auto calibrating electrodes
delay(1000);
MPR121.autoSetElectrodes(); // autoset all electrode settings
digitalWrite(LED_BUILTIN, LOW);
Keyboard.begin();
}
void loop() {
MPR121.updateAll();
for (int i=0; i < 12; i++) { // check which electrodes were pressed
key = KEY_MAP[i];
if (MPR121.isNewTouch(i)) {
digitalWrite(LED_BUILTIN, HIGH);
Keyboard.press(key); // press the appropriate key on the "keyboard" output
if (!HOLD_KEY) {
Keyboard.release(key); // if we don't want to hold the key, immediately release it
}
} else {
if (MPR121.isNewRelease(i)) {
digitalWrite(LED_BUILTIN, LOW);
if (HOLD_KEY) {
Keyboard.release(key); // if we have a new release and we were holding a key, release it
}
}
}
}
//add the extra sensors with the extra keys
//****************************
long sensorValue1 = cs_10_11.capacitiveSensor(30);
long sensorValue2 = cs_12_13.capacitiveSensor(30);
// Check if the existing sensor is touched
if (sensorValue1 > 1000) {
Keyboard.press('Y'); // Example key for existing sensor
delay(10);
} else {
Keyboard.release('Y');
}
// Check if the new sensor 1 is touched
if (sensorValue2 > 1000) {
Keyboard.press('Z');
delay(10);
} else {
Keyboard.release('Z');
}
//****************************
if (MPR121_DATASTREAM_ENABLE) {
MPR121_Datastream.update();
}
}