// XYZ textile pad
// (procedural abstraction)
void analogPullup(int pin, boolean activate)
{
pinMode(14+pin, INPUT); // magic to active pullups 14 is the numbering of the analog pins
digitalWrite(14+pin, activate ? HIGH : LOW);
// if activate is true then HIGH else LOW <--- pseudocode
}
// establish a potential difference between two analog pins
void analog_establish_potential(int pinhigh, int pinlow)
{
pinMode(14+pinhigh,OUTPUT); //
digitalWrite(14+pinhigh, HIGH); //3.3v
pinMode(14+pinlow,OUTPUT); //
digitalWrite(14+pinlow, LOW); //0v
}
// data abstraction (reuse which allows for scaling this to a lot of sensors and cool stuff)
const int left_strip_pin=0;
const int right_strip_pin=1;
const int top_strip_pin=2;
const int bottom_strip_pin= 3;
const int led_pin = 13;
void setup() {
pinMode(led_pin, OUTPUT);
Serial.begin(9600); // debugging
}
void loop() {
delay(500); // slow sensing down so we have time to read values on serial console
analog_establish_potential(top_strip_pin, bottom_strip_pin);
analogPullup(right_strip_pin, true);
analogPullup(left_strip_pin, true);
// analogRead functions numbers from 0 (not 14)!
int sensorValue = analogRead(right_strip_pin);
Serial.print(sensorValue); Serial.print(' ');
if(sensorValue < 900)
{
// disable pullup to get an accurate value
analogPullup(right_strip_pin, false);
analogPullup(left_strip_pin, false);
int sensorValue = analogRead(right_strip_pin);
Serial.print(sensorValue);Serial.print("v ");
// now we do left and right
analog_establish_potential(left_strip_pin, right_strip_pin);
analogPullup(top_strip_pin, false);
analogPullup(bottom_strip_pin, false);
// analogRead functions numbers from 0 (not 14)!
sensorValue = analogRead(bottom_strip_pin);
Serial.print(sensorValue); Serial.print("h ");
// int ledFadeValue = map(sensorValue, 300, 700, 0, 255);
// analogWrite(led_pin, ledFadeValue);
}
Serial.println();
}
// Touch Synth
// Copyright 2009 Adrian Freed. All Rights Reserved.
// tested on the lilypad
// requires rework to deal with different port assignments on the mega
//
//shorthands to turn on the built-in pullup resistors for each pin
inline void digitalPullup(byte pin, boolean b) { pinMode(pin, INPUT); digitalWrite(pin, b?HIGH:LOW); }
#if defined(__AVR_ATmega1280__)
inline void analogPullup(byte pin, boolean b) { digitalPullup(pin+54,b); }
#else
inline void analogPullup(byte pin, boolean b) { digitalPullup(pin+14,b); }
#endif
const byte speakerPin = 0; //a0
const byte speakerPinbis = 1; // differential drive for extra loudness and lower power consumption
const boolean debugging = false;
void setup()
{
if(debugging)
{
Serial.begin(9600);
}
pinMode(speakerPin, OUTPUT); // sets the speakerPin to be an output
pinMode(speakerPinbis, OUTPUT); // sets the other speakerPin to be an output
}
//touch sensing on the 14 digial pins on ports d and b
// http://www.arduino.cc/en/Reference/PortManipulation
typedef struct tr
{
byte t[14+8]; // >1 when touched. The number is larger the better your bodies path is to ground
} touchresult;
struct tr touchsense(int pins); // a bit field to set which pins you want to be touch active.
#define TRANGE 32
struct tr touchsense(unsigned long pins)
{
byte portd = pins &0xff;
byte portb = (pins>>8) &0x3f;
byte portc = (pins>>13)&0xff;
byte i,j;
byte result[TRANGE];
touchresult r= { 0,0,0,0, 0,0,0,0 ,0,0,0,0, 0,0};
// concurrent sensing for portb
portb &= ~DDRB; // don't mess with direction of existing output pins
// xxxhow do we know what input pins are in use?
// how do we not disturb state of existing output pins?
if(portb)
{
PORTB &= ~portb; // low level
DDRB |= portb; // discharge
for(i=0;i<TRANGE;++i)
result[i] = 0;
DDRB &= ~portb;
PORTB |= portb;
result[0] = PINB;
result[1] = PINB;
result[2] = PINB;
result[3] = PINB;
result[4] = PINB;
result[5] = PINB;
result[6] = PINB;
result[7] = PINB;
result[8] = PINB;
result[9] = PINB;
result[10] = PINB;
result[11] = PINB;
result[12] = PINB;
result[13] = PINB;
result[14] = PINB;
result[15] = PINB;
result[16] = PINB;
result[17] = PINB;
result[18] = PINB;
result[19] = PINB;
result[20] = PINB;
result[21] = PINB;
result[22] = PINB;
result[23] = PINB;
result[24] = PINB;
result[25] = PINB;
result[26] = PINB;
result[27] = PINB;
result[28] = PINB;
result[29] = PINB;
result[30] = PINB;
result[31] = PINB;
for(i=2;i<TRANGE;++i)
{
// Serial.println(result[i], HEX);
for(j=0;j<6;++j)
{
if(portb&(1<<j))
r.t[j+8] += !(result[i] & (1<<j));
}
}
}
// concurrent sensing for portc
portc &= ~DDRC; // don't mess with direction of existing output pins
// xxxhow do we know what input pins are in use?
// how do we not disturb state of existing output pins?
if(portc)
{
PORTC &= ~portc; // low level
DDRC |= portc; // discharge
for(i=0;i<TRANGE;++i)
result[i] = 0;
DDRC &= ~portc;
PORTC |= portc;
result[0] = PINC;
result[1] = PINC;
result[2] = PINC;
result[3] = PINC;
result[4] = PINC;
result[5] = PINC;
result[6] = PINC;
result[7] = PINC;
result[8] = PINC;
result[9] = PINC;
result[10] = PINC;
result[11] = PINC;
result[12] = PINC;
result[13] = PINC;
result[14] = PINC;
result[15] = PINC;
result[16] = PINC;
result[17] = PINC;
result[18] = PINC;
result[19] = PINC;
result[20] = PINC;
result[21] = PINC;
result[22] = PINC;
result[23] = PINC;
result[24] = PINC;
result[25] = PINC;
result[26] = PINC;
result[27] = PINC;
result[28] = PINC;
result[29] = PINC;
result[30] = PINC;
result[31] = PINC;
for(i=2;i<TRANGE;++i)
{
// Serial.println(result[i], HEX);
for(j=0;j<8;++j)
{
if(portc&(1<<j))
r.t[j+14] += !(result[i] & (1<<j));
}
}
}
// concurrent sensing for port D
portd &= ~DDRD; // don't mess with direction of existing output pins
// xxxhow do we know what input pins are in use?
// how do we not disturb state of existing output pins?
if(portd)
{
PORTD &= ~portd; // low level
DDRD |= portd; // discharge
for(i=0;i<TRANGE;++i)
result[i] = 0;
DDRD &= ~portd;
PORTD |= portd;
result[0] = PIND;
result[1] = PIND;
result[2] = PIND;
result[3] = PIND;
result[4] = PIND;
result[5] = PIND;
result[6] = PIND;
result[7] = PIND;
result[8] = PIND;
result[9] = PIND;
result[10] = PIND;
result[11] = PIND;
result[12] = PIND;
result[13] = PIND;
result[14] = PIND;
result[15] = PIND;
result[16] = PIND;
result[17] = PIND;
result[18] = PIND;
result[19] = PIND;
result[20] = PIND;
result[21] = PIND;
result[22] = PIND;
result[23] = PIND;
result[24] = PIND;
result[25] = PIND;
result[26] = PIND;
result[27] = PIND;
result[28] = PIND;
result[29] = PIND;
result[30] = PIND;
result[31] = PIND;
for(i=2;i<TRANGE;++i)
{
// Serial.println(result[i], HEX);
for(j=0;j<8;++j)
{ if(portd&(1<<j))
r.t[j] += !(result[i] & (1<<j));
}
}
}
return r;
}
static int pitches[] =
{
523,
554,
587,
622,
659,
698,
740,
784,
831,
880,
932,
988,
2*523,
2*554,
2*587,
2*622,
2*659,
2*698,
2*740,
2*784,
2*831,
2*880,
2*932,
2*988,
};
// differential pulse trains. The marktospacepercentage controls timbre (and amplitude for small values).
// The frequency determines pitch. Use a high impedence driver: 30-100Ohms or a piezo.
void beep (unsigned frequencyInHertz, unsigned timeInMilliseconds, unsigned marktospacepercentage) // the sound producing function
{
int x;
static int swap=0;
unsigned long delayAmount = 1000000L/frequencyInHertz;
unsigned long markdelay = delayAmount*marktospacepercentage/1000l;
unsigned long spacedelay = (delayAmount*(1000l-marktospacepercentage))/1000l;
int loopTime = (int)((timeInMilliseconds*500l)/(delayAmount));
while(loopTime--)
{
pinMode(speakerPin, OUTPUT); // sets the speakerPin to be an output
pinMode(speakerPinbis, OUTPUT); // sets the other speakerPin to be an output
digitalWrite(speakerPin,swap);
digitalWrite(speakerPinbis,!swap);
delayMicroseconds(markdelay);
pinMode(speakerPin, INPUT); // sets the speakerPin to be an output
pinMode(speakerPinbis, INPUT); // sets the other speakerPin to be an output
delayMicroseconds(spacedelay);
}
swap = !swap;
}
void loop ()
{
// read the keys
struct tr r = touchsense(0xcffcUL);
// sound a short pitch for each touch using the touch value to determine loudness/timbre
for(int i = 0; i < 21; i++)
{
int key =r.t[i];
if(key>0 &&i!=13 && i!=speakerPin && i!=speakerPinbis)
{
if(debugging)
{
Serial.print(i); Serial.print(" ");
Serial.println(key);
}
beep(pitches[i]/4,100,key);
}
}
}
#include <stdarg.h>
void touchsensepins(int l, ...)
{
va_list argp;
unsigned long res = 0;
va_start(argp, l);
int i = l;
do
{
res |= 1UL <<i;
}
while((i = va_arg(argp, int))!=-1);
touchsense(res);
va_end(argp);
}