Skip to content

iShutter: Two Arduino’s Controlling A Video Projector

I finally completed my first “major” Arduino project which I’m dubbing iShutter.  Here’s the scenario:

Willow Creek South Barrington - Summit Day 2 Rehearsal
Willow Creek Community Church

The problem is that at Willow Creek Community Church, a large church with a theater-like stage, often uses a center rear-projection screen for graphical elements during the services. However, this screen is on a motorized batten so that during portions of the service where the screen is not needed, it is flown/raised out of sight, and lowered back in when needed.

However, the projectors sit on the ground at the rear of the stage.  The problem here is that when the screen is raised, if the projectors are not disabled/shuttered, the projection image will be projecting into everyone’s eyes…a quite undesirable scenario.  This shuttering of the projectors has been done manually up till now, but alas, Arduino to the rescue.

iShutter - Transmitter and Receiver Modules (Open large to see descriptions of each elements)
iShutter – TX & RX Modules

Introducing iShutter.  This consists of 2 Arduino Unoscommunicating to each other using the XBee chip.  In a nutshell, the transmit module attaches to the side of the projection screen and uses the PING Ultrasonic sensor aimed towards the ground to detect when the screen is at it’s lower limit.  Once this threshold has been passed, the transmit module then tells the receiver module to communicate via RS232 to the projector whether to open or close it’s shutter.  A button on the transmit box allows users to set the threshold limit.

So, screen lowers in, projector turns on. Screen raises out, projector turns off.

Features:

  • Wireless Transmission between two Arduino Uno control boards
  • 9v Powered Screen/Transmit Module
  • Audio Module to confirm threshold set (plays C chord on Transmit module, followed by a D chord on the receiver module to confirm communication)
  • LED Status Indicator (On TX and RX): Blue (Shutter Closed), Green (Shutter Open), Red (Threshold Not Set)
  • RS232 to Projector – Projector Specific RS232 code to talk directly to device
  • Relay Output of Status – Via Cat5, cabling travels 300ft form receiver module to Video Director to indicate tally of whether projector shutter is open/closed
iShutter - Transmitter Module (Open large to see descriptions of each elements)
iShutter – Transmitter Module (Open large to see descriptions of each elements)
iShutter - Receiver Module
iShutter – Receiver Module (Open large to see descriptions of each elements)

Learnings:

  • To help increase battery life on the transmitter module, I added the sleepPin logic to put the XBee to sleep when not in use, and only fire it up when a transmission is needed to be sent.
  • Had to dumb down the sensitivity of the PING ultrasonic sensor as it is extremely sensitive!
  • Needed to get a converter chip for RS232 to transmit the proper RS232 voltage so that the projector would see correct RS232!
  • Aluminum enclosures, while sexy looking, seriously decreases the wireless transmission distance! Sad – had to leave the covers off of the enclosures so that the wireless transmission would be solid.

Transmitter Arduino Code

const int pingPin = 7;
const int buzzerPin = 6;
const int buttonPin = 2;
const int redLedPin = 11;
const int greenLedPin = 10;
const int blueLedPin = 9;
const int sleepPin = 3;

long triggerDistance = 0; 
long curDistance = 0;
boolean shutterOpen = false;
int closeTolerance = 0;
int openTolerance = 0;
int pingAliveCount = 0;
long pingCount = 0;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  pinMode(sleepPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  LED(64,0,0);
  digitalWrite(sleepPin, HIGH);
}

void loop()
{
  if(digitalRead(buttonPin) == LOW) {
    digitalWrite(sleepPin, LOW);
    delay(15);
    Serial.print(49, BYTE);
    delay(10);
    Serial.print(10, BYTE);
    delay(10);
    digitalWrite(sleepPin, HIGH);
    setTriggerDistance();
    successSound();
    openShutter();
  }
  curDistance = getDistance();
  if(curDistance > triggerDistance && shutterOpen && closeTolerance > 0) {
    closeShutter();
  } else if ( curDistance <= triggerDistance && shutterOpen != true && openTolerance > 0) {
    openShutter();
  } else if (curDistance > triggerDistance && shutterOpen) {
    closeTolerance++;
  } else if (curDistance <= triggerDistance && !shutterOpen) {
    openTolerance++;
  } else {
    openTolerance = 0;
    closeTolerance = 0; 
  }
  delay(500);
}

void setTriggerDistance() {
  triggerDistance = getDistance();
  LED(0,64,0);
}
void openShutter() {
 digitalWrite(sleepPin, LOW);
 delay(15);
 Serial.print(50, BYTE);
 delay(10);
 Serial.print(10, BYTE);
 delay(10);
 LED(0,64,0);
 shutterOpen = true; 
 openTolerance = 0;
 closeTolerance = 0;
 digitalWrite(sleepPin, HIGH);
}
void closeShutter(){
 digitalWrite(sleepPin, LOW);
 delay(15);
 Serial.print(51, BYTE);
 delay(10);
 Serial.print(10, BYTE);
 delay(10);
 LED(0,0,64);
 shutterOpen = false; 
 openTolerance = 0;
 closeTolerance = 0;
 digitalWrite(sleepPin, HIGH);
}
void successSound(){
    tone(buzzerPin, 523, 200);
    delay(100);
    tone(buzzerPin, 659, 200);
    delay(100);
    tone(buzzerPin, 783, 200);
    delay(100);
    tone(buzzerPin, 1046, 200);
    delay(100);
    noTone(6); 
}

long getDistance(){
  long distance;

  // 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);
  distance = pulseIn(pingPin, HIGH);

  return distance / 512;
}

void LED(int red, int green, int blue) {
  analogWrite(redLedPin, red);
  analogWrite(greenLedPin, green);
  analogWrite(blueLedPin, blue);
}

Receiver Arduino Code

const int tallyPin = 5;
const int buzzerPin = 6;
const int redLedPin = 11;
const int greenLedPin = 10;
const int blueLedPin = 9;
int mode;

void setup() {
  Serial.begin(9600);
  pinMode(tallyPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  LED(20,0,0);
}

void loop()
{
  while(Serial.available()){ 
    int mode = Serial.read() - '0'; 
    switch(mode) {
      case 1:
         successSound();
         openShutter();
         break; 
      case 2:
         openShutter();
         break;
       case 3:
         closeShutter();
         break;
  }
  Serial.flush();
  } 
}
void openShutter() {

 Serial.print(0xfe, BYTE);
 Serial.print(0x01, BYTE);
 Serial.print(0x22, BYTE);
 Serial.print(0x42, BYTE);
 Serial.print(0x00, BYTE);
 Serial.print(0x65, BYTE);
 Serial.print(0xff, BYTE);
 Serial.print(0x0a, BYTE);
 LED(0,20,0);
 digitalWrite(tallyPin, HIGH);
}
void closeShutter(){
 Serial.print(0xfe, BYTE);
 Serial.print(0x01, BYTE);
 Serial.print(0x23, BYTE);
 Serial.print(0x42, BYTE);
 Serial.print(0x00, BYTE);
 Serial.print(0x66, BYTE);
 Serial.print(0xff, BYTE);
 Serial.print(0x0a, BYTE);
 LED(0,0,20);
 digitalWrite(tallyPin, LOW);
}
void successSound(){
    delay(500);
    tone(buzzerPin, 587, 200);
    delay(100);
    tone(buzzerPin, 740, 200);
    delay(100);
    tone(buzzerPin, 880, 200);
    delay(100);
    tone(buzzerPin, 1174, 200);
    delay(100);
    noTone(6); 
}

void LED(int red, int green, int blue) {
  analogWrite(redLedPin, red);
  analogWrite(greenLedPin, green);
  analogWrite(blueLedPin, blue);
}

More Photos

You can view more photos on the Flickr set.

Find this useful? Take just a moment and give a $1. Thanks!
Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
  • Brian

    So good

    [Reply]

  • Two780a

    How many projectors are blending on that center screen?

    [Reply]

    Sators reply on August 13th, 2011:

    Ya that’s a bad example.  The Arduino’s only typically speak to 1, though you could piggy back the signal to speak to many.  In the photo above, 6 projectors are used for the blending.

    [Reply]

  • Scotty

    Very nice!  What material could be used that would not block the transmission?

    [Reply]

    Sators reply on August 13th, 2011:

    Probably should have used a plastic enclosure…hindsight’s 20/20

    [Reply]

  • Regierungsbeamter

    nice Project. Why not attach some anttenna to the xbee? Does the battery fit into the enclosure or is attached external?

    [Reply]

  • Chanthu Sivachanthiran

    Vis

    [Reply]

  • Vis Kataboman

    I was trying to see how were your Arduino Code written for both transmitter and receiver. Do you think you can share ?

    [Reply]

    Sators reply on February 21st, 2017:

    Sorry about that! The service I was using to host code snippets shutdown Dec 31st…luckily I’m finding all of my code on the Wayback Machine! https://web.archive.org/web/20161101192218/https://snipt.net/sators/

    [Reply]

    Vis Kataboman reply on March 2nd, 2017:

    Thank you verymuch for making the link life again. I was going through your sketch code for both transmitter and receiver, I can visualise the code structure but can’t seems to understand how this code can work in the manner it’s intended. I even try to compile it (my apologies for not asking permission to copy your code) but, I am getting errors, neither will compile. I am in no doubt that you have got it working great. Can you please help me understand your code. Thanks in advance.

    [Reply]