Djette
|
more info:
|http://www.ooooo.be/djette
Contents
Concept:
The BPM of an audio track is regulated by the tempo of biking. The audio equipment is loaded in a bike cart, runs on batteries. An easy manageable device on the steering wheel can be controlled to play funky tracks.
System:
Tracking of the tempo by a PHOTRESISTOR + ARDUINO + PROCESSING.
Audio by a 9 volt MONO amplifier 3,5WAtt and some old recycled speaker.
Arduino code sound bending: | http://www.adafruit.com/blog/2008/05/21/wave-shield-bending-the-playback-sample-rate
Currently a reed switch is being used, and i found this great manual, tracking the speed of a wheel,
| http://www.youtube.com/watch?v=sl8ItZxGM6E |http://idkfa.com/ec/the-bike/the-bike-how-to/
Potential code:
|http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1257785566
Convert AUDIO WAV for waveshield https://boundaryfunctions.wordpress.com/2010/02/23/batch-converting-audio-using-sox-for-arduino-waveshield/
Style:
to pimp up the bike with LEDs: |Project Aura
to pimp up the bike with stuff: |CARDS |STRAWS
result
came up with this -- ptr_
#include <AF_Wave.h> #include <avr/pgmspace.h> #include "util.h" #include "wave.h" #define B_REED_SWITCH 0 #define B_NEXT 1 #define B_NORMAL 2 byte buttons[] = { 9, 8, 7 }; #define NUMBUTTONS sizeof(buttons) volatile byte pressed[NUMBUTTONS], justpressed[NUMBUTTONS], justreleased[NUMBUTTONS]; /////////////////////////////////////////////////////////////////////////////// WAVESTUFF AF_Wave card; File f; Wavefile wave; // only one! uint32_t wavsamplerate = 22050; char * wavname; // filename WAV file uint8_t tracknum = 0; void settrack(uint8_t num){ switch (num){ case 0: wavname = "TRACK0.WAV"; break; case 1: wavname = "TRACK1.WAV"; break; case 2: wavname = "TRACK2.WAV"; break; case 3: wavname = "TRACK3.WAV"; break; case 4: wavname = "TRACK4.WAV"; break; case 5: wavname = "TRACK5.WAV"; break; case 6: wavname = "TRACK6.WAV"; break; case 7: wavname = "TRACK7.WAV"; break; case 8: wavname = "TRACK8.WAV"; break; case 9: wavname = "TRACK9.WAV"; break; case 10: wavname = "TRACK10.WAV"; break; case 11: wavname = "TRACK11.WAV"; break; case 12: wavname = "TRACK12.WAV"; break; case 13: wavname = "TRACK13.WAV"; break; case 14: wavname = "TRACK14.WAV"; break; case 15: wavname = "TRACK15.WAV"; break; case 16: wavname = "TRACK16.WAV"; break; case 17: wavname = "TRACK17.WAV"; break; case 18: wavname = "TRACK18.WAV"; break; case 19: wavname = "TRACK19.WAV"; break; case 20: wavname = "TRACK20.WAV"; break; case 21: wavname = "TRACK21.WAV"; break; case 22: wavname = "TRACK22.WAV"; break; case 23: wavname = "TRACK23.WAV"; break; } card.reset_dir(); } void ls() { char fname[13]; int ret; card.reset_dir(); putstring_nl("Listing:"); while (1) { ret = card.get_next_name_in_dir(fname); if (!ret) { card.reset_dir(); return; } Serial.println(fname); } } bool active_file = false; void playfile(char *name) { while (wave.isplaying) { wave.stop(); } card.reset_dir(); if(active_file) { Serial.println("closing previous file"); card.close_file(f); } card.reset_dir(); f = card.open_file(name); Serial.print("opening new file "); Serial.println(name); if (!f) { putstring_nl(" Couldn't open file"); return; } active_file = true; if (!wave.create(f)) { putstring_nl(" Not a valid WAV"); return; } // ok time to play! wave.play(); } /////////////////////////////////////////////////////////////////////////////////////////// SETUP void setup() { Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("BOOMBIKE!"); // Set the output pins for the DAC control. This pins are defined in the library pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); if (!card.init_card()) { putstring_nl("Card init. failed!"); return; } if (!card.open_partition()) { putstring_nl("No partition!"); return; } if (!card.open_filesys()) { putstring_nl("Couldn't open filesys"); return; } if (!card.open_rootdir()) { putstring_nl("Couldn't open dir"); return; } pinMode(buttons[B_REED_SWITCH], INPUT); // reed switch pinMode(buttons[B_NEXT], INPUT); // button next pinMode(buttons[B_NORMAL], INPUT); // button normal /* TCCR2A = 0; TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20; //Timer2 Overflow Interrupt Enable TIMSK2 |= 1<<TOIE2; */ ls(); } /* SIGNAL(TIMER2_OVF_vect) { check_switches(); } */ void check_switches() { static byte previousstate[NUMBUTTONS]; static byte currentstate[NUMBUTTONS]; byte index; for (index = 0; index < NUMBUTTONS; index++) { currentstate[index] = digitalRead(buttons[index]); // read the button if (currentstate[index] == previousstate[index]) { if ((pressed[index] == LOW) && (currentstate[index] == LOW)) { // just pressed justpressed[index] = 1; } else if ((pressed[index] == HIGH) && (currentstate[index] == HIGH)) { // just released justreleased[index] = 1; } pressed[index] = !currentstate[index]; // remember, digital HIGH means NOT pressed } //Serial.println(pressed[index], DEC); previousstate[index] = currentstate[index]; // keep a running tally of the buttons } } bool normal_mode = false; float avgSpeed = 0.0f; float curSpeed = 0.0f; unsigned long curTime, prevTime; /////////////////////////////////////////////////////////////////////////////////////////// LOOP boolean samplerate_changed = false; uint32_t lastReedRead = 0; void loop() { char c; check_switches(); if(pressed[B_NEXT] && pressed[B_NORMAL]) { justpressed[B_NEXT]=0; justpressed[B_NORMAL]=0; Serial.println("two buttons pushed"); } else if( justpressed[B_NEXT] ) { justpressed[B_NEXT]=0; Serial.println("B_NEXT pushed"); settrack(tracknum); Serial.println(wavname); playfile(wavname); tracknum++; } else if( justpressed[B_NORMAL] ) { justpressed[B_NORMAL]=0; Serial.println("B_NORMAL pushed"); normal_mode =!normal_mode; if(normal_mode) { Serial.print("playing a fixed bitrate"); wave.setSampleRate(wave.dwSamplesPerSec); } else { Serial.print("playing a dynamic bitrate"); } } if(justpressed[B_REED_SWITCH]) { justpressed[B_REED_SWITCH] = 0; prevTime = curTime; curTime = millis(); lastReedRead = curTime; curSpeed = float(curTime - prevTime); // cumulative average const float alpha = 0.5f; avgSpeed = avgSpeed * (1.0f - alpha) + curSpeed * alpha; Serial.print("curSpeed: "); Serial.print(curSpeed); Serial.print(" avgSpeed: "); Serial.println(avgSpeed); // TIMING constantes // const float x1 = 1000.0f; // slow sensor timing const float x2 = 150.0f; // fast sensor timing const float y1 = 5000.0f; const float y2 = 25000.0f; const float m = (y2-y1) / (x2-x1); float fsamplerate = (avgSpeed * m ) - m * x1 + y1; if (fsamplerate > 0.0f) wavsamplerate = fsamplerate; else wavsamplerate = 0.0; samplerate_changed = true; Serial.print("fsamplerate: "); Serial.println(fsamplerate); Serial.print(" wavsamplerate: "); Serial.println(wavsamplerate); } if (millis() - lastReedRead > 700) { if(wavsamplerate>100) wavsamplerate -= 100; samplerate_changed = true; // lastReedRead = millis(); } if(samplerate_changed && wave.isplaying && !normal_mode) { if (wavsamplerate>25000) wavsamplerate= 25000; wave.setSampleRate(wavsamplerate); samplerate_changed = false; } }