Tuesday, April 28, 2015

Bangor Comic & Toy Convention!

This past weekend was the Bangor Comic & Toy Convention (BCTC), the first big Comic Con event for this area!  



The event ran from Friday thru Sunday and featured several famous folks that appeal to all ages!  They had Billy Dee Williams ("Lando Calrissian" from Star Wars), Deep Roy (the new Star Trek movies, Charlie & the Chocolate Factory), Gigi Edgley (Farscape), Doug Jones (Pan's Labyrinth, HellBoy movies), Ernie Hudson (Ghostbusters), Mark Ryan (voice of Bumblebee in "Transformers") and many more!  BCTC also had wrestler "Hacksaw" Jim Duggan and the Mighty Morphin Power Rangers (Red, Black, Blue and Yellow).

And for the Star Wars book readers out there, they had Timothy Zahn!

(Last fall, there was an Comic Con type event called "Bang Pop" but it didn't have much to offer.  They had one of the supporting stars from Battlestar Galactica, The Walking Dead and some comic artists.  I attended it for the cosplay contest and didn't stay long...there just wasn't much there.)

BCTC really had something for every walk of Science Fiction.

R2-D2 were invited to be a part of the 3-Day event and given a booth.  We would have a chance to meet the public and have people take photos with R2.

Show Prep

Before I could get R2-D2 to the show, I had to deal with the weather and my quirky, 13-year old Honda Odyssey.

After a very long winter with record snow fall, I was concerned my front yard would be too soft and muddy to drive onto.  I can only get R2-D2 out the front door!  While the snow had all melted off, a week of rain had be concerned.  I was afraid driving my van on the lawn would be like an X-Wing landing on Dagobah!

I also hadn't driven the van since November, so it had sat for months.  As luck would have have the battery was dead.  And...I noticed the inspection and registration had expired.  Nuts!  

I had my friend bring over his jumper cables and we were able to get my van to run.  After a night on a battery charger, we're back in business.

The lawn was extremely soft the morning of the event.  I left some deep impressions on the lawn from driving on it...but hoping those will flatten out!

The event was held at the Cross Insurance Center, which opened in 2013, replacing the old Bangor Auditorium and Civic Center.  Its a fantastic facility and draws in some excellent acts our previous facility could not support.  While the BCTC event is going on, a Monster Truck Show is going on as well!  

Getting unloaded and setup took some time, with many vendors and there as well as the Monster Trucks next door taking up a lot of room.  One of the Monster Truck teams was quite impressed to see R2-D2 come out of the van.  Meanwhile, I was completely impressed with their HUGE truck.  We chatted for a while, then I was able to wiggle R2-D2 into the building.


Once situated in my booth, I had R2 setup with plenty of time before the event started.  I had a chance to meet my "neighbors", some vendors from southern Maine and Timothy Zahn, a well-known author of many Star Wars books.  We had a chance to chat about many things, including the latest Star Wars 7 trailer.

Show time!

On Friday the show ran from 2pm to 6pm.  Pretty much from the start of the show to closing time, I had a steady line of visitors asking to take a picture with R2-D2, asking questions about how I built it, the R2 Builders Club and where they heard about R2 and I.  I was impressed to meet so many people that have followed our charitable efforts from news and print stories.  


Timothy Zahn, R2 and I
More show pictures from Days 1, 2 and 3.






Billy Dee Williams ("Lando") in the background!

Deep Roy





The show was a fantastic success and as I reflect on it a few days later...

1)  Have a partner to help out!  I missed all the discussion panels since I always had a line wanting to see R2-D2.  Bathroom breaks weren't too difficult, I could always ask one of the 501st troopers to guard R2!  But for a 3 day event, you need to give yourself a break here and there.  I need to do that next time!

2)  Always recharge the batteries each night.  One night I forgot to let the electronics battery recharge.  Thankfully a quick charge got me through the day but 8 hours of beeping noises and lights will eventually drain a battery!

3)  Have signs that say "No charge for photos".  The celebrities charged for autographed photos or pictures.  Of course, I do not...but was asked repeatedly.   It also wouldn't hurt to have some cards that link to my blog of Facebook Page for R2.


Wednesday, April 8, 2015

Part Two: Setting up the random HP movement for R2

First, I owe everyone an apology for two things!

1.  For forgetting to write the Part Two segment (Part One is here )

2.  How technical this entry will read.  

Last time I spoke about the random holoprojector (HP) movement, I detailed the hardware setup.  Figuring out how to make two servos link up to the HP on a stable mount was quite the task.  



Now how to make it all work.

The software for the random movement was made by an Astromech member by the name of Micke Askernas  Using an Arduino microcontroller, you copy and paste his program into the compiler, adjust the settings as detailed in the commented out sections, compile and upload the sketch to the Arduino microcontroller.

Here's the program, cut and paste into a new Sketch with the Arduino software.

/*
* SARLACC For Holo Projectors v 0.3a
*
* - Simple
* - Arduino
* - Random Holoprojector
* - Location for
* - AstroMech Builders
* - Club
* - Control
*
* Micke Askernäs, 2012
*
*/

#include

/*
* User defined constants
* change these for finetuning your servos
* *NOTE* These values are set for my servos.
* In order to get your system running smooth, you need to
* set your own values. See test code at the bottom of code.
*/

const int Min1X = 45; // Min value for X1 
const int Max1X = 150; // Max value for X1
const int Min1Y = 0; // Min value for Y1
const int Max1Y = 130; // Max value for Y1

const int Min2X = 20; // Min value for X2
const int Max2X = 150; // Max value for X2
const int Min2Y = 45; // Min value for Y2
const int Max2Y = 160; // Max value for Y2

const int Min3X = 0; // Min value for X3
const int Max3X = 180; // Max value for X3
const int Min3Y = 40; // Min value for Y3
const int Max3Y = 170; // Max value for Y3

const int MinTime = 1000; // Minimum time to wait before another servo movement.
const int MaxTime = 6000; // Maximum time to wait before another servo movement.

/*
* Arduino Pin Configuration
* Change these if needed
*/

const int servo1Xpin = 8; // PIN on Arduino used for Servo1X
const int servo1Ypin = 9; // PIN on Arduino used for Servo1Y
const int servo2Xpin = 10; // PIN on Arduino used for Servo2X
const int servo2Ypin = 11; // PIN on Arduino used for Servo2Y
const int servo3Xpin = 12; // PIN on Arduino used for Servo3X
const int servo3Ypin = 13; // PIN on Arduino used for Servo3Y

/*
* End Arduino Pin Configuration
*/

/*
* End constants
*/


/* No more changes should be needed below this line. */ 

Servo servo1X; // Define X-Servo 1 (Front)
Servo servo1Y; // Define Y-Servo 1 (Front) 
Servo servo2X; // Define X-Servo 2 (Top)
Servo servo2Y; // Define Y-Servo 2 (Top)
Servo servo3X; // Define X-Servo 3 (Back)
Servo servo3Y; // Define Y-Servo 3 (Back)
unsigned long currentTime;
unsigned long loopTime;

void setup()
{
servo1X.attach(servo1Xpin); // Attaching servo to defined pin.
servo1Y.attach(servo1Ypin); // Attaching servo to defined pin.
servo2X.attach(servo2Xpin); // Attaching servo to defined pin.
servo2Y.attach(servo2Ypin); // Attaching servo to defined pin.
servo3X.attach(servo3Xpin); // Attaching servo to defined pin.
servo3Y.attach(servo3Ypin); // Attaching servo to defined pin.

randomSeed(analogRead(0)); // Feed unhooked analog input as seed for randomizer. Can be set to static number.
// randomSeed(3141592653); // Static number random Seed (for explanantion only)

currentTime = millis();
loopTime = currentTime;
}

void loop()
{
currentTime = millis();

/* Loop 1 for Servo1 */
if (currentTime >= (loopTime + random(MinTime,MaxTime))) {
servo1X.write(random(Min1X,Max1X)); // Turn X-Servo to random X value (0-180)
servo1Y.write(random(Min1Y,Max1Y)); // Turn Y-Servo to random X value (0-180)
loopTime = currentTime; 
}

/* Loop 2 for Servo2 */
if (currentTime >= (loopTime + random(MinTime,MaxTime))) {
servo2X.write(random(Min2X,Max2X)); // Turn X-Servo to random X value (0-180)
servo2Y.write(random(Min2Y,Max2Y)); // Turn Y-Servo to random X value (0-180)
loopTime = currentTime; 
}

/* Loop 3 for Servo3 */
if (currentTime >= (loopTime + random(MinTime,MaxTime))) {
servo3X.write(random(Min3X,Max3X)); // Turn X-Servo to random X value (0-180)
servo3Y.write(random(Min3Y,Max3Y)); // Turn Y-Servo to random X value (0-180)
loopTime = currentTime; 
}

/* 
* Loop for testing max and min values - Comment this out or remove for working program
* Recommended to take one servo at the time and test out the min/max values on X first, then Y
* and then move on to next servo.
*/

// servo1X.write(Min1X); // Turn Servo 1 to Min X value
// servo2X.write(Min2X); // Turn Servo 2 to Min X value
// servo3X.write(Min3X); // Turn Servo 3 to Min X value
//
// servo1Y.write(Min1Y); // Turn Servo 1 to Min Y value
// servo2Y.write(Min2Y); // Turn Servo 2 to Min Y value 
// servo3Y.write(Min3Y); // Turn Servo 3 to Min Y value
//
// delay (1000);
//
// servo1.write(Max1X); // Turn Servo 1 to Max X value
// servo1.write(Max2X); // Turn Servo 2 to Max X value
// servo1.write(Max3X); // Turn Servo 3 to Max X value
//
// servo1Y.write(Max1Y); // Turn Servo 1 to Max Y value
// servo2Y.write(Max2Y); // Turn Servo 2 to Max Y value 
// servo3Y.write(Max3Y); // Turn Servo 3 to Max Y value
//
// delay (1000);
}
If you have no idea what any of this means, let me break it down a little.  The comments are behind the // in most of the lines.  As you go thru, it will start to make sense, such as which pin controls which servo.



What is a little more difficult is the section that sets the min and max positions for the X and Y axis for each servo.  



(The bottom of his code has loop testing, which I didn't try out, simply because I found something else that I found interesting.)

You see, the hard part is "knowing" what position the servo is in.  You can easily remove the servo horn and put it on again in a different spot.  Much like you can remove the hands of clock from showing 6:00 and put them in the noon position.  Where does the servo think it is?

The Sketch I found allows a message box to pop open, you enter the position and the servo moves to it.  Essentially, from 0 to 180, you can use this to determine the servo limit values in your setup

#include  
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the string readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured string 
    int n = readString.toInt();  //convert readString into a number

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}
 (Sorry if the code sections do not publish properly...Blogspot is a bit limiting)

The reason the ranges are so important is the shape of the shroud around the HP.  Depending on which HP you have, you may have more horizontal movement than vertical.  Or the reverse, depending on how you install it.

But ultimately, the goal of this is to have the data to feed into the Random Movement program.  This allowed me to test the minimal and maximum ranges for each axis.  By default, I was going beyond where the HP moved, causing strain on the motor that would eventually cause it to fail.

With the right values in place, Verify and Upload to the Arduino controller, then watch the HP move around.  

Having the HP movement really makes you wonder what R2 is thinking.  Of all the gadgets I have installed and made for R2, the random HP movement is the least expensive yet most convincing.  The caveat is that it quickly becomes a target of young hands grabbing it. However,  when you see R2 there, HP moving around, you really add some personality to the droid.  People think R2 is actively engaged in what's going on in the room and the HP moving around is similar to humans blinking their eyes...it's just natural and automatic.

I hope this wasn't too hard to follow along!