Monday, December 31, 2012

Supervillain Cape for BeagleBone


I got my BeagleBone a couple of months ago, just as the Cape Design Competition was being launched.  Since I planned on building my own cape as I learned my way around the Bone, why not try to enter a design?

I'm an absolute beginner when it comes to embedded Linux and building my own hardware.  I ordered the only BeagleBone book that I was able to find, but the release date keeps getting pushed back.  I watch and re-watch every video tutorial that I can find (thanks Derek Molloy and Shane B. for your contributions), but progress is painfully slow.

I can't read or draw a schematic diagram and haven't had the time to figure out how, yet.  I can't enter the competition, but I would like to ask all you BoneHeads out there to share what you know.  Write tutorials and post tips assuming that the reader has very little clue as to what you're talking about.

Explain how to install and run the scripts and libraries that you share.  Please give step-by-step instructions, especially when using the command line.


The Bone

Shake well with ice:

• 2 oz. Wild Turkey rye (or other 100-proof rye or bourbon)
• 1 teaspoon fresh-squeezed lime juice
• 1 teaspoon simple syrup (made with equal parts sugar and water)
• 3 dashes Tabasco sauce

Strain into chilled tall shot glass and serve.

A cocktail created by David Wondrich.

Thursday, October 11, 2012

RemoteCamera

This is an Arduino-based camera that sends images wirelessly to your computer. In addition to the Grove base shield - used to connect the camera module, a button and an LED light to the Arduino - we need an SD card shield to save the photos we take, and a Bluetooth shield to send the images off.

A Processing sketch on the computer receives the sent picture, saves it to the hard drive and displays it in the program window. In addition to using the hardware button connected to the Arduino, photos can be taken directly from the computer using the on-screen button or the space bar.

This camera will be part of a garden explorer robot that I'm building, inspired by the Mars Curiosity rover. I'll be adding a time-lapse feature and motion trigger.

Parts:
-Ardiuno Uno R3
-Seeed SD Card Shield
-Seeed Bluetooth Shield
-Grove Base Shield
-Grove Serial JPEG Camera
-Grove Button
-Grove LED
-Grove 4-Pin Cables
-Battery Pack
Suppliers:
Trossen Robotics
Epic Tinker
Seeed Studios

Make sure your portName in the Processing sketch matches the blueToothName in Arduino. And, please make sure this name sticks out - don't just name them "Bluetooth" - or the automatic selector might open the wrong port.

The Arduino sends out a series of 3-letter commands to let Processing know how to update the on-screen status and when to start and stop saving the received jpeg ("CAM" when the camera has finished taking its picture, "PIC" when it starts sending jpeg data and "EOF" at the end of the file). I plan on having error messages sent this way, too.

Photos are saved sequentially in a folder called "rcamera" on the SD card. The Processing sketch creates a new time-stamped folder for each session. These are also kept in "rcamera" within the remotePhoto sketch folder.


Arduino:
 #include <SD.h>  
 #include <SoftwareSerial.h>
  
 File photoFile, textFile;
  
 const int blueToothRx = 6;  
 const int blueToothTx = 7;  
 SoftwareSerial blueToothSerial(blueToothRx,blueToothTx);
 String blueToothName = "DreaduinoBluetooth";
  
 const int photoButtonPin = 5;  
 const int ledPin = 4;  
 const int sdCardPin = 10;               // cs pin of sd card shield
  
 const int photoBufferSize = 96;  
 unsigned int photoSize = 0;  
 int readData = 0;  
 boolean firstPhoto = true;  
 int photoNumber = 0;  
 char photoName[] = "rcamera/pic00000.jpg";  

 char cameraReset[] = {  
  0x56,0x00,0x26,0x00};                  // reset camera  
 char cameraCapture[] = {     
  0x56,0x00,0x36,0x01,0x00};             // take picture  
 char cameraContinue[] = {        
  0x56,0x00,0x36,0x01,0x02};             // take next picture  
 char cameraGetSize[] = {  
  0x56,0x00,0x34,0x01,0x00};             // read jpg file size  
 char cameraGetData[] = {                // read jpg data  
  0x56,0x00,0x32,0x0c,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a};

   
 void setup()  
 {  
  Serial.begin(115200);
   
  pinMode(blueToothRx, INPUT);  
  pinMode(blueToothTx, OUTPUT);  
  pinMode(photoButtonPin,INPUT);  
  pinMode(ledPin,OUTPUT);  
  pinMode(sdCardPin,OUTPUT);
   
  blueToothSetup();  
  sdCardSetup();  
  checkLastFile();  
  readLastFile();  
  cameraSetup();  
  ledFlash();   
 }   


 void loop()  
 {   
  readPhotoPin();  
  readBlueTooth();   
 }  
 void readPhotoPin()   
 {   
  if(digitalRead(photoButtonPin) == HIGH){  
   delay(50);                                //debounce  
   if(digitalRead(photoButtonPin) == HIGH){  
    takePhoto();    
   }  
  }   
 }

  
 void readBlueTooth()  
 {   
  if (blueToothSerial.available()) {   
   readData = blueToothSerial.read();  
   if (readData == 80)takePhoto();   
  }  
 }  


 void takePhoto()   
 {  
  if(firstPhoto) {  
   cameraCaptureImage();  
   firstPhoto = false;  
  }  
  else cameraContinueCapture();
  
  ledFlash();  

  cameraReadData(); 
 
  ledFlash();  
 
  sendPhoto(); 
 
  ledFlash();   
 }    


 void savePhoto(File &photoFile,int toBeReadSize)  
 {  
  char readSize = 0;  
  for(char i = 0;i < 5;i ++){      //read "ready to send" signal  
   Serial.read();  
  }  
  while(readSize < toBeReadSize){  //read and store the jpeg data  
   photoFile.write(Serial.read());  
   readSize++;  
  }  
  for(char i = 0;i < 5;i ++){      //read "sussessfully sent" signal  
   Serial.read();  
  }  
 }  


 void sendPhoto()  
 {   
  Serial.println("sending photo");      
  blueToothSerial.print("PIC"); 
 
  File photoFile = SD.open(photoName);
  
  if (photoFile) {  
   ledOn();  
   while (photoFile.position() < photoFile.size()) {  
    blueToothSerial.write(photoFile.read());     
   }  
   photoFile.close();
    
   Serial.println("photo sent");      
   blueToothSerial.print("EOF");
  
   saveLastFile(); 
 
   ledOff();   
  }   
  else {  
   Serial.println("error sending photo");  
  }           
 }  


 ////////////////////////////////////////////////////////////////////////////  
 // bluetooth  


 void blueToothSetup()  
 {  
  blueToothSerial.begin(115200);  
  blueToothSerial.print("\r\n+STBD=115200\r\n ");   
  blueToothSerial.print("\r\n+STWMOD=0\r\n");                 // set bluetooth to work in slave mode   
  blueToothSerial.print("\r\n+STNA="+blueToothName+"\r\n");   // set bluetooth name  
  blueToothSerial.print("\r\n+STOAUT=1\r\n");                 // permit paired device to connect  
  blueToothSerial.print("\r\n+STAUTO=0\r\n");                 // auto-connection should be forbidden here  
  delay(2000);                                                // required delay  
  blueToothSerial.print("\r\n+INQ=1\r\n");                    // make bluetooth inquirable   
  Serial.println("dreaduino bluetooth is inquirable");   
  delay(2000);                                                // required delay  
  blueToothSerial.flush();  
 }

  
 ////////////////////////////////////////////////////////////////////////////  
 // sd card  


 void sdCardSetup()  
 {   
  Serial.println("initializing sd card"); 
  
  if (!SD.begin(sdCardPin)) {  
   Serial.print("initialzation failed");  
   return;  
  }   
  Serial.println("sd initialization done");   
 }  
 void checkLastFile()   
 {  
  if (!SD.exists("rcamera/lastfile.txt")) {  
   SD.mkdir("/rcamera");  
   textFile = SD.open("rcamera/lastfile.txt", FILE_WRITE);  
   textFile.seek(0);    
   textFile.write(photoName);  
   textFile.close();   
  }    
 } 

 
 void readLastFile()  
 {  
  textFile = SD.open("rcamera/lastfile.txt", FILE_READ);  
  for (int i=0; i < 16; i++){  
   photoName[i] = textFile.read();     
  } 
  textFile.close(); 
  photoNumber = ((photoName[11]-48)*10000);  
  photoNumber = photoNumber + ((photoName[12]-48)*1000);  
  photoNumber = photoNumber + ((photoName[13]-48)*100);  
  photoNumber = photoNumber + ((photoName[14]-48)*10);  
  photoNumber = photoNumber + ((photoName[15]-48));      
  photoNumber ++;   
 } 

 
 void saveLastFile()  
 {  
  textFile = SD.open("rcamera/lastfile.txt", FILE_WRITE);  
  if(!textFile){  
   Serial.println("failed to open text file");  
  }  
  else{  
   textFile.seek(0);    
   textFile.write(photoName);  
  }  
  textFile.close();   
 }

  
 ////////////////////////////////////////////////////////////////////////////  
 // serial camera 

 
 void cameraSetup()  
 {   
  sendCameraCmd(cameraReset,4);  
  delay(1000);  
  while(Serial.available() > 0)Serial.write(Serial.read());  
  Serial.println("camera initialization done");  
 } 

 
 void cameraCaptureImage()  
 {   
  sendCameraCmd(cameraCapture,5);  
  delay(50);  
  while(Serial.available()){  
   Serial.read();  
  }  
 }  


 void cameraContinueCapture()  
 {  
  sendCameraCmd(cameraContinue,5);  
  delay(50);  
  while(Serial.available() > 0){  
   Serial.write(Serial.read());  
  }  
 }  


 void cameraReadData()  
 {  
  unsigned int photoSize;  
  sendCameraCmd(cameraGetSize,5);  
  delay(50);  
  for(char i = 0; i < 7; i++){  
   Serial.read();  
  }  
  photoSize = 0;  
  int high = Serial.read();  
  photoSize |= high ;  
  int low = Serial.read();  
  photoSize = photoSize << 8 ;  
  photoSize |= low ;
  
  unsigned int addr = 0;  
  cameraGetData[8] = 0;  
  cameraGetData[9] = 0;
  unsigned int count = photoSize / photoBufferSize;  
  char tail = photoSize % photoBufferSize;  
  cameraGetData[13] = photoBufferSize;  

  photoName[11] = photoNumber/10000 + '0';  
  photoName[12] = photoNumber/1000 + '0';  
  photoName[13] = photoNumber/100 + '0';  
  photoName[14] = photoNumber/10 + '0';  
  photoName[15] = photoNumber%10 + '0'; 
 
  Serial.println("saving photo");      
  blueToothSerial.print("CAM"); 
 
  photoFile = SD.open(photoName, FILE_WRITE);  
  
  ledOn();
  
  if(!photoFile){  
   Serial.println("failed to open photo file");  
  }  
  else{  
   for(char i = 0; i < count; i++){      //get and save count*photoBufferSize data  
    sendCameraCmd(cameraGetData,16);  
    delay(10);  
    savePhoto(photoFile, photoBufferSize);  
    addr += photoBufferSize;  
    cameraGetData[8] = addr >> 8;  
    cameraGetData[9] = addr & 0x00FF;  
   }  
   cameraGetData[13] = tail;               //get rest of the image data  
   sendCameraCmd(cameraGetData,16);  
   delay(10);  
   savePhoto(photoFile, tail);     
  }  
  photoFile.close();
  
  ledOff();  

  photoNumber ++;    
 }  
 void sendCameraCmd(char cmd[] ,int cmd_size)  
 {  
  for(char i = 0; i < cmd_size; i++)Serial.print(cmd[i]);   
 }

  
 ////////////////////////////////////////////////////////////////////////////  
 // led light  


 void ledOn()  
 {  
  digitalWrite(ledPin,HIGH);   
 }  


 void ledOff()  
 {  
  digitalWrite(ledPin,LOW);   
 }  


 void ledFlash()  
 {  
  digitalWrite(ledPin,HIGH);   
  delay(60);   
  digitalWrite(ledPin,LOW);   
  delay(60);   
  digitalWrite(ledPin,HIGH);   
  delay(60);   
  digitalWrite(ledPin,LOW);  
  delay(60);   
 }  

Processing:
 import processing.serial.*;  
 import controlP5.*;
  
 Serial dreadPort;  
 OutputStream output;  
 PImage img;

 ControlP5 controlP5;  
 Button photoButton;  
 PFont font = createFont("Arial", 14);
  
 String photoName;  
 String photoNameNumber;  
 int photoNumber = 1;  
 boolean cameraSave = false;  
 boolean photoOpen = false;  
 boolean photoSwitch = false;
  
 String filePath = "remoteCamera";  
 String fileStatus;  
 String folderName = timeStamp();

 int frameLocationX = 50;  
 int frameLocationY = 50;  
 int frameLocationSet = 0;
    
 String[] serialString;  
 String serialCheck;  
 String portName = "DreaduinoBluetooth";  
 int portNumber;  
 int serialIndex;
  
 int dataIn = 0;  
 int charC = 67;  
 int charA = 65;  
 int charM = 77;  
 int charP = 80;  
 int charI = 73;  
 int charE = 69;  
 int charO = 79;  
 int charF = 70;  
 int[] checkData = new int[3];  
 int[] checkEOF = new int[3]; 

 
 void setup()  
 {  
  size(640, 580);  
  background(40);   
  frame.setResizable(true);
  
  findSerialPort();
  
  dreadPort = new Serial(this, Serial.list()[portNumber], 115200);  
  dreadPort.clear();
  
  setupControlP5();
  
  statusUpdate(); 
 
  println("remoteCamera");  
  println("ready");  
 }  


 void draw()   
 {  
  if (frameLocationSet < 2) {  
   frame.setLocation(frameLocationX, frameLocationY);  
   frameLocationSet ++;  
  }   
  if (photoSwitch) remotePhoto();  
 } 

 
 void serialEvent(Serial myPort)   
 {   
  dataIn = myPort.read();
  
  checkData[2] = checkData[1];  
  checkData[1] = checkData[0];  
  checkData[0] = dataIn; 
 
  if (checkData[2] == charC && checkData[1] == charA && checkData[0] == charM) {    
   photoNameNumber = nf(photoNumber, 5);  
   photoName = ("img" + photoNameNumber + ".jpg");  
   filePath = (folderName + "/" + photoName);  
   println("saving");  
   cameraSave = true;  
   statusUpdate();  
  } 
 
  if (checkData[2] == charP && checkData[1] == charI && checkData[0] == charC) {    
   println("sending");  
   openPhoto();  
   return;  
  } 
 
  if (photoOpen) writePhoto();  
 }  


 void findSerialPort()  
 {  
  serialString = Serial.list(); 
 
  println(serialString);   

  for (int i = serialString.length - 1; i > 0; i--) {  
   serialCheck = serialString[i];  
   serialIndex = serialCheck.indexOf(portName);
  
   if (serialIndex > -1) portNumber = i;  
  }  
 }  


 void statusUpdate()   
 {  
  noStroke();  
  fill(40);   
  rect(0, 481, 640, 100);
  
  fill(255);  
  text(filePath, 300, 512);
   
  if (cameraSave) fileStatus = "saving";
  
  if (photoOpen) fileStatus = "sending"; 
 
  if (!cameraSave && !photoOpen) fileStatus = "ready";
   
  fill(255);  
  text(fileStatus, 300, 547);  
 }  


 void openPhoto()   
 {  
  if (!photoOpen) {  
   cameraSave = false;  
   photoOpen = true;  
   output = createOutput("rcamera/" + filePath);  
   statusUpdate();  
  }  
 }  


 void writePhoto()   
 {  
  try {  
   output.write(dataIn);  

   checkEOF[2] = checkEOF[1];  
   checkEOF[1] = checkEOF[0];  
   checkEOF[0] = dataIn;  

   if (checkEOF[2] == charE && checkEOF[1] == charO && checkEOF[0] == charF) {    
    closePhoto();  
    println(photoName + " received");  
    println("ready");  
    photoOpen = false;  
    statusUpdate();  
   }  
  }  
  catch (IOException e) {  
   e.printStackTrace();  
  }  
 }  

 
 void closePhoto()   
 {  
  try {  
   output.flush();  
   output.close();
  
   photoOpen = false; 
 
   statusUpdate();
  
   photoNumber ++;
  
   displayPhoto();  
  }   
  catch (IOException e) {  
   e.printStackTrace();  
  }  
 }  


 void displayPhoto()   
 {  
  noStroke();  
  fill(40);   
  rect(0, 0, 640, 480); 
 
  img = loadImage("rcamera/" + filePath);  
  image(img, 0, 0);  
 } 

 
 void setupControlP5()  
 {  
  controlP5 = new ControlP5(this);  
  controlP5.setControlFont(font); 
 
  photoButton = controlP5.addButton("photo", 0, 120, 500, 58, 58);  
  photoButton.setSwitch(photoSwitch);  
  photoButton.setColorBackground(color(150, 0, 0, 255));  
 } 

 
 void controlEvent(ControlEvent theEvent)  
 {  
  if (theEvent.controller().name()=="photo") remotePhoto();  
 }  


 void remotePhoto() {  
  dreadPort.write('P');
  
  photoSwitch = false;  
 }  


 void keyPressed() {  
  if (key == ' ' && !photoSwitch) {  
   
   photoSwitch = true; 
 
   remotePhoto();  
  }  
 } 


 String timeStamp() {  
  String timestamp = year()+"_"+month()+"_"+day()+"_"+hour()+"_"+minute();  
  return timestamp;  
 }   

Wednesday, October 10, 2012

Arduino + Processing: Automatic Serial Port Selection

I find that using Bluetooth to connect an Arduino with Processing on a MacBook can be frustrating. The serial port number tends to jump around on me as I disconnect and reconnect. Since I want the first port on the serial list with my Arduino's name, I scan the list backwards - counting down in the 'for()' loop - using 'indexOf()' to search each line for the Arduino's name. If the line contains the text I'm looking for, that line number becomes the chosen port number. Once I've checked each port, the last port number assigned is the first Arduino on the list.

Processing:
 import processing.serial.*;  
   
 Serial dreadPort;  
   
 String[] serialString;  
 String serialCheck;  
 String portName = "DreaduinoBluetooth";  
 int portNumber;  
 int serialIndex;  
    
   
 void setup() {
  
  findSerialPort(); 
 
  dreadPort = new Serial(this, Serial.list()[portNumber], 115200);  
  dreadPort.clear();  
 }  
   
     
 void draw() {  
 }  
   
     
 void findSerialPort() {
  
  serialString = Serial.list();  
   
  println(serialString);   
   
  for (int i = serialString.length - 1; i > 0; i--) {  
   
   serialCheck = serialString[i];  
   serialIndex = serialCheck.indexOf(portName);  
   
   if (serialIndex > -1) portNumber = i;  
  }  
 }    

Sunday, October 7, 2012

Arduino + Processing: JPEG Serial Transfer

I had a hard time figuring out how to send a jpeg file, over serial, from Arduino's SD card to Processing on my laptop. In the end, I found something called 'createOutput' in Processing and that seems to get the job done:

-Run the Processing sketch.
-Press the Arduino button to start sending jpeg.
-When transfer is complete (LED turns off), press any key in Processing sketch to finish saving file.

Arduino:
 #include <SD.h>   
  
 File photoFile;   
 const int buttonPin = 7;   
 const int ledPin = 5;   
   
   
 void setup(){   
   
  Serial.begin(115200);   
   
  pinMode(buttonPin,INPUT);   
  pinMode(ledPin,OUTPUT);   
   
  //Serial.println("initializing sd card");   
  pinMode(10,OUTPUT);     // CS pin of SD Card Shield   
   
  if (!SD.begin(10)) {   
   Serial.print("sd initialzation failed");   
   return;   
  }   
  //Serial.println("sd initialization done");   
 }   
   
   
 void loop(){   
   
  while(1){   
   // Serial.println("press the button to send picture");   
   Serial.flush();     
   
   while(digitalRead(buttonPin) == LOW);   
   if(digitalRead(buttonPin) == HIGH){   
    delay(50);   
   
    if(digitalRead(buttonPin) == HIGH){   
     delay(200);   
     File photoFile = SD.open("pic02.jpg");   
   
     if (photoFile) {   
      while (photoFile.position() < photoFile.size()) {   
   
       digitalWrite(ledPin,HIGH);              
       Serial.write(photoFile.read());   
      }   
   
      photoFile.close();   
      digitalWrite(ledPin,LOW);    
     }    
   
     else {   
      Serial.println("error sending photo");   
     }         
    }   
    //Serial.println("photo sent");    
   }   
  }   
 }     

Processing:
 import processing.serial.*;  
   
 Serial myPort;  
 OutputStream output;  
   
   
 void setup() {  
   
  size(320, 240);  
   
  //println( Serial.list() );  
  myPort = new Serial( this, Serial.list()[0], 115200);  
  myPort.clear();  
   
  output = createOutput("pic02.jpg");  
 }  
   
   
 void draw() {  
   
  try {   
   while ( myPort.available () > 0 ) {  
    output.write(myPort.read());  
   }  
  }   
  catch (IOException e) {  
   e.printStackTrace();  
  }  
 }  
   
   
 void keyPressed() {  
   
  try {   
   output.flush(); // Writes the remaining data to the file  
   output.close(); // Finishes the file  
  }   
   
  catch (IOException e) {  
   e.printStackTrace();  
  }  
 }    

Dreaduino: Tinkering With Open-Source Hardware

Ciao. I have been playing with Arduino, the tiny Italian computer, for a few months now, and enjoying it thoroughly. This single-board microcontroller is meant to be easily modified into electronic hardware of your own design. Just plug in a few electronic inputs (buttons, knobs, motion sensors, etc.) and outputs (lights, buzzers, screens). Then, upload a program to the board’s flash memory telling Arduino what to do when a certain button is pressed or sensor reaches a specific reading.

The standard size and placement of the board’s connectors means that anyone can extend the functionality of Arduino by creating a “shield” – another circuit board that fits snugly on top and adds specific input and display options.

More importantly, Arduino is an open-source project with the board’s design and accompanying software given away freely. Anyone may build or program an Arduino clone or shield without risk of patent or copyright infringement.

I decided to begin my hardware adventures with a preassembled Arduino Uno R3 and Seeed Studio’s Grove base shield that makes use of 4-pin JST connectors to simplify the entire process of building a working electronic circuit. This way, I don’t need to bother with a soldering iron to get my prototypes working.

I have been learning a great deal as I struggle with a few projects that I’ll try to share through video and bits of code that I have managed to stitch together.

Tuesday, August 21, 2012

Phobos & Deimos


Another Vimeo weekend project - a theme is given on Friday, your creation must be uploaded by Tuesday. The brief this time was 'Wetter is Better', so I created this double moonrise over the Martian Riviera.

Thanks to Artie for the Curiosity Rover .blend file.

Music by Dub Nomads.

Sunday, May 13, 2012

SimpleVideoMixer

I have uploaded my first Processing sketch over at OpenProcessing.org.  It is a 2-channel video mixer with MIDI control, built on lessons learned from Joseph Gray's Processing  / Arduino video mixer tutorial.

-Place your video files in the "data/videos/" folder.

-Create a list of the video file names as a simple text file named "videoFileList.txt" and place it in the same "data/videos/" folder.

-Hold down the spacebar to record your mix.


I would like to build a full-featured VJ mixer for live performances, mixing video and audio-reactive Processing sketches.  The only problem is that Processing's video library does not allow for continuous looping of video clips at anything other than normal speed.  I had to use a convoluted bit of code to pause each frame of the video and re-sequence them at the speed and in the direction I want.  This all runs quite slowly and, at lower playback speeds, there is a "hiccup" that happens on my laptop.  It looks like the video actually plays a few frames before the pause and next jump, causing the sequence to stutter.

The Processing programming language is in the midst of an extensive update and I mentioned this problem to the creator of the GSVideo library that is being integrated into the code's core package.  He says that he has found a fix (something about catching the EOS event (?) from gstreamer and forcing a speed reset) that will be part of the next alpha release of Processing 2.0.   

The MIDI channels are from those found on the Numark DJ2GO USB mixer, but they can be reassigned to fit any hardware controller with both buttons and knobs (note and cc output).

There are still a few bugs that I haven't been able to squash:

-I sometimes get a "NullPointerException" when using the control window record button.  I don't seem to get it when holding down the spacebar to record the mix.  If the first recording in a session is made with the spacebar, the control window button seems to work fine after that.  And, sometimes the record button works fine right from the beginning.  The most frustrating part is I can't consistently recreate the error message.

-There seems to be a problem with the way that Processing exports this sketch as an applet.  I get an "UnsatisfiedLinkError" - something to do with gstreamer 0.10 - so, if you have Processing 1.5.1 already installed, be sure to download the GSVideo, controlP5 and themidibus external libraries (I had to rename the downloaded MIDI library simply "themidibus" for it to work).  Then just delete the "code" folder from the sketch and run "SimpleVideoMixer.pde".

Tuesday, March 13, 2012

Revo Lessons




It was 33 years ago today that the New Jewel Movement seized state power on the Caribbean island of Grenada – a textbook cold war revolution, but with several elements that gave it exciting potential.

Grenada is a small island with just over 100,000 people. On this scale, socialist theorists have an opportunity to rethink collective production and ownership without the size burdens of the Soviet model. These are an English-speaking people of African decent. What happens on Grenada can be easily shared with a large African-American and pan-African audience.

We tend to remember the Grenadian Revolution through the historical lens of its tragic demise; but, what lessons are there to be learned from all that was done right during this period?










Cuban Solidarity Poster (1982)
by Rafael Morante Boyerizo












GRENADA: The Future Coming Towards Us
-A documentary on the Grenadian Revolution.










The Grenada Tapes
-John Douglas (one of the "Future Coming Towards Us" filmmakers) has begun digitizing some of the tapes he made while living in Grenada.








The Grenada Revolution Online
-Learn the basics of the story of The Grenadian Revolution.







The Revo Blog

-Debi Alper's personal account of the Grenadian Revolution, the coup and U.S. invasion.






Freire in Grenada
-Professor Rich Gibson's analysis of Paulo Freire's Grenadian Literacy Project.







Working Out Grenada: An Interview with Merle Collins

-From Calabash Magazine.






Requiem for Revolution: Perspectives in the U.S. / OECS Intervention in Grenada
-by William Eric Perkins from Contributions in Black Studies.











-An audio reminder of the historical events of March 13, 1979.








The Lost Bishop Photos
-During the invasion, a U.S. paratrooper finds a box of books, pamphlets and unprocessed film in a drainage ditch. A few years later, he develops the film and is surprised to discover photos of Maurice Bishop, Unison Whitman and various scenes from the Revo years.









United States PSYOP in Grenada
-Sergeant Major Herbert A. Friedman (Ret.) outlines some of the Psychological Operations carried out by the U.S military during the invasion.









GRENADA: Rescued From Rape and Slavery
-Post-invasion comic book put out by the CIA.






The Grenada Documents
-A selection from the over five tons of documents collected by US armed forces during the invasion. This collection has been edited and released by the U.S. Department of Defense, ostensibly to show the inner workings of a hostile regime arming itself against the United States. It also makes an interesting read for anti-poverty activists who wish to see some of the activities of a state-run national development plan.










-In October 2011, the Grenada Arts Council hosted an exhibition: "The Grenada Revolution 1979-1983: Artists' Perspective."







Thursday, March 8, 2012

Saturday, February 25, 2012

iPhone Cinema

I have set up a new iPhoneArt.com group - iPhone Cinema - for sharing videos, time-lapses, animations, slideshows, animated GIFs, etc. Please join and post your creations, however short or random.

There are quite a few apps that let you record video with various filters and effects, but only two, that I know of - CinemaFXV and GameUrVideo - that allow processing of clips from your library. "Timelapse" is the only app of its kind that can import pictures from your camera roll. With ReelDirector (and iMovie, I believe) you can zoom and pan over still images (the so-called Ken Burns effect).

Consider leaning your phone on something solid or pressing it up against a window for steady shots. You may need to use the "Rotate Video" app to do just that.

If you're not a musician, but still want to create your own soundtrack, consider downloading some of the free drum machines and synthesizers that are out there. Use a 1/8" Male to 1/8" Male audio cable to connect the output of your phone (headphone jack) to the input of your computer (line/mic jack) and record your performance/sequence directly to an audio program, such as Audacity or GarageBand. Sync the exported track in iTunes to make it available for use in a video editing app, such as Vimeo or ReelDirector.

If you decide to invest in a few music-making apps - be warned, they can get quite expensive - try sticking with apps that allow AudioCopy and AudioPaste whenever possible. This will allow you to easily share performances between apps. For the musical novice, I suggest NodeBeat for automatic rhythms and Loopy for audio loops (a la Reggie Watts). ThumbJam is fun, even if you can't play an instrument. And, if you're already familiar with digital audio and multitrack production, NanoStudio is a good option.

Miles+Moog



Cellular Rhythm



Lifelines


Digital Tapestry

Thursday, February 9, 2012

Tuesday, February 7, 2012

Positive Vibration (High/22.05kHz/Noise/LogF)






Created on an iPod Touch.

Apps Used: APT-Pro, HoughCam, aremaC, Decim8, ArtStudio, Phonto, TimeFreeze, CinemaFXV, Vimeo.

The soundtrack contains an APT-Pro image. Use the settings above to see what you're hearing: