User:Laurier Rochon/prototyping/arduino recorder: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
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?
unsigned long time;
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);
  tone(13,600,10);
   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);
   } 
  }
  
}