Posts | Comments

Planet Arduino

Archive for the ‘Project Files’ Category

Dec
28

Lilypad Arduino Passion Sensing Scarf

arduino, Lilypad, Lilypad Arduino, Project Files, RGB LED, Sensor, Soft Circuit Comments Off on Lilypad Arduino Passion Sensing Scarf 

My latest Instructable:  Lilypad Arduino Passion Sensing Scarf. This was my first time working with an Arduino Lilypad. I have been wanting to try something that dealt with soft circuits for awhile now. This project is what I came up with. The concept is based off my friend Ethan Dicks from theFusefactory.org’s emergent Sheep Sculpture project.

The Lilypad Interactive Passion Sensing Scarf works like so:

Scarf number one being worn by someone walking alone will light up with the color Blue for Lonely. When the wearer of scarf number two joins up with number one, the two scarves will sense each other and then light up Red for Love.

Future plans for capacitance touch: which will allow the colors to Pulsate for Passion if one wearer touches the other wearers scarf. View My Instructable

Share/Bookmark

This is a repost of a previous project. I am still working to get the older post back online from when we upgraded Wordpress.

The robot was basically built using a Parallax Boe Bot chassis. Rather than using the Basic Stamp we added an Arduino with a proto shield to control the robot functions.

You can use any type of chassis for this project. The robot moves about using a ping sonar and IR sensors to avoid running into any objects. As you can see in the video, it was a bit thrown off by our kitten. We added additional items such as a wireless camera that sends audio/video back to our TV.The original design for this was created by an Instructable’s member and can be found here.

Items you will need for this project:

Arduino Autonomous Robot

Arduino Autonomous Robot

The standard servo will be used to mount the Ping Rangefinder. This will give you a back and forth sweep motion as the robot travels around. The two continuous rotation servos are used for the wheels. You do not need to use the Parallax brand of servos, other brands will work. You may have to adjust the PWM values in the source code to go with the servos you are using.

It is also possible to use DC motors and edit the code, which would be considerably cheaper. You could use a SN754410 Quad Half H-Bridge to drive two DC motors. Tutorial for how to do this is available here.

The Arduino hook up is pretty simple. You will have the following:

  • Pin (Analog) 0: Left Sensor
  • Pin (Analog) 1: Center Sensor
  • Pin (Analog) 2: Right Sensor
  • Pin 5: Pan Servo
  • Pin 6: Left Drive Servo
  • Pin 7: Ultrasonic Rangefinder ( ‘Ping)))’ )
  • Pin 9: Right Drive Servo
  • Pin 11: Piezo Speaker
Shield Close-up

Shield Close-up

Radioshack sells an RC car battery as well as connector repair kit. You can solder the repair kit connector onto the shield, and then be able to hook up your battery to power the servos with. You can use a separate battery holder to power the Arduino.

Make all your connections onto the shield. This way everything can remain in place if you need to use your Arduino for something else and save you from needing to tear apart everything.

for power to the shield, you won’t need any extra filter capacitors since the 5V switching  regulator has them built in. We used a small project box to hold the battery in place, and was able to attach the wireless camera on top of it.

The Arduino and camera are power source 1, while the servos and sensors are power source 2 (the RC battery). A small piece of PVC pipe mounted onto a cable clip will help you to keep your wires all organized to a central point and be less likely to get caught or tangled up into something as the robot is moving around.

Arduino Sketch

// Begin Robot Code
int micVal;
int cdsVal;
int irLval;  // Left IR
int irCval;  // Center IR
int irRval;  // Right IR

int i;   // Generic Counter
int x;  // Generic Counter
int PLval;  // Pulse Width for Left Servo
int PRval;  // Pulse Width for Right Servo
int cntr;  // Generic Counter Used for Determining amt. of Object Detections
int counter; // Generic Counter
int clrpth;  // amt. of Milliseconds Of Unobstructed Path
int objdet;  // Time an Object was Detected
int task;  // Routine to Follow for Clearest Path
int pwm;  // Pulse Width for Pan Servo
boolean add;  // Whether to Increment or Decrement PW Value for Pan Servo
int distance;  // Distance to Object Detected via Ultrasonic Ranger
int oldDistance;  // Previous Distance Value Read from Ultrasonic Ranger

float scale = 1.9866666666666666666666666666667;  // *Not Currently Used*

int LeftPin = 6;  // Left Servo
int RightPin = 9;  // Right Servo
int PiezoPin = 11;  // Piezo
int PingServoPin = 5;  // Pan Servo
int irLPin = 0;            // Analog 0; Left IR
int irCPin = 1;            // Analog 1; Center IR
int irRPin = 2;            // Analog 2; Right IR

int ultraSoundSignal = 7; // Ultrasound signal pin
int val = 0;              // Used for Ultrasonic Ranger
int ultrasoundValue = 0;  // Raw Distance Val
int oldUltrasoundValue;  // *Not used*
int pulseCount;        // Generic Counter
int timecount = 0; // Echo counter
int ledPin = 13; // LED connected to digital pin 13

#define BAUD 9600
#define CmConstant 1/29.034

void setup() {
  Serial.begin(9600);
  pinMode(PiezoPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(LeftPin, OUTPUT);
  pinMode(RightPin, OUTPUT);
  pinMode(PingServoPin, OUTPUT);
  pinMode(irLPin, INPUT);
  pinMode(irCPin, INPUT);
  pinMode(irRPin, INPUT);
  for(i = 0; i < 500; i++) {
    digitalWrite(PiezoPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(PiezoPin, LOW);
    delayMicroseconds(1000);
  }
  for(i = 0; i < 20; i++) {
  digitalWrite(PingServoPin, HIGH);
  delayMicroseconds(655 * 2);
  digitalWrite(PingServoPin, LOW);
  delay(20);
  }
  ultrasoundValue = 600;
  i = 0;
}

void loop()
{
  //Scan();
  Look();
  Go();
}
void Look() {
  irLval = analogRead(irLPin);
  irCval = analogRead(irCPin);
  irRval = analogRead(irRPin);
  //if(counter > 10) {
    //counter = 0;
    //readPing();
  //}
  if(irLval > 200) {
    PLval = 850;
    PRval = 820;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
  }
  else if(irCval > 200) {
    PLval = 850;
    PRval = 820;
    x = 10;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
  }
  else if(irRval > 200) {
    PLval = 650;
    PRval = 620;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
  }
  else {
    x = 1;
    PLval = 850;
    PRval = 620;
    counter = counter + 1;
    clrpth = (millis() - objdet);
    if(add == true) {
      pwm = pwm + 50;
    }
    else if(add == false) {
      pwm = pwm - 50;
    }
    if(pwm < 400) {
      pwm = 400;
      add = true;
    }
    if(pwm > 950) {
      pwm = 950;
      add = false;
    }
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(pwm * 2);
    digitalWrite(PingServoPin, LOW);
    delay(20);
    readPing();
    if(ultrasoundValue < 500) {
      cntr = cntr + 1;
      switch(pwm) {
        case 400:
          x = 7;
          PLval = 650;
          PRval = 650;
          Go();
          break;
        case 500:
          x = 10;
          PLval = 650;
          PRval = 650;
          Go();
          break;
        case 600:
          x = 14;
          PLval = 850;
          PRval = 850;
          Go();
          break;
        case 700:
          x = 10;
          PLval = 850;
          PRval = 850;
          Go();
          break;
        case 950:
          x = 7;
          PLval = 850;
          PRval = 850;
          Go();
          break;
      }
    }
  }
  //Serial.print("clrpth: ");
  //Serial.println(clrpth);
  //Serial.print("objdet: ");
  //Serial.println(objdet);
  //Serial.print("cntr: ");
  //Serial.println(cntr);
  if(cntr > 25 && clrpth < 2000) {
    clrpth = 0;
    cntr = 0;
    Scan();
  }
}
void Go() {
  for(i = 0; i < x; i++) {
    digitalWrite(LeftPin, HIGH);
    delayMicroseconds(PLval * 2);
    digitalWrite(LeftPin, LOW);
    digitalWrite(RightPin, HIGH);
    delayMicroseconds(PRval * 2);
    digitalWrite(RightPin, LOW);
    delay(20);
  }
}
void readPing() {  // Get Distance from Ultrasonic Ranger
 timecount = 0;
 val = 0;
 pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output

/* Send low-high-low pulse to activate the trigger pulse of the sensor
 * -------------------------------------------------------------------
 */

digitalWrite(ultraSoundSignal, LOW); // Send low pulse
delayMicroseconds(2); // Wait for 2 microseconds
digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
delayMicroseconds(5); // Wait for 5 microseconds
digitalWrite(ultraSoundSignal, LOW); // Holdoff

/* Listening for echo pulse
 * -------------------------------------------------------------------
 */

pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
val = digitalRead(ultraSoundSignal); // Append signal value to val
while(val == LOW) { // Loop until pin reads a high value
  val = digitalRead(ultraSoundSignal);
}

while(val == HIGH) { // Loop until pin reads a high value
  val = digitalRead(ultraSoundSignal);
  timecount = timecount +1;            // Count echo pulse time
}

/* Writing out values to the serial port
 * -------------------------------------------------------------------
 */

ultrasoundValue = timecount; // Append echo pulse time to ultrasoundValue

//serialWrite('A'); // Example identifier for the sensor
//printInteger(ultrasoundValue);
//serialWrite(10);
//serialWrite(13);

/* Lite up LED if any value is passed by the echo pulse
 * -------------------------------------------------------------------
 */

if(timecount > 0){
  digitalWrite(ledPin, HIGH);
}
} 
void Scan() {   // Scan for the Clearest Path
  oldDistance = 30;
  task = 0;
  for(i = 1; i < 5; i++) {
    switch(i) {
      case 1:
        //Serial.println("Pos. 1");
        pwm = 1125;    ///  incr. by 100 from 1085
        break;
      case 2:
        //Serial.println("Pos. 2");
        pwm = 850; //// increased by 100 from 850
        break;
      case 3:
        //Serial.println("Pos. 3");
        pwm = 400;
        break;
      case 4:
        //Serial.println("Pos. 4");
        pwm = 235;
        break;
    }
    for(pulseCount = 0; pulseCount < 20; pulseCount++) {  // Adjust Pan Servo and Read USR
      digitalWrite(PingServoPin, HIGH);
      delayMicroseconds(pwm * 2);
      digitalWrite(PingServoPin, LOW);
      readPing();
      delay(20);
    }
    distance = ((float)ultrasoundValue * CmConstant);   // Calculate Distance in Cm
    if(distance > oldDistance) {  // If the Newest distance is longer, replace previous reading with it
      oldDistance = distance;
      task = i;   // Set task equal to Pan Servo Position
    }
  }
  //Serial.print("Task: ");
  //Serial.println(task);
  //Serial.print("distance: ");
  //Serial.println(distance);
  //Serial.print("oldDistance: ");
  //Serial.println(oldDistance);
  distance = 50;  // Prevents Scan from Looping
  switch(task) {   // Determine which task should be carried out
    case 0:  // Center was clearest
      x = 28;
      PLval = (850);
      PRval = (850);
      Go();
      break;
    case 1:  // 90 degrees Left was Clearest
      x = 14;
      PLval = (650);
      PRval = (650);
      Go();
      break;
    case 2:  // 45 degrees left
      x = 7;
      PLval = (650);
      PRval = (650);
      Go();
      break;
    case 3:  // 45 degrees right
      x = 7;
      PLval = (850);
      PRval = (850);
      Go();
      break;
    case 4:  // 90 degrees right
      x = 14;
      PLval = (850);
      PRval = (850);
      Go();
      break;
  }
}

// End Robot Code
Share/Bookmark
Bridge Passage,courtesy of Professor Tom Robbins, Architecture

Bridge Passage, photo courtesy of Professor Tom Robbins, Architecture

The bridge, “Passage” by L. Brower Hatcher at Columbus State, is one of the most outstanding and notable landmarks on campus. Connecting the main parking garage and Davidson Hall over Spring Street, the bridge offers safe passage above the fast moving one-way traffic below. Painted bright red, it also adds a strong visual contrast against the blue sky above and the green grass below.

The bridge contains many educational symbols and decorative metal icons mounted along the passage, which at one time were lighted at night by fiber-optics, creating a moving array of colors and light. This night-time light display has been noticeably absent for several years, apparently due to the mechanical failure of the high-powered “luminaries” which project colored light through the fiber optic cables.

Bridge Icons

Bridge Icons

As a class project, we designed a Solar Powered LED Lighting system to replace the existing outdated system that no longer works. (I can’t reveal the design yet here until things are approved) After thorough investigation, our class determined that the luminaries, located on the side of the bridge, most likely failed due to heat build-up, and possibly corrosion from exhaust and salt water mist from the traffic below. By contacting the vendor, we discovered that the 277 VAC model PH-3001 luminaries installed when the bridge was commissioned are no longer manufactured, and the replacement units would not be compatible with any of the PH-3001 units which still may be repairable on the bridge.  This means that to light the bridge again using the high-powered Metal-Halide luminaries, all 14 units would need to be replaced, at a minimum cost of $13,000.00 USD, not including labor.

It is also important to note, that the PH-3001 units are extremely difficult to maintain. Maintenance is very labor intensive, and consumes a large block of time for maintenance personnel who obviously have a multitude of other important tasks, maintaining a large campus the size of Columbus State. The bulbs burn out frequently, with a replacement cost of $211.00 each, or approximately $3000.00 USD per year. The units are also located in a difficult to reach location, and the fragile glass color wheels which require frequent cleaning and maintenance because of pollution from the traffic below, are easily damaged during maintenance.

Cost Benefit Analysis:

As noted earlier, the old Metal Halide lighting units are very labor intensive, and difficult to maintain. Due to heat buildup inside the enclosed units (Metal Halide bulbs run very hot), the bulbs would need to be changed yearly at a material cost of $3000.00 USD. Added to this amount would be a minimum of 28 hours of labor at $40 per hour, or $1120 in labor costs. The 14 units each consume approximately 200 watts of power per hour, or a total of $3.36 per day, $1226 per year. This would bring the approximate operating costs for the old lighting units to $3000 + $1120 + $1226 = $5346.00 per year operating cost.

Since the Solar Powered LED illuminated bridge runs off of the Sun’s energy, electrical costs and Carbon footprint would be Zero. LED light bulbs have an average MTBF (Mean time between failure) of 50,000 to 100,000 hours, or approximately 20 times that of the metal halide bulbs. By eliminating the mechanical rotating color wheels, valuable maintenance costs for an LED lighting system would be greatly reduced, to possibly only several hours per year. The estimated cost savings for the Solar Powered LED lighting system would be over $5000.00 USD per year.

So far the school has seemed to drag their feet with getting things done. Each day when I go to class and walk across the bridge I day dream about more stuff to add to the design which brings me to my original intent for this post, which is how to connect a PIR sensor to an Arduino.

The bridge has lighted square panels along the walkway. What I would like to see added is the ability for each panel to light up as a person gets close and then turn off as they move further away. This I feel will add to the cost savings since the walk way lights will only be in use at night when there is traffic on the bridge. If nobody is on the bridge, there is no need for them to be on at that time since the only purpose they serve is to see where you are walking.

Arduino with PIR Sensor

Arduino with PIR Sensor

Connecting a PIR sensor to an Arduino board can be done easily. PIR sensors consist of 3 pins, Vcc (Positive Voltage), Vss (Ground), and Signal. Interfacing it to the Arduino only requires +5v, GND and a digital input pin.

I put a short video clip on YouTube showing how the sensor works and the code is below.

I am thinking I could easily put together a small board and have each one located throughout the bridge with PIR sensors connected to them to control the individual squares. Or possibly have one central location for a control station and each PIR sensor runs to it.

Then as you walk, each panel will light up and turn off a few seconds later as you move away from it. The panels are staggered all the way down the walkway, so this would give a nice effect at night as someone is walking across the bridge.

Another thought I had was to tie all the walkway panels into one PIR at the entrance and one PIR at the exit of the bridge (maybe one in the middle also) and then the bridge would light up in 2-3 stages, rather than individual panels. Kind of boring, but serves its purpose for safety.

Additional Resources:

Parallax PIR Sensor Datasheet

Arduino PIRsense

Arduino Sketch:

// Parallax PIR sensor's output

//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;        

//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all motion has stopped
long unsigned int pause = 5000;  

boolean lockLow = true;
boolean takeLowTime;  

int pirPin = 3;    //the digital pin connected to the PIR sensor's output
int ledPin = 13;

//SETUP
void setup(){
  Serial.begin(9600);
  pinMode(pirPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(pirPin, LOW);

  //give the sensor some time to calibrate
  Serial.print("calibrating sensor ");
    for(int i = 0; i < calibrationTime; i++){
      Serial.print(".");
      delay(1000);
      }
    Serial.println(" done");
    Serial.println("SENSOR ACTIVE");
    delay(50);
  }

////////////////////////////
//LOOP
void loop(){

     if(digitalRead(pirPin) == HIGH){
       digitalWrite(ledPin, HIGH);   //the led visualizes the sensors output pin state
       if(lockLow){
         //makes sure we wait for a transition to LOW before any further output is made:
         lockLow = false;
         Serial.println("---");
         Serial.print("motion detected at ");
         Serial.print(millis()/1000);
         Serial.println(" sec");
         delay(50);
         }         
         takeLowTime = true;
       }

     if(digitalRead(pirPin) == LOW){
       digitalWrite(ledPin, LOW);  //the led visualizes the sensors output pin state

       if(takeLowTime){
        lowIn = millis();          //save the time of the transition from high to LOW
        takeLowTime = false;       //make sure this is only done at the start of a LOW phase
        }
       //if the sensor is low for more than the given pause, 
       //we assume that no more motion is going to happen
       if(!lockLow && millis() - lowIn > pause){
           //makes sure this block of code is only executed again after 
           //a new motion sequence has been detected
           lockLow = true;
           Serial.print("motion ended at ");      //output
           Serial.print((millis() - pause)/1000);
           Serial.println(" sec");
           delay(50);
           }
       }
  }
Share/Bookmark


  • Newsletter

    Sign up for the PlanetArduino Newsletter, which delivers the most popular articles via e-mail to your inbox every week. Just fill in the information below and submit.

  • Like Us on Facebook