FPVLAB

image
Page 1 of 2 12 LastLast
Results 1 to 10 of 17

Thread: Scripting Canon SX230 for Aerial Surveys with CHDK and Arduino

  1. #1
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Scripting Canon SX230 for Aerial Surveys with CHDK and Arduino

    I'm putting an SX230 in my ZII as a downward facing camera. My plan is to fly over a nearby forest this spring on subsequent weeks to capture the leafout, which I think is changing due to the overpopulation of deer.

    The ZII is a nice platform for this, because the two skids would protect the lens on landing. However, I'm not the greatest launcher, and I land in a field, so I also want to have the lens retracted on launch and landing.

    The SX230 is a great camera for this purpose because it has a built-in GPS, has no bad frequencies in the UHF band, and can be scripted with CHDK:

    http://chdk.wikia.com/wiki/SX230

    My rig has the camera turned on at launch but the lens retracted. Once I get to altitude, I turn on the intervalometer and take pictures every 2 seconds. Once I get ready to land, I cause the camera to go into shutdown mode, which retracts the lens. It is important to note that there are no permanent modifications to the camera. My daughter would kill me if there were, because she likes to take slow-mo pictures of the cat drinking milk...

    In this thread I will document the arduino code, the chdk code, and the scripting parameters that allow the arduino to talk to the canon camera to either start the picture taking or to shut down the camera. I want to stress that there are no reports of damage to cameras from CHDK and it seems tolerant of the 5V supply. However, while it has worked fine for me, you are on your own if you damage things...

    Here is an example video of the camera in action. At the end of the movie you can see the micro usb cable coming out of the camera.



    Parts needed:

    SX230 camera http://www.amazon.com/Canon-PowerSho...keywords=sx230
    Arduino nano http://microcontrollershop.com/produ...oducts_id=3648
    Small micro usb cable you can cut up. This might work: http://www.cellphoneshop.net/microus...Fao7MgodAUAANA

    I will also be using ardupilot 2.5 and minimosd because it has good waypoints, but RVOSD 5 would also be a great choice. The only bad thing about RVOSD is that you either set the automatic function to be RTH or next waypoint, and if you are on a mission and lose your radio, it will complete the mission before returning home.

    Take these steps:

    Create the SD card with CHDK and the correct scripts.
    Make a connector cable from the camera to the Arduino
    connect your receiver or a servo tester to the arduino
    Program the arduino with the camera controller script
    Change the settings on the camera to automatically start the CHDK with the pictuav.lua script

    It will take a few hours to learn CHDK and a few minutes to make a cable.
    Last edited by BloomingtonFPV; 10th January 2013 at 05:06 PM.
    About to maiden my Fascination...

  2. #2
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Step 1: get an SX230 and prep CHDK

    I got a used SX230 of Amazon. It was $100, and I've seen others around the same price. Why buy new when you are going to throw this bad boy in the air?

    I won't bore you with the steps I went through to get CHDK to work. It was the better part of the weekend. Here is all you need to do:

    1) First, you need the firmware version number of your camera:

    http://chdk.wikia.com/wiki/FAQ#Q._Ho...f_my_camera.3F

    create a file called ver.req or vers.req in the root directory of your SD card. It can be blank or whatever. Follow the instructions on the link above.

    2) Download the firmware for your camera:

    http://mighty-hoernsche.de/

    look for SX230 and get the zip file from the first column that corresponds to your firmware number. Mine was 101b so I got this one:

    sx230hs-101b-1.1.0-2461-full_BETA.zip (790KB)


    3) Stick a 16 gig sd card in your camera and use the tools in the camera to do a low level (raw) format of the card.

    4) On a windows machine, copy the contents of the zip file (not the zip file itself) to the sd card. The file DISKBOOT.BIN and other files in the same location must be on the root directory of the card, with the CHDK folder also in the same place. (the next step didn't work for me on a mac but on a windows machine it was fine. Keep fussing with it).

    5) start the camera by holding the PLAYBACK button for ~ 1-2 seconds
    select Firm Update...-> OK
    go into mode -> Menu -> Miscellaneous stuff -> Make card bootable...


    6) Now take the card out and slide the lock slider to lock. This will make CHDK automatically load when you insert the card and power on. You'll have to unlock it when you edit the files on a computer.

    7) Eventually we will make the pictuav script autoplay when we start the camera. It will wait for a medium-length pulse and then start recording. When it sees a long pulse, it will shut down. If it doesn't see anything it won't extend the lens.
    Last edited by BloomingtonFPV; 6th January 2013 at 10:56 PM.
    About to maiden my Fascination...

  3. #3
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Step 2: Set up your CHDK parameters

    Once you get the CHDK working, you need to copy this code and save it into a file called pictuav.lua in the Scrips folder in the CHDK folder on the SD card (remember to unlock it first!).

    Code:
    --[[
    @title PictUAV
    @param s Secs/frame
    @default s 2
    @param h Sequence hours
    @default h 1
    @param m Sequence minutes
    @default m 5
    @param e Endless? 0=No 1=Yes
    @default e 1
    @param f Focus: 0=Every 1=Start
    @default f 1
    @param d Display off frame 0=never
    @default d 0
    --]]
    print( "PictUAV Started " )
    -- convert parameters into readable variable names
    secs_frame, hours, minutes, endless, focus_at_start, display_off_frame = s, h, m, (e > 0), (f > 0), d
    
    props = require "propcase"
    
    -- derive actual running parameters from the more human-friendly input
    -- parameters
    function calculate_parameters (seconds_per_frame, hours, minutes, start_ticks)
       local ticks_per_frame = 1000 * secs_frame -- ticks per frame
       local total_frames = (hours * 3600 + minutes * 60) / secs_frame -- total frames
       local end_ticks = start_ticks + total_frames * ticks_per_frame -- ticks at end of sequence
       return ticks_per_frame, total_frames, end_ticks
    end
    
    function print_status (frame, total_frames, ticks_per_frame, end_ticks, endless)
       local free = get_jpg_count()
       if endless then
          local h, m, s = ticks_to_hms(frame * ticks_per_frame)
          print("#" .. frame .. ", " .. h .. "h " .. m .. "m " .. s .. "s")
       else
          local h, m, s = ticks_to_hms(end_ticks - get_tick_count())
          print(frame .. "/" .. total_frames .. ", " .. h .. "h" .. m .. "m" .. s .. "s/" .. free .. " left")
       end
    end
    
    function ticks_to_hms (ticks)
       local secs = (ticks + 500) / 1000 -- round to nearest seconds
       local s = secs % 60
       secs = secs / 60
       local m = secs % 60
       local h = secs / 60
       return h, m, s
    end
    
    -- sleep, but using wait_click(); return true if a key was pressed, else false
    function next_frame_sleep (frame, start_ticks, ticks_per_frame)
       -- this calculates the number of ticks between now and the time of
       -- the next frame
       local sleep_time = (start_ticks + frame * ticks_per_frame) - get_tick_count()
       if sleep_time < 1 then
          sleep_time = 1
       end
       wait_click(sleep_time)
       return not is_key("no_key")
    end
    
    -- delay for the appropriate amount of time, but respond to
    -- the display key (allows turning off display to save power)
    -- return true if we should exit, else false
    function frame_delay (frame, start_ticks, ticks_per_frame)
       -- this returns true while a key has been pressed, and false if
       -- none
       while next_frame_sleep (frame, start_ticks, ticks_per_frame) do
          -- honour the display button
          if is_key("print") then
    	 click("print")
          end
          -- if set key is pressed, indicate that we should stop
          if is_key("set") then
    	 return true
          end
       end
       return false
    end
    
    -- click "print" to turn on/off display
    function seek_display_mode()
       click "print"
    end
    
    -- switch to autofocus mode, pre-focus, then go to manual focus mode
    function pre_focus()
       local focused = false
       local try = 1
       while not focused and try <= 5 do
          print("Pre-focus attempt " .. try)
          press("shoot_half")
          sleep(2000)
          if get_prop(18) > 0 then
    	 focused = true
    	 set_aflock(1)
          end
          release("shoot_half")
          sleep(500)
          try = try + 1
       end
       return focused
    end
    
    Started = 0
    print( "PictUAV loop " )
    a = -1;
    repeat
    	aold = a
    	a = get_usb_power()
    	if (a ~= aold) then
    		print("a = " .. a)
    	end
    	if (a>7) then
    	        print( "shutting down " )
    
    			shut_down()
    			sleep(1500)
    	end
    	if (a>2) or (Started == 1) then
    		if Started == 0 then
    			print( "recording Started " )
    
    			sleep(1500)
    			Started = 1
    			if focus_at_start then
    			   if not pre_focus() then
    				  print "Unable to reach pre-focus"
    			   end
    			end
    			
    			start_ticks = get_tick_count()
    			
    			ticks_per_frame, total_frames, end_ticks = calculate_parameters(secs_frame, hours, minutes, start_ticks)
    			
    			frame = 1
    			
    			print "Press SET to exit"
    		end	
    		print_status(frame, total_frames, ticks_per_frame, end_ticks, endless)
    	   shoot()
    	--   if display_off_frame > 0 and frame >= display_off_frame then
    	--	  seek_display_mode()
    	--   end
    	   if frame_delay(frame, start_ticks, ticks_per_frame) then
    		  print "User quit"
    		  break
    	   end
    	   frame = frame + 1
    		
    	end
    until ( false )
    print( "PictUAV ended " )
    We will then lock the tab on the sd card and boot up the camera. Press the menu key and go to Scripting Parameters -> Load Script From File...

    and select Pictuav.lua

    Turn on autostart then go into "remote parameters->"
    Here we Enable the Remote (make it look like this[*]) which allows the chkd to listen to the usb power signal.
    The other two types are at 'none'

    hit menu to exit and then turn off your camera. When you turn it on again it should start the script and you should see

    ***Autostart***
    PictUAV Started
    PICTUAVLoop
    a=0

    The first two are debugging, and the third tells us that the last pulse received on the usb port was 0ms long (actually, the units are 10s of milliseconds).

    Once you connect the arduino and a servo tester you can change this to get the script to work.
    Last edited by BloomingtonFPV; 6th January 2013 at 11:33 PM.
    About to maiden my Fascination...

  4. #4
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Step 3: Connect an Arduino

    The RC receiver will put out a pulse-width modulated (PWM) signal, which is basically a signal that turns on for a given period of time and then turns off. The CHDK might or might not be able to read that, but I didn't want to take that chance. I also wanted to build some logic into the system to make sure I didn't accidentally launch my plane with the camera lens extended.

    I used a tiny arduino nano ($18):

    http://microcontrollershop.com/produ...oducts_id=3648

    I run the same 5v supply to the gnd and vcc (which is +) as my receiver gets, and I run channel 6 (a dial on my hitec eclipse 7, but a 3 position switch would also work) into pin 10.

    Pin 12 gets the output of the arduino and goes to the + on the USB connector for the canon camera.

    The ground on the canon camera USB connector must also be connected to the ground on the arduino. Note that there is a second ground along the upper edge of the board for these grounds.

    The Canon camera has the ability to 'listen' to the usb connector. That's how it knows to go into review mode when you plug your camera into the computer. The CHDK software has a routine called get_usb_power() which will return the duration of the last pulse you send.

    We use this to send out a code:

    a) 15ms pulse for 'standby' mode
    b) 45ms pulse for 'record' mode
    c) 90ms pulse for 'shutdown' mode

    The arduino is programmed to read the channel 6 of the receiver and monitor the duration of the pulses coming from the channel. If it is short, the 15ms pulse is sent out. If it is of medium length (corresponding to the middle position of the switch), the 45 ms pulse is sent out. The long duration pulse coming from the receiver gives a 90ms pulse for the camera.

    We also configure the software so that if the dial starts in either positions 2 or 3, no pulse is emitted until the switch is 'armed' by moving it into the first position. Once armed, however, recording can be paused by moving the switch to the first position.

    Below is the code for the arduino. Copy it and save it as CameraController.pde and install arduino from here:

    Upload it to your arduino via an fdti cable or usb depending on your board. It will run automatically. You may have to adjust these values:

    int StartState = 1250;
    int RecordStateStart = 1350;
    int RecordStateEnd = 1650;
    int ShutdownStart = 1750;

    If the switch is at the low end (less than 1250microseconds) it will be in arming mode. In between 1350 and 1650 it is in record mode, and anything above 1750 is shutdown mode.

    Code:
    /*
      Blink
      Turns on an LED on for one second, then off for one second, repeatedly.
     
      This example code is in the public domain.
     */
     
    // Pin 13 has an LED connected on most Arduino boards.
    // give it a name:
    int led = 13;
    int PWM_In = 10;
    int USB_Power_Out = 12;
    unsigned long duration;
    int StartState = 1250;
    int RecordStateStart = 1350;
    int RecordStateEnd = 1650;
    int ShutdownStart = 1750;
    int Armed = 0;
    int ActiveState;
    int STARTING = 0;
    int RECORDING = 1;
    int SHUTDOWN = 2;
    int DEADZONE = -1;
    
    // the setup routine runs once when you press reset:
    void setup() {                
      // initialize the digital pin as an output.
      pinMode(led, OUTPUT);     
      pinMode(USB_Power_Out, OUTPUT);     
      pinMode(PWM_In, INPUT);
        Serial.begin(9600);
     Armed = 0;
      digitalWrite(USB_Power_Out, LOW);
    Serial.println("Camera Controller Started");
    }
    
    // the loop routine runs over and over again forever:
    void loop() {
       duration = pulseIn(PWM_In, HIGH);
       Serial.println(duration);
       if (duration < StartState)
         {ActiveState = STARTING;} b 
       else 
       {ActiveState = SHUTDOWN;}
       
       //Serial.println( ActiveState);
      
         if (ActiveState == STARTING)
           {
             digitalWrite(USB_Power_Out, HIGH);
             digitalWrite(led, HIGH);
      
             delay(15);
             digitalWrite(USB_Power_Out, LOW);
             digitalWrite(led, LOW);
             Armed = 1;
             Serial.println("Arming");
         }//only arm if put in starting position 
       
       if (Armed > 0)
       {
         if (ActiveState == RECORDING)
         {
          //send short burst to camera to have it start recording
         //  if (Armed == 1)
          {
            Armed = 2; //recording
             Serial.println("Recording");
             digitalWrite(USB_Power_Out, HIGH);
            digitalWrite(led, HIGH);
    
            delay(35);
            digitalWrite(USB_Power_Out, LOW);
            digitalWrite(led, LOW);
    
         }
    
         }
         
         if (ActiveState == SHUTDOWN)
         {
          //send long burst to camera to shut it down
           // if (Armed > 0)
            {
                 Serial.println("Shutdown");
                digitalWrite(USB_Power_Out, HIGH);
                 digitalWrite(led, HIGH);
                
                 delay(90);
                 digitalWrite(USB_Power_Out, LOW);
                digitalWrite(led, LOW);
                
                //Armed = -1;
            }
    
         }
       }
       delay(200); 
    }
    Last edited by BloomingtonFPV; 6th January 2013 at 11:29 PM.
    About to maiden my Fascination...

  5. #5
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Step 4: Connect your receiver to your Arduino

    This is easy. Just power your arduino using the same 5 volt supply that powers your receiver, and run a 3 position switch (or a dial) channel into pin 10 on the arduino.

    You also need to connect your arduino to the camera.

    Pin 1 on the mini USB is 5v, and pin 5 is ground:

    http://www.accesscomms.com.au/reference/usb.htm

    Pin 1 goes to pin 12 on the arduino, and pin 5 connects to the ground on the arduino.
    Last edited by BloomingtonFPV; 7th January 2013 at 12:12 AM.
    About to maiden my Fascination...

  6. #6
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Step 5: Program the camera

    The CHDK software allows you to adjust the parameters (via the menu button) so you could set it to take pictures every 10 seconds or even focus before each shot. Don't access these via the function button because the settings don't get saved!
    Last edited by BloomingtonFPV; 6th January 2013 at 11:32 PM.
    About to maiden my Fascination...

  7. #7
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    Conclusions

    Right now the camera has been happily taking pictures every 2 seconds for the past 90 minutes. The next step is to mount this into the ZII and test it out.

    The two things I'm still a little worried about are center of gravity (it is in the front of the battery bay and the batteries are in cutouts in the wings), and launches.

    I upgraded the motor on the Z2 to a Hyperion 3020 1100kv motor. I'm running a 70 amp speed controller and two 4s 3300 mAh lipos.

    My plan is to launch with an overhead throw at about 30 degrees at full throttle. I should have enough juice to get into the air.

    So far I'd recommend this setup. I'm happy to answer questions about the build.

    -Tom
    Last edited by BloomingtonFPV; 7th January 2013 at 12:16 AM.
    About to maiden my Fascination...

  8. #8
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    adding video

    The same technique will work if the camera is in video mode on the dial (may not have to switch the dial, actually)

    with this script:

    Code:
    --[[
    @title VidUAV
    --]]
    -- switch to autofocus mode, pre-focus, then go to manual focus mode
    function pre_focus()
       local focused = false
       local try = 1
       while not focused and try <= 5 do
          -- print("Pre-focus attempt " .. try)
          press("shoot_half")
          sleep(2000)
          if get_prop(18) > 0 then
    	 focused = true
    	 set_aflock(1)
          end
          release("shoot_half")
          sleep(500)
          try = try + 1
       end
       return focused
    end
    
    -- print( "VidUAV Started " )
    
    Started = 0
    -- print( "VidUAV loop " )
    a = -1;
    repeat
    	aold = a
    	a = get_usb_power()
    	-- if (a ~= aold) then
    	-- 	print("a = " .. a)
    	-- end
    	if (a>7) then
    	   --      print( "shutting down " )
    
    			shut_down()
    			sleep(1500)
    	end
    	if (a>2) or (Started == 1) then
    		if Started == 0 then
    		-- 	print( "recording Started " )
    
    			sleep(1500)
    			Started = 1
    			if focus_at_start then
    			   if not pre_focus() then
    			-- 	  print "Unable to reach pre-focus"
    			   end
    			end
    			sleep(1000)
    
    			press("video")
    			sleep(2000)
    			release("video")
       		end	
    	end
    until ( false )
    -- print( "VidUAV ended " )
    About to maiden my Fascination...

  9. #9
    Flying my Fascination BloomingtonFPV's Avatar
    Join Date
    Mar 2011
    Location
    Bloomington, IN
    Posts
    1,016

    setting video parameters

    The caveat is that the video recording is buggy, and so you have to use version 1.2 of CHDK and turn off ALL the OSD functions in the camera. Nothing (except for the and the script name) should be showing. Also set Clear Videoparams on Start and Video Quality Control. My video mode was default and the quality was 84. Don't show remaining videotime or any other osd function.

    Under remote parameters you need to enable the remote but I had none for the two switch types. The options were left off.

    This camera has a 4gig limit on filesize so it will only record for about 15 minutes or so. I tried to use a script that would do continuous recording but it kept crashing. That's 4 gig on the 1080p/24hz setting. The lower video modes would probably go for longer.
    About to maiden my Fascination...

  10. #10
    Selective Fading.. Vintabilly_NS's Avatar
    Join Date
    Feb 2012
    Location
    East Side-Kanada
    Posts
    579
    Hey guys..
    We've been doing GIS work with a similar setup since 2011. Have you gotten as far as what to do with the pics once you have them?
    It's actually a hoot and I find the results are "juicier" than just going out and making flying videos.

    Good work on the scripting with CHDK.

    Check these threads too:
    http://fpvlab.com/forums/showthread....-Photo-Stitch&
    http://fpvlab.com/forums/showthread....apixel-Project

Page 1 of 2 12 LastLast

Similar Threads

  1. .
    By zolp in forum HD RECORDING / VIDEO EDITING
    Replies: 4
    Last Post: 21st December 2012, 08:12 PM
  2. CANON 7D AV OUT CORD FOR STINGER TRANSMITTER
    By nreim1 in forum ReadyMadeRC
    Replies: 1
    Last Post: 10th August 2012, 12:20 AM
  3. Aerial Exposure/ Got Aerial COLLAB
    By KMart in forum AIR SHOWS...
    Replies: 13
    Last Post: 4th October 2011, 01:29 AM
  4. Canon S95- A better GoPro?
    By BloomingtonFPV in forum HD RECORDING / VIDEO EDITING
    Replies: 3
    Last Post: 13th September 2011, 05:53 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •