Feedback!

Panoramic Camera

Views: 7108 Difficulty: 4 Status: Development
Pan_cam_case

Servo motor, JPEG camera, and Arduino Leonardo combine to make a panoramic camera.

Panoramic Cameras take beautiful pictures! They are great for shooting landscapes, cityscapes, or apartments for rent when you want to show the whole room. In this tutorial we show how to make a DIY Arduino-based panoramic camera. It can save images to an SD card or send them out over the Serial port and USB cable. The camera can be powered by battery or USB. In keeping with our desire to make transparent devices we include a laser-cut plexi glass case for this camera (by the way, it is the same case used in our time-lapse camera project.) We are using the TTL Serial JPEG Camera with NTSC Video from adafruit, (they also have a weatherproof version).

Panoramic Camera and Plexi Glass Case

Pan_cam_case
The panoramic camera in its plexi-glass case.

Video of the Panoramic Camera in Action

The Arduino-based panoramic camera in action!

Arduino Code for Panoramic Camera

Okay now the basic idea of this code is to fix the camera to the motor, then rotate the motor a little bit, take a picture, then wash, rinse and repeat. So we get a bunch of overlapping shots which we can stitch together (by hand or with software). The crux of the algorithm is the function called take_panoramic_picture() [notice the self-documenting code]. The function takes as input the number of pictures to take, and the number of angles to rotate in total. Even at the lowest resolution setting we found that 8 pictures were enough to fully span the 180 degrees that the servo can rotate. take_panoramic_picture loops takes a picture at each rotation increment and saves them to the SD card with names like pan02.jpg, and pan03.jpg. The function goes like this:
void take_panoramic_picture(int pics, int rotate){
  // Create an image with the name panxx.jpg
  char filename[13];
  strcpy(filename, "pan00.jpg");
  int cur_angle = 0;
  int angle_inc = rotate/pics;
  for (int i = 0; i < pics; i++) {
    pan_servo.write(cur_angle);
    delay(cur_wait);
    filename[3] = '0' + i/10;
    filename[4] = '0' + i%10;
    take_picture(filename);
    delay(cur_wait);
    cur_angle += angle_inc;
  }   
}
Lastly, the library list, we use a ton of Arduino libraries in this code so get ready: Adafruit vc0706 camera library, the SoftwareSerial Library (to talk to the camera), the SD Card library (to save the images), the SPI protocol library (to talk to the SD Card), and lastly the Servo motor library, we need this one to spin the camera around.
/* Panoramic Camera by LucidTronix
 * Example pictures, explanation, tutorial at
 * http://www.lucidtronix.com/tutorials/39
 * Uses the vc0706 camera library from adafruit
 * The camera is fixed to the motor which rotates
 * and takes a photo every 10 degrees or so.
 */
#include <SoftwareSerial.h>
#include <VC0706.h>
#include <SD.h>
#include <SPI.h>
#include <Servo.h> 

Servo pan_servo;

SoftwareSerial cameraconnection = SoftwareSerial(8,9);
// pass the serial connection to the camera object
VC0706 cam = VC0706(&cameraconnection);
#define SD_CS 4    // Set the chip select line to whatever you use (4 doesnt conflict with the library)
int pin_pan = 5;
int pin_btn = 10;

int pan = 0;

unsigned int cur_wait = 500;

int leds[] = {A0,A1,A2,A3};

void setup() {
  
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Serial.println("in setup yo.");
  delay(1400);
  Serial.println("now gonna try");
  Serial.println("VC0706 Camera snapshot test");
  // Try to locate the camera
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
    cam.setImageSize(VC0706_160x120);          // small
  }
  // Set the picture size - you can choose one of 640x480, 320x240 or 160x120 
  // Remember that bigger pictures take longer to transmit!  
  //cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  cam.setImageSize(VC0706_640x480);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");
  pinMode(pin_btn, OUTPUT); 

  for (int i = 0; i < 4; i++){
    pinMode(leds[i], OUTPUT); 
  }
  
  Serial.println("Trying SD Card..");
  pinMode(SD_CS, OUTPUT);
  digitalWrite(SD_CS, HIGH);
  while (!SD.begin(SD_CS)) {
    Serial.println(" no SD card :(");
    Serial.println("will try again in 10 seconds..");
    delay(10000);
  }
  Serial.println("SD Card Ready!");
  for (int i = 0; i < 4; i++){
    digitalWrite(leds[i], HIGH); 
  }
  delay(500);
  for (int i = 0; i < 4; i++){
    digitalWrite(leds[i], LOW); 
  }
  delay(500);
  pan_servo.attach(pin_pan);
  Serial.print("Ready to take image! Press the Button!");
}
void loop(){
  if (digitalRead(pin_btn) == HIGH) {
    take_panoramic_picture(8,170);
    Serial.print("Pan Image Taken");
  }
}
void take_panoramic_picture(int pics, int rotate){
  // Create an image with the name panxx.jpg
  char filename[13];
  strcpy(filename, "pan00.jpg");
  int cur_angle = 0;
  int angle_inc = rotate/pics;
  for (int i = 0; i < pics; i++) {
    pan_servo.write(cur_angle);
    delay(cur_wait);
    filename[3] = '0' + i/10;
    filename[4] = '0' + i%10;
    take_picture(filename);
    delay(cur_wait);
    cur_angle += angle_inc;
  }   
}


void take_picture(char * filename){
  Serial.println("Snap in 1 secs...");
  delay(1000);
  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!"); 
    // Create an image with the name filename
    // Open the file for writing  
    // delete it if it exists 
    delay(200);
    SD.remove(filename) ;
    delay(100);   
    File imgFile = SD.open(filename, FILE_WRITE);
    // Get the size of the image (frame) taken 
    delay(100);   

    uint16_t jpglen = cam.frameLength();
    Serial.print(jpglen, DEC);
    Serial.println(" byte image");
      pan_servo.detach();

    int32_t time = millis();
    // Read all the data up to # bytes!
    while (jpglen != 0) {
      // read 64 bytes at a time;
      uint8_t *buffer;
      uint8_t bytesToRead = min(32, jpglen);   // change 32 to 64 for a speedup but may not work with all setups!
      buffer = cam.readPicture(bytesToRead);
      imgFile.write(buffer, bytesToRead);
      jpglen -= bytesToRead;
    }

    imgFile.close(); 
    delay(50);
    cam.reset();
    pan_servo.attach(pin_pan);
}
void blink_leds(int wait){
  for (int i = 0; i < 4; i++){
    digitalWrite(leds[i], HIGH); 
    delay(wait);
  }
  for (int i = 0; i < 4; i++){
    digitalWrite(leds[i], LOW); 
    delay(wait);  
  }
}

Parts

Title Description # Cost Link Picture
TTL Serial JPEG Camera with NTSC Video Camera from adafruit 1 $39.95 Link Vc0706_lrg
Stepper Motor BiPolar Stepper motor from sparkfun. 2 $14.95 Link 09238-01
PCB for SD Card and Camera PCB supports camera and SD card atmge32u4 and USB. 1 $7.0 Link Screen_shot_2013-02-15_at_5.34.31_pm
ATMEGA32U4-MU Integrated Circuits MCU AVR 32K FLASH 16MHZ 44-QFN Value: 2.7 V ~ 5.5 V 16MHz 1 $6.04 Link Screen_shot_2012-12-28_at_7.31.41_pm
SD Card (micro 4GB) MicroSD Card 4GB with full-size SD card adapter Value: 4GB 1 $5.35 Link Microsd4gb
microSD Card Connector Secure Digital - microSD™ Push In, Push Out Value: microSD 1 $3.44 Link 0473340001
Battery Holder Holds 3 AAA Batteries. Has on/off switch. Value: 4.6V 1 $1.95 Link Id727_med
USB connector USB Mini type B Value: female 1 $0.68 Link Usb-m26ftr
Crystal CRYSTAL 16.00000 MHZ 20PF SMD Value: 16MHz 1 $0.53 Link Ecs-270-20-3x-en-tr
Button Tactile switch SMD SPST 0.05A 12V Value: SPST 3 $0.2 Link Fsm4jsma
Resistor Array RES ARRAY 300 OHM 4 RES 1206 Value: 300 1 $0.02 Link Vishay_-_cra06s-8

    Comments:

    20120519_163335
    sam
    It still in the prototype phase... But we will keep you posted!
    Sat, Feb 28 2015 1:01PM
    Missing_profile
    kongkawai
    Hi there! When can I buy this product. I have been waiting for long time.
    Tue, Dec 30 2014 3:06AM
Permalink: http://lucidtronix.com/tutorials/39
Arduino-powered spherical camera with 2 Servo Motors and an SD Card....
This PCB controls a camera and an SD card so you can make automatic time lapse videos. ...
Mixing pixels from two face images together....
Handheld gaming machine, based on the Arduino Leonardo, equipped with joystick, SD card and more....
Our take on the classic bouncing ball, paddle game....
Wall-ter is a wall following robot....
Print bitmaps, cellular automata, drawings and text.....
Light sensors guids this robot towards the light....