PDA

View Full Version : My first project of epic scale - foot sized Cap sensing piano under floor



Max Power
- 23rd November 2011, 17:50
this project started about 2 years ago. I had a large piece of perf board, a super simple, relaxation oscillator, non-interupting, 1-channel cap sensing routine running on a 16F628A, and a 16 to 1 analog multiplexer, and some time to kill, so I arranged 16 finger sized copper tape squares on the underside of the perf board and wired them to the multiplexer, and then wired the multiplexer to the cap sensor circuit. lo and behold, it worked, and I made a routine to scan the keys and use the SOUND command to output a tone corresponding to the key. I originally wanted to use the HPWM channel to generate the correct tones, (maybe more than one at at time!) and keep them sustained for the duration of the key press. What I ended up with was a little less impressive.. out of tune tones generated by the SOUND command that just went beep beep beep if you held your finger on one key at a time.


The board has sat on my bench since then, collecting dust. But in that time, I've worked more and more with cap sensors, and I've always thought about putting cap sensors under the floor, and doing something cool with that. Fast forward to now, we are due to have our third kid around Christmas time, and my 7 year old daughter is moving her room from upstairs to the downstairs so the baby can have her old room.It's a little cold down there, there are spiders, and the window is tiny. So, I wanted to make her room special. I ripped up the old carpeting, re-painted, and now I'm installing laminate flooring. I thought 'Hey, here is my chance to put in cap sensors under the floor.. what should I do?'


I ended up laying out 16 piano keys -10 white keys, B through D, and their black keys, so 16 in total. They are foot sized sensors on the laminate pad made with copper tape and wired to that same controller/multiplexer board which now sits in a cutout in the drywall, which will be eventually hidden by the trim. I spent most of last weekend on my hands and knees, but now it is working with my super simple code that I wrote long ago.


Now that I've upgraded the hardware, I need to rethink the code. and how I can get different sounds, chords, and whatnot, without breaking the bank. I have an old keyboard that I could hack up and put fets or transistors on the key pads and control it that way... but that'll be a kludged together hack job.


Right now, I'm thinking that I'll run 3 wires to the buried 16F628 controller, +5V, GND and a serial data line that will spit out 2 bytes, 16 bits corresponding to the pressed/unpressed states of the 16 keys. Then, I'll have another pic reading that data and (somehow) make the music happen.


I'd love to have something like rmteo has posted:
http://www.pic24.ru/doku.php/en/osa/articles/pk2_osa_piano




Any suggestions about how to go about making the music happen?


I also got 2 meters of RGB LEDs and a cheap controller from ebay that has a remote. Eventually it would be nice to get the piano and the RGBs working together...but that is for another day.


but anyway, here is the code that is running right now on the 16F628A, controlling the multiplexer and counting the pulses from the relaxation oscillator.


if I count for 8mS, I get a count of about 3100, so the oscillator is running at about 380KHz. put your foot on the sensor, with the laminate in between, and it drops to about 2950~3000, since then, I changed to counting for 4mS.


Any suggestions?


I realize that what I call 'average' is not really an average, it's just a snapshot of the values it saw when it was first powered on..
and, I see that my line to combine the timerH and timerL bytes is wrong, but I can't seem to get value=timerH.timerL to work.




'PIc and analog multiplexer capsense




' PIC16F628A Configuration
' ================




@ __CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF & _WDT_ON & _PWRTE_ON & _BODEN_ON


' Hardware configuration
' ======================


CLEARWDT


DEFINE OSC 4 '4 MHz internal oscillator




DEFINE DEBUG_REG PORTB 'RS-232 output on PORTB.4
DEFINE DEBUG_BIT 7
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0 'not inverted. using RS-232 chip, or pickit2
DEFINE DEBUG_PACING 1000






CMCON = %00000110 ' 2 common ref comparators with outputs ..datasheet pdf page 64
TRISB = %01000000 ' B.6= timer input = Comparator output freq
TRISA = %00000111 ' Comparator inputs and Vref set to input
VRCON = %11100011 ' turn on Vref, output connected to RA2, Low range, Vref = .6 when Vcc = 5V
' ..datasheet pdf page 69




' RAM Assignments and Variables
' =============================




DEBUGPIN var PORTB.4
S0 var PORTB.0
S1 var PORTB.1
S2 var PORTB.5
S3 var PORTB.7
EN var PORTB.2
SPEAKER var PORTB.3








S0 =0
S1 =0
S2 =0
S3 =0
EN =1






SenseTime CON 4 ' how many milliseconds to run the cap sense counter for one sample




Sleepy var WORD ' counter used with 'asleep'
asleep CON 1000 ' number of times around the main loop with no activity to put the chip to sleep.
Sleeptime CON 6 'Nap command period (5 = approx 480ms, 4 = approx 280ms)




TONE var BYTE[16]




TONE[15] = 48
TONE[14] = 53
TONE[13] = 56
TONE[12] = 61
TONE[11] = 64
TONE[10] = 68
TONE[9] = 72
TONE[8] = 75
TONE[0] = 78
TONE[1] = 81
TONE[2] = 83
TONE[3] = 86
TONE[4] = 89
TONE[5] = 90
TONE[6] = 92
TONE[7] = 94


Trip CON 30
playtime con 12


AVE VAR WORD[16] ' current Capsense average
Value VAR WORD[16] ' instantaneous Capsense count array






SensorNumb var BYTE




pause 3000




DEBUG REP $00\8,13,10,"Hello"


Sleepy = 0




GOSUB SCAN


FOR SensorNumb = 0 to 15
AVE[SensorNumb] = Value[SensorNumb]


NEXT SensorNumb






main:






GOSUB SCAN








'DEBUG DEC Value[15], ", ", DEC Value[14], ", ", DEC Value[13], ", ",DEC Value[12], ", ",DEC Value[11], ", ",DEC Value[10], ", ", DEC Value[9],13,10




FOR SensorNumb = 0 to 15


IF Value[SensorNumb] < (AVE[SensorNumb] - Trip) THEN
SOUND SPEAKER,[TONE[SensorNumb],playtime]
Sleepy = 0
goto main
ENDIF
NEXT SensorNumb








'Sleepy = Sleepy +1



IF Sleepy = asleep THEN
DEBUG REP $00\8,13,10,"zz.."
CMCON=7 ' disable internal comparator
VRCON = %00000000 ' disable voltage reference


NAP Sleeptime ' places the microcontroller into low power mode


CMCON = %00000110 ' enable internal comparator
VRCON = %11100011 ' enable voltage reference
Sleepy = (asleep -1) ' Preload the the sleepy counter so it'll go right back to sleep after one reading


ENDIF






goto main


' -=-=-=-=-=-= Scan sensors and put results into Value[X] -=-=-=-=-=-=-=-=-=-=
SCAN:


FOR SensorNumb = 0 to 15




S0 =SensorNumb.0
S1 =SensorNumb.1
S2 =SensorNumb.2
S3 =SensorNumb.3
EN =0




TMR1H = 0 'Clear high and low timer1 registers
TMR1L = 0
T1CON = %00000111 'Start counter
pause SenseTime 'wait
T1CON = %00000110 'Stop counter


EN =1


Value[SensorNumb] = ((255 * TMR1H) + TMR1L) 'Combine high and low byte into one word sized variable




NEXT SensorNumb


RETURN


End

Max Power
- 29th November 2011, 04:09
no suggestions. OK. so that was a pretty long winded post. Sorry. but anyway, I'm moving away from the idea of hacking up my old keyboard and I'm thinking that I could spit out midi messages to a midi synth. I have never played with midi stuff before, but after reading some posts like the one called
'button press AND hserout issues?! (http://www.picbasic.co.uk/forum/showthread.php?t=15235)' it looks possible. well sort of, the OP of that post had some unresolved issues.

if I put a 20MHz resonator on my 16F628A, then connect it to something like this:
http://www.sparkfun.com/products/8953
(http://www.sparkfun.com/products/8953)and then connect some powered speakers to the headphone jack, I'm thinking I could play different tones at the same time, and also switch instruments

anybody have some insight on midi? would this work?