Video installation with sensor

Hi,

I'd like to run a film from a hard drive using a sensor so that the film starts playing when the viewer enters. I want the first frame to be projected as a still image until someone walks in, causing the video to begin playing. Afterwards, I want the film to return to the first frame, ready to play again when someone else enters. It'll be a really short film, about 30 seconds. I have coded for the sensor to control a digital out. How do I go about controlling a video file on a computer, using the arduino? Do I need any special equipment or software? No idea where to start looking. If someone could point me in the right direction, it'd be a big help.

Thanks.

I think that you may need to use Maxmsp for that

You need maxduino and using jitter max mps with jit.qt movie and also use message commad for go frame $1 (see help for jit qt.movie on max msp)

You could also use a language called Processing, this has the advantage over the other suggestions of being free.

Hi guys. I have since got something to run in Processing, with the film split into stills at 25fps. Both Processing and Arduino sketches run fine with a push button, but I'm having trouble adapting the code to get Processing to read the PING as a switch. I want arduino to trigger processing when the distance is less than 33 inches. Have been on this for days. Any ideas where I'm going wrong? I know it's quite an old post, so will repost if I don't hear back.

Thanks for your help,

Ben.

Code adapted from: http://www.arduino.cc/en/Tutorial/Ping

// this constant won't change. It's the pin number
// of the sensor's output:
const int pingPin = 4;

void setup() {
Serial.begin(9600);
pinMode(pingPin, INPUT);

}

void loop()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches;

// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);

// Serial.println(duration); // Print value to serial monitor

// If there is a an object less than 33 inches from the sensor send 1 to
// processing, otherwise send 0. (Number of microseconds divided by 74
// gives ms per inch. Half this value gives the distance of the object)

if (duration / 74 / 2 < 32)
{
Serial.print(1, BYTE);
} else {
Serial.print(0, BYTE);
}
delay(100);
}

Any ideas where I'm going wrong?

Well, you didn't tell us what the problem is.

Open the Serial Monitor, instead of Processing. Do you see the 0 and 1 appear there? Probably not, since 0 and 1 are not ASCII characters. So, the question becomes why are you sending the values as bytes instead of characters?

What does your Processing code look like? It's difficult to diagnose a sender/receiver problem when you only post the sender code and don't describe the problem.

Ok. Processing code is below, as is original pushbutton code for arduino. Am not getting anything in the serial monitor. I am using bytes because the code I had for a push button sends bytes, and this worked perfectly with the processing code so I thought I could just change the if statement? I haven't yet learned about ASCII. Can you explain why I need to use these instead?

Thanks,

Ben.

// import libraries
import processing.serial.*; //  serial library

// define objects
Serial port; // define serial object

// variables 
int trigger= 0;  // has the ultrasonic been triggered?
int frames = 1; //  frame counter, so we know when we're at the end
int numOfFrames = 239; // the number of frames in your movie MINUS ONE
int val;      // Data received from the serial port

PImage[] theFrames = new PImage[240]; // array for PImages (still images of video)

void setup() {
  size( 787 , 576 );         // sub-DV size, smaller is better
  frameRate(25);                 // hopeful!
  

// load the stills
  for(int i=1; i<numOfFrames; i=i+1) { 
    theFrames[i] = loadImage("Collapse"+ nf((i),3) + ".jpg");  // change the filename of image here

    // test that they loaded
    if (theFrames[i] != null) {
      println("Loaded, " + getTheDate());  // debug
    }  
    else {
      println("Error loading the image, " + getTheDate());  // error report
    }
  }
  
  println(Serial.list()); // prints list of serial ports
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  
  // UNCOMMENT NEXT TWO LINES
  //  String portName = Serial.list()[1]; // chose the right one from the list that printed out
  // port = new Serial(this, portName, 9600);
}


void draw() {
 
  if (trigger == 1 && frames < numOfFrames) {          // if it's triggered
  image(theFrames[frames], 0, 0);              // draw the frame to the screen
   frames++;                                  // increment the frame number
    //   println("1 debug: frames =" + frames +" trigger =" + trigger ); // debug
  } 
  else if (frames == numOfFrames) {  // if we're at the end of the movie
    frames = 1;              // reset frame counter to first frame
    image(theFrames[frames], 0, 0);        // draw the frame to the screen
    trigger =0;              // no longer triggered
 

    //  println("2 debug: frames =" + frames +" trigger =" + trigger ); // debug
  } 
  else {                     // if we're waiting to be triggered
      image(theFrames[frames], 0, 0);        // draw it
    frames = 1;                      // set frames to 0
    //  println("3 debug: frames =" + frames +" trigger =" + trigger ); // debug
  }
 
  // Triggering code currently set up to respond to key press.  
  if (keyPressed == true) {
    trigger = 1;
   // player.play();
  }
  
//  // Serial read code. Uncomment this block when you're all connected.
//  if ( port.available() > 0) {  // If data is available,
//    val = port.read();         // read it and store it in val
//  }
//  
//  if (val != 0) {              // If the serial value is not 0,
//     trigger = 1;
//  } 

}


String getTheDate() {
  int s = second();  // Values from 0 - 59
  int m = minute();  // Values from 0 - 59
  int h = hour();    // Values from 0 - 23
  int d = day();    // Values from 1 - 31
  int mon = month();  // Values from 1 - 12
  int y = year();   // 2003, 2004, 2005, etc.

  return(nf(h, 2) + ":" +nf(m, 2)+":"+ nf(s, 2) + ", " + d +"/"+mon+"/"+y);
}
/*

// Wiring / Arduino Code
// Code for sensing a switch status and writing the value to the serial port.

int switchPin = 4;                       // Switch connected to pin 4

void setup() {
  pinMode(switchPin, INPUT);             // Set pin 0 as an input
  Serial.begin(9600);                    // Start serial communication at 9600 bps
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {  // If switch is ON,
    Serial.print(1, BYTE);               // send 1 to Processing
  } else {                               // If the switch is not ON,
    Serial.print(0, BYTE);               // send 0 to Processing
  }
  delay(100);                            // Wait 100 milliseconds
}

*/

Moderator edit, on a mission to eliminate italics in software listings. AWOL

In your Processing sketch, you declare a variable of type Serial, but you never assign it a value. In addition, you are not providing a serialEvent callback. How can you expect to read serial data without doing these two steps?

Code needs to be posted using the # button, which includes tags that the forum uses to prevent characters in a post from being interpreted. The sequence of characters [, i, and ] in your code tell the forum software to display the rest of the text in italics. Makes understanding what you are trying to do with that array kind of hard.

just to add another possible solution, that may be much simpler if you want to add different videos.
There are a lot of VJ software or Multitrack Audio/Video software, which accept MIDI signals as triggers. (for ex, on a C 4th octave play the video n°2, on E play n°4 ect..)
sending MIDI notes out of Arduino is really simple. Hardware part is very simple too.
This way (maybe for future installations) you can have different sensors, each one triggering different Videos, just adding another Note generated by another sensor (maybe 6 lines of code more.)

I'd go with dab77's solution, seems simpler and more elegant than manually messing around with all the internals.

--------------------------------------------------------
Iron Realms Entertainment games: Achaea, Aetolia, Imperian, Lusternia and Tears of Polaris scam:
Ripoff Report | Iron Realms En Review - Mill Valley, California

HI: Could you please post the code for the video out? I'm working on a sound unit to play when a viewer crosses a sensor. And, what kind of sensor are you using? IR? Any suggestions? Thanks kindly, :slight_smile:

Hi ProfAnita,

Only just revisited this post so not sure if it's still relevant to you ... but, the code I was using also had audio (which I didn't post because mine was silent). I can post it if helpful, so that you can take out the bits that apply to you. Alternatively, I ended up using a relay switch to trigger a DVD player when the viewer passed a sensor. It was a bit clumsy for my installation (since there was a symbol from the DVD player that appeared in the projection whenever the switch was triggered), but since yours is purely audio, this might be a good workaround for you.

Also, thanks to all those that posted replies. I've been using MaxMSP for the past few months and only really tried Processing once before but feel I want to learn to code, so am getting into Processing alongside learning C++. Just wanted to say how great it is that this is available open source.