CNC Engraver Improvements

Previously I’ve written about my CNC build , a sound proof box I made for it and a description of the software I’m using with it.

After some usage I found a few weaknesses in my CNC machine. Today I’m going to cover 3 improvements that target those weaknesses:

  • Installing some new parts from CNCRouterParts (ACME Anti-backlash Nut, Z-Axis Plate and Low Profile Bearing Block)
  • Installing clamp-on couplers from DumpsterCNC
  • Building a custom dust control vacuum system

CNCRouterParts ACME Anti-backlash Nut

Previously I had used these ACME anti-backlash leadnuts from DumpsterCNC. These seem to be a common suggestion on CNCZone. They worked fine except that mounting them onto my 8020 Aluminum frame required some custom mounting brackets. I spent hours designing and making these brackets. I’ve had a few problems with them. One of my brackets was ever so slightly out of alignment causing some binding issues. They also had a few bolts/nuts that could vibrate loose so I had to keep an eye on these and tighten them from time to time. There were no major problems here, but these issues were annoying.

I ordered some ACME Anti-backlash Nuts from CNCRouterParts to replace the ones from DumpsterCNC. I was told these would mount directly onto my 8020 frame without any special brackets. Another advantage is that they are cheaper ($18.50 versus $22.50). As promised they mounted directly to my 8020 frame. I’ve used them for about an hour and they seem to work very well.

In my mind the CNCRouterParts solution is vastly superior to anyone building their frame out of 8020 due to fact that they are way easier to mount. I think that even on most non-8020 machines these would e easier to mount.

CNCRouterParts Z-Axis Plate

As a full discloser, I got this part free of charge from CNCRoutnerParts because I was the first to post an informative blog about other parts I’ve bought from them. I do not feel this has influenced my evaluation of this part.

This plate is well designed and a good deal at $28.75. Originally I spent many hours designing a steel plate solution. This gives more Z axis reach than my steel plate since the router is mounted lower than in my design. The biggest advantage is of this plate is time savings. I could just bolt my K2CNC router mount to this plate instead of spending the time to create my own. If you don’t mind spending a few hours you can save a few bucks by making your own, but I feel its money well spent.

CNCRouterParts Low Profile Bearing Block

As a full discloser, I got this part free of charge from CNCRoutnerParts because I was the first to post an informative blog about other parts I’ve bought from them. I do not feel this has influenced my evaluation of this part.

The low profile bearing block adds about one inch of Z travel to my machine over the standard bearing block because it lets the Z axis plate to travel over it. That said I like the standard bearing block more and after some testing went back to the standard bearing block. One reason is this new block uses a bushing instead of bearings so there is significantly more friction. I found this limited the speed I could run my Z axis at. Another issue is that I don’t need the extra Z travel and the standard block adds a hard stop to my Z axis, which I like as an extra safety precaution. With the low profile block I could run my Z axis rollers off their rails. If you need more Z travel you might want to look at the low profile bearing block, but I’ll stay with the standard bearing block which is an excellent product.

It’s also worth mentioning that the standard blocks are significantly more expensive after adding in the cost of the bearings so if price is a high concern that might give you more incentive to try and use this low profile bearing block.

DumpsterCNC Clam-on Couplers

I wanted to try these couplers from DumpsterCNC instead of the lovejoy connectors I used to mount my ACME screws to my stepper motors. The DumpsterCNC couplers are a little cheaper and they take up less space than the lovejoy connectors. They work just as well as the lovejoy connects so in any future builds I’ll likely use these instead of lovejoy connectors. I have nothing else to say since both products do their job perfectly.

Dust Control Vacuum System

My CNC machine is in an enclosed box so I don’t need to worry about dust getting all over my basement, but I found that having dust get all over my CNC machine was problematic. The biggest two areas of concern were dust on the ACME threads and dust on the roller rails. Instead of trying to stop dust from getting on these parts by covering them I decided to add a vacuum to suck up the dust before it could go on anything.

I bought this vacuum because is small, powerful, and cheap. I fabricated a small mount out of aluminum and wood to attach the vacuum to the router. The only other components I needed were some wire and duct tape. I used the wire as a structure and the duct tape to form a flexible skirt around the router to help suck up the dust. The pictures show this better than I can describe in words.

I am very pleased at how well this works. I really believe this is nearly an optimal solution. It took much less time to build than the solid wood/aluminum skirt designs I’ve seen, and I think this flexible design should perform better. It might not be pretty but it works great!

Results

Here’s a few objects I made while testing.

Comments (2)

CNC Router Software

I’ve already written about building my CNC router and making a sound proof box for it.  The last step I needed to do in order to make pretty pictures is the software. This post will walk you through the software I used to draw an image and then engrave that image into a piece of wood.

First I needed to draw a picture.  I didn’t want to use something like Photoshop or Microsoft Paint because I these are raster based programs and I wanted my image to be stored as vector graphics so that I could tell my CNC machine exactly what vectors to draw.  There are ways to transfer raster graphics to a CNC machine, but for more things using vector graphics works better.  Corel Draw is probably the most popular software for drawing vector graphics, but it was pretty expensive.  I found the free open source inkscape worked very well.  I drew a picture in inkscape called and saved it as HelloWorld.svg (I will be giving links to all the files I created).

After this I had to change all the text and other complicated objects into paths.  The reason for this step is because these objects are stored as complex mathematical models that later software would not be able to properly understand.  Converting objects to paths is just a single mouse click in inkscape, but if you forget to do this you’ll be scratching your head trying to figure out why some parts of your drawing are missing.  After this I saved the image in inkscape again as HelloWorld.dxf.  The reason I used the DXF format is because it’s a wildly used vector format that other software can understand.

At this point I’m done with inkscape and I start using Mach3’s LazCam.  Mach3 is the software that I use to control my CNC machine through my computer’s parallel port.  Setting this up takes some time and I’m not going to discuss this here, but Mach3’s website has some excellent video tutorials.

LazCam comes with Mach3 and it converts DXF files into Gcode that can drive my CNC machine.  If you’re looking for a free alternative to LazCam there is a free version of CamBam, but I haven’t used it much.  In LazCam I imported the DXF file.  This takes a long time (5 minutes on my mid-ranged PC) so after this I save it as HelloWorld.LCam so I can open it quickly later if I want to tweak something.  Then I adjusted the scale of my image and saved it out as Gcode (HelloWorld.tap).

In Mach3 I opened up the HelloWorld.tap file and my CNC engraver engraved the image into some wood.

There are a lot of steps there, but once you’ve done it a few times it’s not so bad.  It would be nice if it was easier, but I couldn’t find an easier way.  Maybe I’ll write some software myself someday to help speed this up a bit, but until I do I’ll just follow these steps.

Here’s a link to a video of my CNC Machine in action or you can watch the youtube embedded video below.  The linked video is better quality, but might take some time to download.

Comments

Sound Proof Box

FYI: This isn’t really a sound “proof” box, but I didn’t think sound dampening box had the same ring to it.

The construction of this box was done entirely with components from my local Home Depot. The total cost was about $200 for this 3ft x 3ft x 3ft box. The main components were:

  • 2×4s for box frame
  • 1/2 inch plywood for top/bottom (had Home Depot cut these free of charge)
  • 10 sheets of 1/8 inch hard board for sides and top/bottom (again Home Depot cut these for me)
  • Insulation to help sound proof the box
  • Lots of screws and nails
  • Hinges and a bolt lock for the door
  • 2 8×12 inch pieces of Plexiglass for the door’s window
  • Bathroom ceiling fan to suck out hot air from top (surprised that this was only $10)
  • Vent to let in air on the bottom
  • Cheap light for the box
  • Carpet or cloth to attach on the inside to help deaden the sound

I’m not going to detail the exact construction since it will vary depending on the size and options you need. For instance you might not need the fan, vent or window that my project needed.

The first main point about construction that I want to mention is that you should pick insulation that’s at least twice as think as the space between your walls. When you’re using insulation for heat you want to have it loose, but when using it for sound proofing you want it compressed. Another trick is to make sure a large part of the box’s interior is covered with cloth or carpet. I think carpet would be best, but I had some extra felt at home so I just used that.

Here are some pictures of a single wall’s stages of construction.

Here are some pictures of the finished box. I was quite happy with how much quieter my CNC machine is after I put it in this box.

Here’s a link to my CNC build.

Comments (2)

My CNC Engraver (Part 1)

The goal of this project is to design and build a CNC wood router/engraver.This turned out to be a much larger project than I had anticipated.  Bigger both in terms of dollars and hours I spent on it.  It took me about 50 hours to build the mechanical portion of my CNC machine and I still have to do the electrical and software work.  This posting will focus on the parts list and the mechanical systems.

I have done a lot with electronics and with software, but never have I build such a complicated mechanical machine before so I needed to do a lot of research before I started my build.  The best tools I found for this research phase where cnczone and google.  Eventually I decided on a gantry style table because the were the most common and simplest form of table. This thread in particular on cnczone influenced my final build. I didn’t do a very good job at recording the time I spent during this research phase, but it was probably something like 30 hours.

There is no way I’m going to take the time to explain every step of this build procedure, but here is a part list and the price I paid for each one.  I wish this list had existed before I started my build so I would have had an example of the different components you need to build a full CNC router and the approximate cost.

Frame
8020 Garage Sale Series 15 Aluminum Frame, connecting plates, bolts, nuts, … $581.80
CNC Router Parts (6) Linear Carriage with ABEC 7 Bearings $141.00
CNC Router Parts (2) Extended Linear Carriage with ABEC 7 Bearings $67.00
Speedy Metals Cold Rolled steel (2) 0.25×4x36, 0.25×6x32, 0.25×4x16 $89.26
K2 CNC RM-PC892 Porter Cable 690 & 892 Mount $57.95
Local Hardware Store Bolts, angle iron, washers, screws, … $50.00
Electronics
HobbyCNC HobbyCNC PRO Driver Board Packages with 305 oz-in motors $240.00
Mouser Pactec case #DM-4 $37.21
Allied Electronics 24VAC 10A Triad Transformer $52.00
Amazon Porter-Cable 690 LR Router $125.85
XYZ Threaded Axises Go to CNC Router Part List to see how these axises are assembled (note: I did not use the drill that he listed as optional).
CNC Router Parts (6) Bearing Block and Cover for 1/2″ ACME $75.00
CNC Router Parts (3) NEMA 23 Motor Mount $37.50
McMaster (3)5 Start 10 thread/inch 1/2″ Acme Threaded Rods - 3ft $117.51
VXB 10 R8ZZ Bearings (only use 6) $31.34
DumpsterCNC (3)1/2″-10 ACME 5 Start Anti-backlash Nut $73.50
MSC (12)Thrust Washer $10.08
MSC (6)Clamping Collar $9.06
MSC (6)Thrust Bearing $17.52
MSC (3)Spider Lovejoy Connector $5.31
MSC (3)1/4′ Lovejoy Connector $9.90
MSC (3)1/2′ Lovejoy Connector $9.90
Total 1838.69

Some other parts you’ll need are an old PC and the CNC software, but I’ll discuss these in a future post.

The main tools I used were hammer, table saw with aluminum blade, hacksaw, screw drivers, wrenches, hand drill, drill press, threading die (5/16th-18 male), center punch, Allen wrenches, Dremel, and a measuring ruler.

The best way to describe the my machine is with pictures so here we go.

Images of my engraver from different angles.

Images of the threaded axis assembly.

The plate used to attach frame to threads.

Image of the moutned motor.

Image of the rollers on the y-axis.

Image of the y-axis (it’s upside down so you can see the bottom).

Image of the z-axis.

I’ll also haven’t tested it yet, but it feels extremely smooth and sturdy so I’m quite confident that the machine will work great, but complete confidence won’t exist until I’ve used the machine for awhile.  In future posts I’ll cover the electrical systems, software, possibly other add-ons, and the reliability of the machine (after I’ve used it for awhile).

Update: I’ve made some improvements to the engraver here.

Comments (17)

Lightning Trigger for a Camera

From Public DomainI knew there were devices that could trigger a camera to fire during a lightning strike, but their circuits were more complicated than I wanted to make. I’m a software guy not a hardware guy so I decided to use an Arduino and that allowed me to write a little code that made the circuit much simpler.

Before I got started I looked at this wikipedia article about lightning so that I could verify this project would work. It has a lot of interesting information about lightning, but the most useful piece of data in the wikipedia article is the time lapse shot of a lightning strike. From the time lapse photo I was able to determine the duration of a lightning strike is about 100 ms. Then from this page I found my Canon 30d camera has a shutter lag of 65 ms. I know from a past project that if I use a reverse biased photo transistor to detect light it has a response time under 1 ms. The last piece of delay is the software running on the Arduino board and since it’s running at 16 MHz I am sure I can run a tight loop that takes under 1 ms. Adding up all the delays, I get 67 ms which is still much less than the 100 ms duration of a lightning strike so I was pretty confident this would work before I started work on the prototype.

The circuit I used to detect the light from the lightning was a very simple circuit that looked like the above circuit diagram. I used a cheap infrared photo transistor because that’s what Radio Shack had. I noticed that the sun, my house lights, and lightning all pump out plenty of infrared light for this circuit to detect. If this circuit is not sensitive enough try changing the value of the resistor. Larger resistance values should help sensitivity when there is only a little infrared light and smaller resistance values should help sensitivity when there is a lot of infrared light.

I also needed a circuit to trigger the camera. I already have written a short tutorial about how to do that here.

The last thing I needed to do was write some software. At first I thought I’d just have a threshold value that triggered the camera. That would work, but I’d need to calibrate the threshold value to different values depending on the environment. Instead I have the software look for a rapid change in the amount of infrared light detected. This works great because lightning causes a very rapid change.

Here is the code.

// Maurice Ribble
// 6-1-2008
// http://www.glacialwanderer.com/hobbyrobotics

// This code uses my camera trigger and lightning detector.
// It waits for a sudden change in the light intensity
// and then triggers the camera.

#define SHUTTER_PIN 7
#define LIGHTNING_TRIGGER_ANALOG_PIN 0
#define TRIGGER_THRESHHOLD 5

int lightningVal;

void setup()
{
  pinMode(SHUTTER_PIN, OUTPUT);
  digitalWrite(SHUTTER_PIN, LOW);
  Serial.begin(9600); // open serial

  lightningVal = analogRead(LIGHTNING_TRIGGER_ANALOG_PIN);
}

void loop()
{
  int cmd;
  int newLightningVal = analogRead(LIGHTNING_TRIGGER_ANALOG_PIN);
  Serial.println(lightningVal, DEC);

  if (abs(newLightningVal - lightningVal) > TRIGGER_THRESHHOLD)
  {
    digitalWrite(SHUTTER_PIN, HIGH);
    delay(1000); // May want to adjust this depending on shot type
    digitalWrite(SHUTTER_PIN, LOW);
    Serial.println("Shutter triggered");
  }

  lightningVal = newLightningVal;
}

Comments (6)

Arduino, Xport, PHP and the Internet

This article explains how to use the Arduino and an Xport Ethernet module to send and retrieve data to an external web server. I discuss the advantages of this method over various other methods of communications between Arduino and the internet. After discussing hardware setup, some simple test code for Arduino and the PHP code that you need to run on the web server is provided. Some real world extensions of this project are a web page that lets you control the lights in your house, or sending sensor data to a web page and graphing it so you have a pretty record of sensor readings.

The first stage in this project was researching how I wanted to connect Arduino to the internet. There are a lot of different options. The easiest required an external computer, but I avoided this because I wanted a highly reliable and very low power solution which a PC could not provide. I wanted a fairly simple solution that would use a minimal amount of flash memory on my Arduino. There is only 16K of flash memory on Arduino to hold your code. Since talking to a web server will always just part of a larger project I wanted to use the least memory possible so the rest of the project had enough space. After this research phase, I decided one the Xport modules from Lantronix would fit my needs best. The three Lantronix Ethernet modules I considered were the Xport, Xport Direct+ and Xport Direct. Xport has a different pin out than the Direct modules, but other than that they are very similar. As far as functionality the main difference is that Xport and Xport Direct+ have a web server, but Xport Direct does not. I went with the Xport because it was slightly smaller and had a web server. Knowing what I know now I would just get Xport Direct because it’s $30 instead of $50 like Xport Direct+ and Xport and I don’t need the web server.

Why don’t I care about a web server? At first I thought having a web server built into Xport was important, but for my use case it is not. The reason is because I would rather upload my data to a real web server. This way I don’t have to worry about a bunch of people connecting to my Arduino and effectively launching a denial of service attack on my Arduino. I would rather push data up to a real web server and then let it dish out the data to the rest of the world. This model also means I don’t need to worry about my firewall or getting my router to forward ports to my Arduino since all requests are initiated with Arduino. Another benefit of not using Xport’s web server is that it is quite limiting, but if I use an external web server then I can have much more flexibility like running PHP, SQL, Java, and any other common features that the Xport web server does not support.

I have a cheap hosted web server through Dreamhost. I mention dreamhost because I use them, but any web server that supports PHP and has a dedicated IP address should work fine for this project. One issue that took a long time to figure out is that cheap hosted account usually don’t have dedicated IP addresses for each domain name. I had to pay dreamhost an extra $4 a month for this option. One way to see if the domain you want to use has a dedicated IP address is to ping the server and then type that IP address into your web browser. If you have a dedicated IP address then you will go to your domain. If you don’t your browser will return an error. Another limitation of using a hosting service like dreamhost is that they have firewalls that get triggered if you try to connect too frequently. You can see in my code below how I added a delay to work around the firewall issues I found. I had to contact dreamhost a few times to get everything working. I must say their tech support was great and I was very pleased with the service they provided.

At this point I needed a way to connect the Xport to Arduino. I could have done this with a breadboard, but I found this cheap ($15) shield for the Xport module at Adafruit and it works great. That page also links to a great tutorial about putting the shield together and some code examples on how to setup a web server on Xport if you choose to go that route instead of what I’m describing here.

Now I could power up the Xport module and plug and Ethernet cable into it. Then I could configure it with telnet. You can get full documentation on your xport module and how to configure it here. Here is a list of the things I changed on my xport module.

  • Set the Channel 1 ConnectMode to “D4″ which changed the serial responce to single character mode (my code expects this mode)
  • Changed the Channel 1 port to 81 to work around my webhosting firewall
  • (Optional) Set the Xport to use a static IP address since I prefer that over the default dynamic IP address

The last part of the hardware setup was to hook up 3 wires between the Arduino and the Xport. Before doing this I decided to use the AFSoftSerial library. To install this library you just copy the AFSoftSerial directory into your Arduino-0011/hardware/libraries folder where all the libraries live. You could use the hardware serial port by using pins 0 and 1, but I wanted to allow those to talk to my PC so I used this soft serial port library. You can reconfigure all this in the code if you want, but I choose to use pin 2 as TX, pin 3 as RX and pin 4 as Xport Reset. Remember you need to connect Arduino’s TX pin to Xport’s RX pin, and Arduino’s RX pin to Xport’s TX pin. I made this stupid mistake. Just remember you need the transmit pins talking to the recieving pins or things just won’t work.

I have one note about the php code below. You can test test the php code with your web browser to make sure the php code is setup correctly. All you need to do is type this into your browsers address bar: http://www.yourdomain.com/arduino/xPortTest.php?value0=111&value1=222. Of course you’ll need to make sure the the location of the php file matches where it is located on your web server. This will append the values 111 and 222 to xportTest.txt and create the file if needed. If it doesn’t work the most likely issues are that your web server doesn’t support php or you don’t have the permissions setup to allow the php script to create/modify the text file.

That’s pretty much it. The code I used on Arduino and the PHP code I put on my web server is listed below. If anyone has any questions don’t hesitate to ask them here or on the Arduino Forums.

Arduino Code:

// Maurice Ribble
// 4-3-2008
// http://www.glacialwanderer.com/hobbyrobotics

// The flow of data is Arduino -> Xport -> PHP -> text file
// Once the connection is established by Arduino to the PHP page
// the PHP page can also send data back to Arduino

// This code demonstrates a simple yet flexible way to let Arduino
// talk to a webserver.  While there are versions of xport that
// have a webserver built in they are more expensive and require you
// to setup your internet connection to allow you to run a server.
// With this method you can just use a cheap hosted website.
// I use dreamhost and am very satisfied with their service, but there are
// many other options (any host that support PHP should work fine).
// With Dreamhost I needed to sign up for a dedicated IP address and I
// had port 80 with connections no more frequent than once per minute or
// I had problems with their firewall blocking my connection attempts.
// If you want to send data back and forth frequently just connect once
// and just keep using that connection.  This will avoid issues with
// web hosting firewalls.

// Xport Settings (everything default except)
//  Channel 1 -- CoonnectMode : D4 -- This changes serial responce to single char mode
//  Channel 1 -- Port 80
//   I also changed my IP address to a static IP, but you could leave this alone

#define XPORT_SERIAL_RX_PIN 3
#define XPORT_SERIAL_TX_PIN 2
#define XPORT_RESET_PIN 4

// These are web server specific values
#define PHP_PAGE_LOCATION "/arduino/xPortTest.php"
#define WEB_HOST "HOST: yourdomain.com\n\n"
#define IP_AND_PORT "C111.111.111.111/80\n"

#include 

AFSoftSerial xPortSerial = AFSoftSerial(XPORT_SERIAL_RX_PIN, XPORT_SERIAL_TX_PIN);

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(9600);
  xPortSerial.begin(9600);
}

void loop()
{
  xportReset();
  xportConnect();
  httpRequest();

  // Delay for 1 minute to aviod triggering my host's firewall
  delay(60000);
}

void xportReset()
{
  pinMode(XPORT_RESET_PIN, OUTPUT);
  digitalWrite(XPORT_RESET_PIN, LOW);
  delay(100);
  digitalWrite(XPORT_RESET_PIN, HIGH);
  delay(3000);
}

void xportConnect()
{
  byte theByte = 0;

  while (theByte != 'C')
  {
    xPortSerial.print(IP_AND_PORT);
    while(!xPortSerial.available()) {} // Just loop until available
    theByte = xPortSerial.read();
    Serial.print(theByte);
    Serial.print(" ");
  }
}

void httpRequest()
{
  byte theByte;

  xPortSerial.print("GET ");
  xPortSerial.print(PHP_PAGE_LOCATION);

  // value0 = 123 and value1 = 456
  // You should change these to be your sensor values or whatever you want to send
  // (see php code if you want to add more values or change the names value0/value1
  xPortSerial.print("?value0=123&value1=456");
  xPortSerial.print(" HTTP/1.1\n");
  xPortSerial.print(WEB_HOST);

  while(!xPortSerial.available()) {} // Just loop until available
  theByte = xPortSerial.read();
  if (theByte != 0)
    Serial.println("Passed.");
  else
    Serial.println("Failed.");
}

PHP Code:



You need to pass in valid _GET parameters.  Script Terminated.";
  exit;
}

$fp = fopen("./xportTest.txt", 'at');
if (!$fp)
{
	echo '

Failed to open file';
	exit;
}

$outputstring = "$value0 $value1\r\n";
fwrite($fp, $outputstring, strlen($outputstring));

// end with a 0 to close the session to the client:
echo "\0";
end;
?>

Comments (5)

Processing

I just found this open source project at processing.org that looks supper useful. A lot of people use it to design cross platform GUIs for interfacing the Arduino with the PC since it has easy to use serial communications. Another part that looks useful to me is that it has imaging/camera libraries that should make some of my ideas that require motion tracking and other video related ideas much easier to implement.

I will likely use this in future projects, but for now I just wanted to write it down so I don’t forget about it.

Comments

Camera Trigger

This article explains how to use a microcontroller like Arduino to trigger the shutter on a Canon DSLR camera that has an N3 connector. Canon cameras like the 10d through the 40d and their professional cameras all have this connector. Many other DSLR cameras have a very similar connector that you could adapt this article to, but they’ll require a little more research from you.

This project would work well with another project I wrote about here. It describes how to trigger a flash with sound or a laser trigger. You could easily adapt it so it triggers your camera instead of the flash. Note that in that article I discuss the downside of directly triggering your camera (namely the delay), but if a delay of a fractional part of second doesn’t matter then triggering your camera directly works great. Some cool applications would be having your camera take a picture every time you say a word, taking a picture every time someone rings your doorbell, or taking a picture when someone walks down the hallway.

The most difficult part of this tutorial is getting a cheap N3 connector. Canon decided to go with a proprietary plug and they charge ridiculous prices for any accessory that uses this plug. I think their cheapest device with the N3 plug is a basic remote trigger and they charge $50 for it. You could try to make your own plug. But my favorite solution was to type “canon n3 remote” into ebay and I found lots of simple remote triggers for under $10. I just got my plug from one of these devices.

With the plug in hand I started figuring out what the different wires did. Here is picture of the the plug and the color of wire attached to each pin in the plug. The white wire is ground. The green wire is +3V and when it’s grounded it causes the camera to focus (similar to pushing your shutter button half way down). The red wire is +4V and when it’s grounded it causes the camera to take a picture (depending on the mode the camera is in it might focus first). If you want to guarantee a quick picture you should pre-focus your camera and then set focus to manual.

Now that we know how the N3 plug works all we needed to do is wire a circuit that lets us switch the green (focus) or red wire (shutter) to ground. I actually find the focus wire to be pretty useless since I can have the camera focus before it takes a picture if I want, but there are some use cases where it would be nice so I’ve included it here for completeness. I figured a simple switching transistor like the 2N2222 would be be the perfect switch for this project and so that’s what I used. See my circuit diagram below.

This example code for Arduino is very simple. All it does is focus when you hit the “f” key and and take a picture when you press the space bar key. Here is a link to the code.

// Maurice Ribble
// 4-28-2008
// http://www.glacialwanderer.com/hobbyrobotics

// This code just tests my camera trigger.  It lets you
// focus the camera by pressing the 'f' key and take a
// picture by pressing the space bar.

#define FOCUS_PIN 6
#define SHUTTER_PIN 7

void setup()
{
  pinMode(FOCUS_PIN, OUTPUT);
  pinMode(SHUTTER_PIN, OUTPUT);
  digitalWrite(FOCUS_PIN, LOW);
  digitalWrite(SHUTTER_PIN, LOW);
  Serial.begin(9600); // open serial
  Serial.println("Press 'f' to focus and 'spacebar' to trigger shutter");
}

void loop()
{
  int cmd;

  while (Serial.available() > 0)
  {
    cmd = Serial.read();

    switch (cmd)
    {
    case 'f':
      {
        digitalWrite(FOCUS_PIN, HIGH);
        delay(800); // May want to adjust this depending on focus time
        digitalWrite(FOCUS_PIN, LOW);
        break;
      }
    case ' ':
      {
        digitalWrite(SHUTTER_PIN, HIGH);
        delay(2000); // May want to adjust this depending on shot type
        digitalWrite(SHUTTER_PIN, LOW);
        break;
      }
    default:
      {
        Serial.println("Press 'f' to focus and 'spacebar' to trigger shutter");
      }
    }
  }
}

Comments (5)

An I2C Bus Example Using the DS1307 Real-Time Clock

A more complete description of I2C can be read here on Wikipedia, but I will give you the four sentence summary here. I2C is a serial data bus protocol that allows multiple devices to connect to each other with fairly slow data transfer rates. These slow data transfer rates are fast enough for many devices and allow the bus to be very simple to implement. The real beauty of this protocol is that you can control up to 112 devices with just two wires from a microcontroller. Many microcontrollers have a libraries to support I2C; on Arduino the official Wire library handles the details for you.

In this example I use an Arduino board as the bus master and have just one slave device on the I2C bus, a DS1307. You can read the DS1307 data sheet here. As I mentioned before Arduino has a library called Wire that handles all the details of the I2C protocol. Wire uses analog pin 4 for the Serial Data (SDA) connection and analog pin 5 for the Serial Clock (SCL) connection. The I2C protocol defines the bus as an open drain bus, which means you need to use pull-up resistors on each of the two bus wires. Here is the circuit of how I wired the DS1307 to Arduino using a I2C bus.

Here is the code I wrote. There are a lot of other places on the web that have code for using the DS1307, but I couldn’t find a simple and efficient one that just did what I needed. This code has two main functions for accessing the DS1307. One sets the time and date, and the other gets the time and date. The DS1307 returns it’s numbers coded in binary-coded decimal (BCD). This code also converts the numbers returned from the DS1307 out of BCD for you. If all you want to do is display the time BCD is probably better, but most of the time I won’t be just displaying the time. Instead I’ll be using it to decide when to run events and for this it’s better to work with normal numbers.

//
// Maurice Ribble
// 4-17-2008
// http://www.glacialwanderer.com/hobbyrobotics

// This code tests the DS1307 Real Time clock on the Arduino board.
// The ds1307 works in binary coded decimal or BCD.  You can look up
// bcd in google if you aren't familior with it.  There can output
// a square wave, but I don't expose that in this code.  See the
// ds1307 for it's full capabilities.

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// Stops the DS1307, but it has the side effect of setting seconds to 0
// Probably only want to use this for testing
/*void stopDs1307()
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.send(0x80);
  Wire.endTransmission();
}*/

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  Serial.begin(9600);

  // Change these values to what you want to set your clock to.
  // You probably only want to set your clock once and then remove
  // the setDateDs1307 call.
  second = 45;
  minute = 3;
  hour = 7;
  dayOfWeek = 5;
  dayOfMonth = 17;
  month = 4;
  year = 8;
  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}

void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
  Serial.print(hour, DEC);
  Serial.print(":");
  Serial.print(minute, DEC);
  Serial.print(":");
  Serial.print(second, DEC);
  Serial.print("  ");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print("  Day_of_week:");
  Serial.println(dayOfWeek, DEC);

  delay(1000);
}

UPDATE 5-20-2008
Updated the code to fix a few bugs Fabien pointed out. He also informed me of this: “Because you’re hooking up the clock to analog pins 4 & 5 on the Arduino and using the Wire lib, you don’t need to bother with pull-up resistors in your schematics. Turns out that the Arduino has built-in pull-up resistors for these pins. The Two Wire library enables the built-in pull-ups in the twi_init() function in twi.c (located here: \arduino-0011\hardware\libraries\Wire\utility).”

Thanks Fabien!

Comments (10)

Triggering a Camera’s Flash with Sound and Light

For those just wanting to see the pretty pictures, click here.

This article focuses on making the sensors used to trigger a camera’s flash using a microphone or a cheap laser pointer. Since I’ve already described how to do the actual firing of a camera’s flash here I won’t focus on that part of this project today.

There are a lot of places on the web that describe how to trigger a flash with an electrical circuit, but I feel that using a microcontroller like Arduino offers big benefits. For instance you can easily add new sensors, or even run multiple sensors at once. Since the triggering of the flash is done in software it’s easy to add delays, or make a more complicated triggering algorithm based on multiple sensors. Lastly while the microcontroller does add some cost, it’s not much because boards like Arduino can be bought for around $35 and some of this cost for the microcontroller is offset by simpler circuits.

Now let’s talk about why we’re triggering the flash. The main reason is to help capture those moments that require extremely accurate timing. Computers are many orders of magnitude faster at waiting around for something to happen and then triggering the flash when that something does happen. Humans can try to compensate for this by watching the event and then trying to plan when to trigger the flash. For example when photographing a balloon popping, you can tell your friend to pop the balloon on the count of three and then take the picture on three. This sort of works, but this electronic flash trigger works much more consistently and it’s always ready to take the picture of those less predictable events.

Most SLR and DSLR cameras let you attach a cable to trigger the camera directly. Why not interface that camera trigger directly and just attach the flash to the camera if it’s dark? This would let you use the camera’s built in flash (my method requires an external flash unit). The reason we can’t do this is because camera’s are too slow. I’ve done some measuring of the delay between when you tell a camera to take a picture and when it actually takes a picture and found on my camera it’s around 20 ms. To a person this delay isn’t noticeable, but to a popping balloon it’s way too long. So instead of of triggering the actual camera we must trigger the much more quickly responding flash.

When I’m using this flash trigger I work in a dim room and set my shutter speed to 10 seconds. Since it’s nearly dark in the room the camera’s picture is still black after these 10 seconds. However if I trigger the flash for 1/1000th of a second that short burst of high intensity light is enough to light up the scene. So even though my shutter speed is 10 seconds, I’m effectively only taking a picture while the flash is active because that’s where all the photograph’s light is coming from.

Laser Sensor

This first sensor uses a cheap laser pointer and a photo resister to detect the laser’s light. The software is setup to trigger the flash when the laser beam is broken. The software also turns off the laser so it doesn’t show up in your photograph. Think of it as an electronic trip wire. This is great for catching moving objects. Add a small delay between the detection and triggering of the flash and you can catch cool things like a light bulb that is is smashing into the ground.

Since I didn’t have an extra laser pointer sitting around I bought this cheap laser card module. It’s very low power so I can run it off a digital output on the Arduino board. Originally I powered the laser directly from Arduino’s +3 volt output, but I found that it was better to run it off a digital pin so that the laser could be turned on/off. Since this laser runs on 3 volts and Arduino outputs 5 volts I used a voltage divider in my circuit to get the needed voltage. To sense the laser I used another voltage divider circuit with a photoresistor. An analog input on the Arduino was used to detect the if the laser was hitting the photoresistor or not.

Here’s the circuit.

Sound Sensor

This sensor detects noise. It’s very useful for detecting things like a drop of water splashing, or anything that makes noise. There are lots of places on the web that discuss how to build your own microphone and amplifying circuits, but I liked the idea in this article about using a guitar amplifier. A karioki machine or any other device that has a microphone input and an output line should work. You can pick up a low quality amp and microphone pretty cheaply on ebay or in a retail store. Sometimes you can get them really cheap at a garage sale.

The signal you get from an amplifier is going to be an electrical AC wave representation of the sound going into the microphone. This often means something like a 5 volt 8 kHz wave. The only thing I did was to add a diode to protect the analog input I was using on my Arduino board from the negative portion of this wave. Here are some pictures from my oscilloscope of the wave being generated by the amp. The first one is the full wave of my voice (I was singing “Twinkle Twinkle Little Star”), and the second picture is what it looks like with a diode.

You can see that the bottom half of the waves are getting chopped off, but that should be fine. The Arduino is more the fast enough to detect the voltage spikes. You could even make more sophisticated software to only trigger on certain frequencies of sound, but for now my software just looks for any sound spike over a certain threshold voltage.

Here’s the circuit.

Flash Trigger

I’ve already discussed this part of the system in this article, but for completeness here’s the circuit.

Building a Box to Hold it All

After understanding how all of these circuits worked it was time to put them all together and build a box that would handle all my flash triggering needs. Here are some photos of what I created.

Software

Last, but not least here is the software I wrote to run it.

// Maurice Ribble
// 4-12-2008
// http://www.glacialwanderer.com/hobbyrobotics

// This code is designed to to tune (see PRINT_MESSAGE define) and
// to run a sound sensor and a laser sensor.  Both of these sensors
// Are used to trigger a flash.  It should be easy to add additional
// sensors if you want.

// These enable the different types of triggers
//#define ENABLE_LASER_TRIGGER
#define ENABLE_SOUND_TRIGGER

// The threshhold values for the different triggers.
// These may need to be changed depending on evironment and sensors being used.
// Using PRINT_MESSAGES can help determine the correct value for these.
#define LASER_THRESHHOLD 500
#define SOUND_THRESHHOLD 100

// This prints messages to the serial port.  This is good to enable while determining
// the threshholds for your trigger, but these communications are very slow and
// when using these sensors to actually take pictures this should be turned off.
//#define PRINT_MESSAGES

// The digital pins being used
#define CAMERA_FLASH_PIN 4
#define LASER_PIN 5

// The analog pins being used
#define LASER_TRIGGER_ANALOG_PIN 0
#define SOUND_TRIGGER_ANALOG_PIN 1

void setup()
{
  pinMode(CAMERA_FLASH_PIN, OUTPUT);
  digitalWrite(CAMERA_FLASH_PIN, LOW);
  pinMode(LASER_PIN, OUTPUT);
  digitalWrite(LASER_PIN, LOW);

#ifdef ENABLE_LASER_TRIGGER
  digitalWrite(LASER_PIN, HIGH);  // Turn on the Laser
#endif

#ifdef PRINT_MESSAGES
  Serial.begin(9600); // open serial
#endif
}

void loop()
{
  int soundVal;
  int laserVal;

  ////////////////////////////////////////////////////////////
  // SOUND TRIGGER
  ////////////////////////////////////////////////////////////
#ifdef ENABLE_SOUND_TRIGGER
  soundVal = analogRead(SOUND_TRIGGER_ANALOG_PIN);
  if (soundVal > SOUND_THRESHHOLD)
  {
     digitalWrite(CAMERA_FLASH_PIN, HIGH);
#ifdef PRINT_MESSAGES
     Serial.println("Flash Triggered!!!");
#endif
     delay(100);
     digitalWrite(CAMERA_FLASH_PIN, LOW);
   }
#ifdef PRINT_MESSAGES
  Serial.print("Sound: ");
  Serial.println(soundVal, DEC);
#endif
#endif // ENABLE_SOUND_TRIGGER

  ////////////////////////////////////////////////////////////
  // LASER TRIGGER
  ////////////////////////////////////////////////////////////
#ifdef ENABLE_LASER_TRIGGER
  laserVal = analogRead(LASER_TRIGGER_ANALOG_PIN);
  if (laserVal < LASER_THRESHHOLD)
  {
     digitalWrite(CAMERA_FLASH_PIN, HIGH);
     digitalWrite(LASER_PIN, LOW);  // Turn off laser during picture
#ifdef PRINT_MESSAGES
     Serial.println("Flash Triggered!!!");
#endif
     delay(100);
     digitalWrite(CAMERA_FLASH_PIN, LOW);
     digitalWrite(LASER_PIN, HIGH);  // Turn laser back on after picture
   }
#ifdef PRINT_MESSAGES
  Serial.print("Laser: ");
  Serial.println(laserVal, DEC);
#endif
#endif // ENABLE_LASER_TRIGGER
}

Comments (17)

« Previous entries