Thursday, February 28, 2013

Storing data in arrays

Yesterday I posted about how my respiratory-musical interface gathers information from the analog sensors (sent via the lilypad) and read in through supercollider.

Today I will post how these values are stored for comparison.

For starters, recall that this code read the serial values in from the lilypad:

(

~serialReceive = Task({  //create a new task to get serial data

   inf.do({
        if(~myPort.notNil, { //if the serial port is notNil
                ~incData = ~myPort.next; //then assign the new incoming serial value to incData
                if(~incData.notNil, { //if the values coming in are notNil
                    ~incData.postln;//post them

                    });
          });
         0.1.wait;
      });
});

)

This next code adds on to this basic template.  First we need to add variables (inside the task, but outside the inf loop) for the array where we will store the data:


//6 sensors...1 zero 'message' to say that the array is over
var serialArraySize = 7; 


//make a new array (with space for serialArraySize number of values) for incoming serial data
var serialArray = Array.newClear(serialArraySize); 



Next, inside the inf loop, we will need to tell the serial array to constantly shift values to the left so that new values can replace the old as they are read in:


//make the serial array constantly shift to receive new data
serialArray = serialArray.shift(-1); 


And then we will need to tell the array what values it should storing:
//put the new values into the serial array
serialArray[serialArraySize - 1] = ~incData


Finally, we need to figure out when the analog values coming into the array are in the right position, so that the value for sensor 0 is in index 0 and sensor 1 is in index 1 and so on.  Remember we did this by making the array have one extra index that we fill with a message (a zero) that we can then use to tell our code that the array is complete.  

if(serialArray[serialArraySize - 1]==0, { 
       serialArray.postln; //post the serial array
    });




And we'll stop here to see this altogether:




(

~serialReceive = Task({  //create a new task to get serial data
 
        var serialArraySize = 7; 
        var serialArray = Array.newClear(serialArraySize); 

               inf.do({
                        if(~myPort.notNil, { //if the serial port is notNil
                                ~incData = ~myPort.next; //then assign the new incoming serial value to incData
                                 if(~incData.notNil, { //if the values coming in are notNil
                                        ~incData.postln;//post them

                                        //make the serial array constantly shift to receive new data
                                         serialArray = serialArray.shift(-1);
                                         //put the new values into the serial array
                                         serialArray[serialArraySize - 1] = ~incData;  

                                                 if(serialArray[serialArraySize - 1]==0, { 
                                                         //if sc receives the 0, the flag or message coming in from the arduino             
                                                         //and it is placed at the end of the serial array,
                         
                                                         serialArray.postln; //post the serial array

                           });
                 });
            0.1.wait;
           });
    });

)

The next step is to store these completed arrays as they come in so that it's possible to compare old sensor values with new ones to tell if there has been a breath.  Note that the time between an old value and a new one is *very* small--I've been setting it at tenth of a second or less.  

Wednesday, February 27, 2013

Breathing in Banff


For the past seven weeks I have been working on a new version of the Respiratory-Musical Interface in Banff, AB, as part of the Winter Creative Residency.  Somewhat belatedly, I wanted to return to posting updates about the project.  There is quite a lot to catch up with so I will try to post a very short code excerpt every day from now until I leave, rather than trying to get EVERYTHING into a single post.

*Apologies for the lack of formatting in the code...blogger seems to make that disappear when I copy and paste.  I'll look for a solution when I have a chance!

Anyway, for starters, here is the LilyPad Arduino code:


int message = 0;
int numSensors = 6; //number of analog sensors used
int sensorVal;
int sensorIn = 0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{

  for(int a=0; a<numSensors; a++) //loop through sensors 0 through 5
  {
    sensorVal = analogRead(a); //read sensor values at a
Serial.write(sensorVal/4); //IMPORTANT - USE Serial.write NOT serial.print or SC will have a bit of a FIT
  }

  Serial.write(message); //send message so SC can distinguish between serial values
// delay(175);
 delay(500);
}



The 'message' variable is there to help the SC side of the equation distinguish between the values coming in for the various pins from the LilyPad.  When it gets the message (a zero), it knows that the subsequent value it receives will be from analog pin 0.  (After receiving the zero it puts the next 7 values into an array in which the last index is the 0 message.)


Now, moving to SuperCollider, the most important part of the code below is assigned to the ~myPort variable, which tells SC where to find the serial values. SerialPort.listDevices justs lets you find the name of the proper device.



SerialPort.listDevices;
~myPort = SerialPort("/dev/tty.usbserial-A600dSr9", baudrate: 9600, crtscts: true);
~myPort.close
SerialPort.closeAll;

~pieceBegins = thisThread.seconds; //assign the start of the piece



After assigning the start of the piece, the next step is to actually read in some values from the analog sensors. The code below reads in data from the serialPort, ~myPort, assuming it is notNil, and then posts it.




(

~serialReceive = Task({  //create a new task to get serial data

   inf.do({
        if(~myPort.notNil, { //if the serial port is notNil
                ~incData = ~myPort.next; //then assign the new incoming serial value to incData
                if(~incData.notNil, { //if the values coming in are notNil
                    ~incData.postln;//post them

                    });
          });
         0.1.wait;
      });
});

)

~serialReceive.play;
~serialReceive.stop;

Tomorrow I will post the code that captures this data in an array, and perhaps the code that enables a comparison between old and new values from the sensors.