User:Laurier Rochon/prototyping/arduino recorder: Difference between revisions
No edit summary |
(→SOFT) |
||
Line 17: | Line 17: | ||
== SOFT == | == SOFT == | ||
'''Self-resetting / state-run / compact version''' | '''Self-resetting / state-run / compact / verbose version''' | ||
The realization with this version was that there are actually not 3 states, but more like 2 & 1/2. Counting the 'waiting' period as state 1, pressed as state 2 - but the 'released' state not being an actual state in itself, rather the un-doing of the 'pressed' one. To paraphrase, you can't really 'hold' the unpressed state, it just delimits/completes the 'pressed' action. It also seemed weird to have a for/while loop inside the loop() statement, creating somewhat of a nested loop. | The realization with this version was that there are actually not 3 states, but more like 2 & 1/2. Counting the 'waiting' period as state 1, pressed as state 2 - but the 'released' state not being an actual state in itself, rather the un-doing of the 'pressed' one. To paraphrase, you can't really 'hold' the unpressed state, it just delimits/completes the 'pressed' action. It also seemed weird to have a for/while loop inside the loop() statement, creating somewhat of a nested loop. | ||
Line 23: | Line 23: | ||
With that in mind, I built a simple IF structure (could easily of been a case/switch) that changes states depending on the previous state, and button position. Since all the combinations have discrete properties, it is possible to only mark the difference in state change, and let the loop run 'in between the cracks' (i.e. when none of the conditions are met) of the program, triggering only the recording function when we need it. | With that in mind, I built a simple IF structure (could easily of been a case/switch) that changes states depending on the previous state, and button position. Since all the combinations have discrete properties, it is possible to only mark the difference in state change, and let the loop run 'in between the cracks' (i.e. when none of the conditions are met) of the program, triggering only the recording function when we need it. | ||
So the 'state' var controls the flow of recordings. | So the 'state' var controls the flow of recordings here. | ||
I've somewhat compacted the variables and code a bit for readability, sorry. | I've somewhat compacted the variables and code a bit for readability, sorry. | ||
<source lang="C"> | <source lang="C"> | ||
const int b = 2; | const int b = 2; //button pin | ||
int bs=0; | int bs=0; //button state | ||
int state=0; //0 is waiting, 1 is pressed, 2 is released | int state=0; //0 is waiting, 1 is pressed, 2 is released | ||
boolean sr=false; | boolean sr=false; //started recording? | ||
int t[100]; //recordings array | |||
int t[100]; | int c=0; //counter index for recordings | ||
int c=0; | |||
void setup() { | void setup() { | ||
pinMode(b, INPUT); | pinMode(b, INPUT); | ||
Serial.begin(9600); | |||
Serial.begin(9600); | |||
Serial.println("Start recording..."); | Serial.println("Start recording..."); | ||
} | } | ||
void loop(){ | void loop(){ // all the heavy lifting is here | ||
bs = digitalRead(b); | bs = digitalRead(b); // read the state | ||
if(!sr){ if(bs==1) sr=true; }else{ | if(!sr){ if(bs==1) sr=true; }else{ // if user has started clicking, turn SR to true | ||
if(bs && state==0){ state=1; t[c] = millis(); c++; Serial.println("tstamped"); } | if(bs && state==0){ state=1; t[c] = millis(); c++; Serial.println("tstamped"); } //button pressed, last state : waiting | ||
if(!bs && state==1){ state=2; t[c] = millis(); c++; Serial.println("tstamped"); } | if(!bs && state==1){ state=2; t[c] = millis(); c++; Serial.println("tstamped"); } //button unpressed, last state : pressed | ||
if(!bs && state==2){ state=0; } | if(!bs && state==2){ state=0; } //button unpressed, last state : waiting | ||
if((millis() - t[c-1])>5000){ p(); } | if((millis() - t[c-1])>5000){ p(); } //check if there has been 5 secs of silence | ||
} | } | ||
} | } | ||
void p(){ | void p(){ //playback function | ||
Serial.println("Playing back"); | Serial.println("Playing back"); | ||
for(int a=1;a<c-1;a++){ | for(int a=1;a<c-1;a++){ | ||
tone(13, 600,t[a]-t[a-1]); | tone(13, 600,t[a]-t[a-1]); //play the tone | ||
delay(t[a+1]-t[a]); | delay(t[a+1]-t[a]); //wait | ||
} | } | ||
sr = !sr; | sr = !sr; //flush & clean | ||
memset(t,0,100); | memset(t,0,100); | ||
c=0; | c=0; | ||
Serial.println("You can start recording again"); | Serial.println("You can start recording again"); //start again | ||
} | } | ||
</source> | </source> |
Revision as of 15:43, 12 November 2010
Rough arduino pattern recorder/playback #1
Simple code to emulate a pattern recording device. It has a few little glitches, but the main idea works.
- Program starts
- User starts using pushbutton to determine a pattern (up to 100 clicks before array goes out of bounds)
- After 5 seconds of silence (there can be 1min at the beginning though, that's fine)
- Play the pattern back
- And then erase it from memory, begin recording again
HARD
- Piezo in ground/pin 13
- Pushbutton in 10K resistor => pin 2 / 5V power
SOFT
Self-resetting / state-run / compact / verbose version
The realization with this version was that there are actually not 3 states, but more like 2 & 1/2. Counting the 'waiting' period as state 1, pressed as state 2 - but the 'released' state not being an actual state in itself, rather the un-doing of the 'pressed' one. To paraphrase, you can't really 'hold' the unpressed state, it just delimits/completes the 'pressed' action. It also seemed weird to have a for/while loop inside the loop() statement, creating somewhat of a nested loop.
With that in mind, I built a simple IF structure (could easily of been a case/switch) that changes states depending on the previous state, and button position. Since all the combinations have discrete properties, it is possible to only mark the difference in state change, and let the loop run 'in between the cracks' (i.e. when none of the conditions are met) of the program, triggering only the recording function when we need it.
So the 'state' var controls the flow of recordings here.
I've somewhat compacted the variables and code a bit for readability, sorry.
const int b = 2; //button pin
int bs=0; //button state
int state=0; //0 is waiting, 1 is pressed, 2 is released
boolean sr=false; //started recording?
int t[100]; //recordings array
int c=0; //counter index for recordings
void setup() {
pinMode(b, INPUT);
Serial.begin(9600);
Serial.println("Start recording...");
}
void loop(){ // all the heavy lifting is here
bs = digitalRead(b); // read the state
if(!sr){ if(bs==1) sr=true; }else{ // if user has started clicking, turn SR to true
if(bs && state==0){ state=1; t[c] = millis(); c++; Serial.println("tstamped"); } //button pressed, last state : waiting
if(!bs && state==1){ state=2; t[c] = millis(); c++; Serial.println("tstamped"); } //button unpressed, last state : pressed
if(!bs && state==2){ state=0; } //button unpressed, last state : waiting
if((millis() - t[c-1])>5000){ p(); } //check if there has been 5 secs of silence
}
}
void p(){ //playback function
Serial.println("Playing back");
for(int a=1;a<c-1;a++){
tone(13, 600,t[a]-t[a-1]); //play the tone
delay(t[a+1]-t[a]); //wait
}
sr = !sr; //flush & clean
memset(t,0,100);
c=0;
Serial.println("You can start recording again"); //start again
}
(better than below)
const int buttonPin = 2;
const int nb=100;
int bs = 0;
int cs = 0;
unsigned long time;
int values[nb];
int c=0;
boolean startrec = false;
void setup() {
pinMode(buttonPin, INPUT);
tone(13,600,10);
Serial.begin(9600);
Serial.println("Start recording...");
}
void loop(){
bs = digitalRead(buttonPin);
time = millis();
char buffer[255];
if(cs!=bs){
startrec=true;
cs=bs;
values[c] = time;
sprintf(buffer,"Recorded : %d",time);
Serial.println(buffer);
c++;
}
if(startrec){
int deadtime = time-values[c-1];
if(deadtime>5000) playback();
}
}
void playback(){
Serial.println("Playing back");
int cc = 0;
for(int a=1;a<c-1;a++){
int playtime = values[a]-values[a-1];
int delaytime = values[a+1]-values[a];
tone(13, 600,playtime);
delay(delaytime);
}
Serial.println("Finished playing back");
delay(1000);
restart();
}
void restart(){
startrec = false;
memset(values,0,nb);
c=0;
Serial.println("You can start recording again");
}
(old version)
//globals
const int buttonPin = 2;
int values[100];
int c=0;
unsigned long time;
boolean startrec = false;
int buttonState = 1;
int newstate = 1;
void setup() {
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
void loop(){
//time counter
time = millis();
buttonState = digitalRead(buttonPin);
//this prevents the button from recording 2-3 times in the same push...
delay(10);
//if state has changed
if(buttonState != newstate){
startrec = true;
//store in the array, print to screen and increment array index
newstate = buttonState;
values[c] = time/100;
Serial.println(values[c]);
c++;
}
if(startrec){
//if it's been more than 5 seconds doing nothing, after you've started pushing
int deadtime = (time/100)- values[c-1];
if(deadtime > 50){
int cc = 0;
//loop through values, and interpret the time difference as delays
for(int a=0;a<c-1;a++){
tone(13, 600,10);
int dtime = (values[a+1]-values[a])*100;
delay(dtime);
}
//gimme something to look at
Serial.println("waiting 2 secs...replaying");
delay(2000);
}
}
}