supplierdeeply

Synchronizing two SX40s

  • 33 Replies
  • 3136 Views
Synchronizing two SX40s
« on: 03 / March / 2014, 10:29:51 »
Advertisements
Hi, I have now got two SX40s that I intend to use for stereo-photography and would like to eventually synchronize pretty much everything across the cameras. In a master/slave configuration probably. I know that will take a lot of work so I'll have to do it step-by-step. I plan on using a micro between the two cameras.


The back-story is below, doesn't contain any questions or useful information
Quote
About a week ago while I was putting the SX40 back together after repairing it I managed to damage the end of the ribbon connector for the buttons on the back. After a few days trying to solder a hair-thin wire across each contact pad, all the buttons finally work (except for the power-LED as it's pad came off). I dare not open it up again in case the very messy repair stops working. Not to worry though, I have my other original SX40 which I can do some testing on.

In case anyone's interested in what was wrong with it, it was a power issue on the mainboard. I had naively bought the second SX40 thinking that the missing battery door was the reason it was reported to not turn on. Unfortunantly when I got it I found that the door had been perposely taken off as a spare part, as the camera wasn't working. Swapping the mainboard around with the one on my working SX40 isolated the problem to the mainboard. Comparing voltages present on the decoupling caps located the 4 missing voltages. Bridging a largeish 3.3 volt supply on the mainboard to a missing 3.3 volt rail made all the other voltages return, and it powered on!

I had plans to transplant the viewfinder from the "slave" camera to the side of the "master" to get a stereo preview, but had no way to reliably send the 27MHz signals through wires between the two, so I think I'll have to use a separate viewfinder rig running off the composite video outputs.

The fix however has one side effect that I only just noticed now that I'm putting together the rig. If the battery temperature input is connected to anything when switching to camera-mode for the first time, it'll tell me to change the battery. So it has to be started up then plugged in. Don't want to open it up again just to fix this minor issue (not that I know exactly what's causing it anyway).


Is there any way I could trick the camera into ignoring the battery temp when it goes into shooting mode for the first time?

I will have some more questions coming up in the next few days as I run into problems. For now I have to build the hardware (such as the shoulder-mount and the external stereo evf) which may take a while.

One other thing of interest I'm going to do is synchronize them via GPS for when they're 100m apart for cloud stereo photography. I'm going to do that with the Navspark, anyone else here ordered any or at least heard of it?

Re: Synchronizing two SX40s
« Reply #1 on: 03 / March / 2014, 10:40:49 »
Is there any way I could trick the camera into ignoring the battery temp when it goes into shooting mode for the first time?
You will probably have to do a lot of reverse engineering / dissassembly to determine where that test is made.  I don't think it's part of the current CHDK assembler code FWIW.

There is of course a more obvious solution - use a resistance value on the battery input that mimics a normal battery temperature for the remote "off" state. Then short or open that connection for an "on" state.
Ported :   A1200    SD940   G10    Powershot N    G16

*

Offline ahull

  • *****
  • 634
Re: Synchronizing two SX40s
« Reply #2 on: 03 / March / 2014, 10:52:50 »
Is there any way I could trick the camera into ignoring the battery temp when it goes into shooting mode for the first time?
You will probably have to do a lot of reverse engineering / dissassembly to determine where that test is made.  I don't think it's part of the current CHDK assembler code FWIW.

There is of course a more obvious solution - use a resistance value on the battery input that mimics a normal battery temperature for the remote "off" state. Then short or open that connection for an "on" state.

If you have the battery pin attached to a D to A pin on your micro-controller, you may be able to simulate a range of temperatures using suitable values of resistors to create a voltage in the correct range to  fool the A to D converter in the camera. You could also use a D to A pin on the micro-controller to adjust a digital potentiometer chip, and use that as your fake thermistor.

Something like this...


waterwingz's solution is probably simpler though.
« Last Edit: 03 / March / 2014, 10:56:33 by ahull »

Re: Synchronizing two SX40s
« Reply #3 on: 05 / March / 2014, 10:50:24 »
I'm going to be using the AF LED to communicate to the slave camera for now (and probably for the slave to communicate back to the master if necessary). I believe the code to turn on the power LED on the SX40 is *((volatile int *) 0xC0220134) = 0x46; right? However after some searching both through the source (with grep) and the internet I cannot find the address for the SX40's AF LED. I'd much rather use the AF LED as it doesn't just flash whenever it wants to (and also as the power LED on one of the SX40s isn't even connected anymore). Does anyone know what the address may be or will I have to use an LED finding script?

About the problem I had earlier with anything connected to the faulty SX40's battery temp input causing it not start up, the problem seems to have gone now that I've changed some wiring on the rig. The problem was pretty bad, any resistor below about 360K to gnd would cause it. But it seems to work fine now.

One other question I have at the moment is about synchronizing the focus. Basically something that would get the focus from the master (perhaps during halfpress or when the cameras are awaiting the precision sync signal) and then send it to the slave camera which would set it's focus to that value. I can probably figure out the sending part, but I'm not sure how to get or set the focus from within the source, only from a script (and I don't really want to be doing this all from within a script)


*

Offline nafraf

  • *****
  • 1303
Re: Synchronizing two SX40s
« Reply #4 on: 05 / March / 2014, 11:57:18 »
Does anyone know what the address may be or will I have to use an LED finding script?
In platform/sx40hs/sub/100d/stubs_entry.S:
Code: [Select]
// LED table init @ 0xff15b1f0
// LED #1: 0xc022c200 (#98 in GPIO table), offset 0x1d8
// LED #2: 0xc022c024 (#81 in GPIO table), offset 0xa0

*

Offline srsa_4c

  • ******
  • 3688
Re: Synchronizing two SX40s
« Reply #5 on: 05 / March / 2014, 18:26:58 »
Does anyone know what the address may be or will I have to use an LED finding script?
In platform/sx40hs/sub/100d/stubs_entry.S:
Code: [Select]
// LED table init @ 0xff15b1f0
// LED #1: 0xc022c200 (#98 in GPIO table), offset 0x1d8
// LED #2: 0xc022c024 (#81 in GPIO table), offset 0xa0
After having taken a look at the sx40's LEDCon task, I think that not more than one of those LED addresses will likely work. The magic numbers used to switch on and off that LED are 0x93d800 and 0x83dc00.
There's a "special case" LED @ 0xc022c30c:
*(int*)0xc022c30c = ((*(int*)0xc022c30c) & 0xffffffcf) | 0x20 // switch on
*(int*)0xc022c30c = (*(int*)0xc022c30c) & 0xffffffcf // switch off

I have no idea which address corresponds to which physical LED.

Re: Synchronizing two SX40s
« Reply #6 on: 05 / March / 2014, 23:59:41 »
Quote
In platform/sx40hs/sub/100d/stubs_entry.S:
Code: [Select]

// LED table init @ 0xff15b1f0
// LED #1: 0xc022c200 (#98 in GPIO table), offset 0x1d8
// LED #2: 0xc022c024 (#81 in GPIO table), offset 0xa0
Quote
The magic numbers used to switch on and off that LED are 0x93d800 and 0x83dc00.
OK thanks, the address that worked was 0xc022c200 with those numbers.
For some reason the stubs_entry.S that I have doesn't seem to have that comment in it so it's probably been updated since I downloaded the source.

Quote
There's a "special case" LED @ 0xc022c30c:
*(int*)0xc022c30c = ((*(int*)0xc022c30c) & 0xffffffcf) | 0x20 // switch on
*(int*)0xc022c30c = (*(int*)0xc022c30c) & 0xffffffcf // switch off
This turned out to be the power LED on the back. Now if only I had bothered to repair the broken ribbon cable pad for the power LED on the faulty SX40...

Re: Synchronizing two SX40s
« Reply #7 on: 06 / March / 2014, 11:16:13 »
Ran into another smallish problem (I hope). Actually two problems.

Firstly, I added this to kbd_process.c (in long kbd_process() )
Code: [Select]
    if (kbd_is_key_pressed(KEY_SHOOT_FULL))
{
        key_pressed = 0;
        kbd_key_release_all();         
        return 1;
}
(and also one for half-press)
and replaced the appropriate lines in usb_remote.c with kbd_is_key_pressed(KEY_SHOOT_FULL) so that the full-shoot button would act as a the usb remote input. However it doesn't work (nothing happens) I'm pretty sure it's because kbd_key_release_all() virtually releases the keys even within CHDK right? How would I be able to get around this?

Also, I tried it with the zoom assist button without those lines in kbd_process.c and it nearly works, but when the button is released to take the photo (in two-press mode) it doesn't recognise it and instead just times out after 10 seconds. I'm assuming this is because somehow the state of that button can't be properly read during void _wait_until_remote_button_is_released(void), any idea of what could be done to allow it to be read?

FWIW here is the code that's in it.
Code: [Select]
void _wait_until_remote_button_is_released(void)
{
int tick;

if ( ( conf.remote_enable ) // menu : USB remote enabled - bracket everything in this function
&& ( conf.synch_enable  ) // menu : Sync enabled - tells us to wait for USB to disconnect
&& ( usb_sync_wait      ) ) // only sync when USB remote is active - don't trap normal shooting
{
usb_remote_status_led(1); // indicate to user we are waiting for remote button to release - this happens every time the camera takes a picture
tick = get_tick_count(); // timestamp so we don't hang here forever if something goes wrong

//    #ifdef USB_REMOTE_PRECISION_SYNC
//if ( conf.synch_vnd_enable )
//{
int std_period = _EngDrvRead(GPIO_VSYNC_MAX);
        int sync_time = std_period * 3;         // schedule the end of extended period at t = t(synch pulse) + sync_time
    if ( conf.remote_input == 0 )
{
do { }  while( get_usb_bit() &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
}
if ( conf.remote_input == 1 )
{
// do { }  while( (*(short*)0xc090004a < 300) &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
do { }  while( (kbd_is_key_pressed(KEY_ZOOM_ASSIST)) &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
}
        int cur_cnt = *(volatile int*)(GPIO_VSYNC_CURRENT) & 0xffff; // get the counter state at the time of sync
        int sync_period = sync_time - (std_period - cur_cnt);
        if (std_period - cur_cnt < 10)
        {
            // too close to overflow, wait for the next period
            sync_period -= std_period;
            while ((*(volatile int*)(GPIO_VSYNC_CURRENT) & 0xffff) >= cur_cnt) {};
        }
        *(volatile int*)(GPIO_VSYNC_MAX) = sync_period; // write the length of the extended period to the register
        *(volatile int*)(GPIO_VSYNC_UPDATE) = 1;
        while (*(volatile int*)(GPIO_VSYNC_UPDATE)) {}; // wait until the new value is applied
        //now we are at the beginning of extended period
        *(volatile int*)(GPIO_VSYNC_MAX) = std_period; // back to standard timing on next period
        *(volatile int*)(GPIO_VSYNC_UPDATE) = 1;
        msleep(40);
//    #endif
//}
// Commented out code removed
        sync_counter++ ;
        usb_sync_wait = 0 ;
        usb_remote_status_led(0);       // alert the user that we are all done

}


*

Online reyalp

  • ******
  • 11491
Re: Synchronizing two SX40s
« Reply #8 on: 06 / March / 2014, 22:44:40 »
Also, I tried it with the zoom assist button without those lines in kbd_process.c and it nearly works, but when the button is released to take the photo (in two-press mode) it doesn't recognise it and instead just times out after 10 seconds. I'm assuming this is because somehow the state of that button can't be properly read during void _wait_until_remote_button_is_released(void), any idea of what could be done to allow it to be read?
The key_is* functions are just reading from the physw_status values that are maintained by kbd task. This won't give you the kind of precise timing you get from the usb remote, and if your code prevents kbd_task from executing (perhaps by being in a higher priority task sitting in a tight loop) then it won't update at all.

To do something equivalent to USB remote using key inputs, you'd want to read the MMIO addresses for the keys directly.  _GetKbdState may do this for you, or provide you with the addresses in disassembly.
Don't forget what the H stands for.

Re: Synchronizing two SX40s
« Reply #9 on: 06 / March / 2014, 22:55:23 »
FWIW here is the code that's in it.
Code: [Select]
void _wait_until_remote_button_is_released(void)
{
int tick;

if ( ( conf.remote_enable ) // menu : USB remote enabled - bracket everything in this function
&& ( conf.synch_enable  ) // menu : Sync enabled - tells us to wait for USB to disconnect
&& ( usb_sync_wait      ) ) // only sync when USB remote is active - don't trap normal shooting
{
usb_remote_status_led(1); // indicate to user we are waiting for remote button to release - this happens every time the camera takes a picture
tick = get_tick_count(); // timestamp so we don't hang here forever if something goes wrong

//    #ifdef USB_REMOTE_PRECISION_SYNC
//if ( conf.synch_vnd_enable )
//{
int std_period = _EngDrvRead(GPIO_VSYNC_MAX);
        int sync_time = std_period * 3;         // schedule the end of extended period at t = t(synch pulse) + sync_time
    if ( conf.remote_input == 0 )
{
do { }  while( get_usb_bit() &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
}
if ( conf.remote_input == 1 )
{
// do { }  while( (*(short*)0xc090004a < 300) &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
do { }  while( (kbd_is_key_pressed(KEY_ZOOM_ASSIST)) &&  ((int)get_tick_count()-tick < DELAY_TIMEOUT));
}
        int cur_cnt = *(volatile int*)(GPIO_VSYNC_CURRENT) & 0xffff; // get the counter state at the time of sync
        int sync_period = sync_time - (std_period - cur_cnt);
        if (std_period - cur_cnt < 10)
        {
            // too close to overflow, wait for the next period
            sync_period -= std_period;
            while ((*(volatile int*)(GPIO_VSYNC_CURRENT) & 0xffff) >= cur_cnt) {};
        }
        *(volatile int*)(GPIO_VSYNC_MAX) = sync_period; // write the length of the extended period to the register
        *(volatile int*)(GPIO_VSYNC_UPDATE) = 1;
        while (*(volatile int*)(GPIO_VSYNC_UPDATE)) {}; // wait until the new value is applied
        //now we are at the beginning of extended period
        *(volatile int*)(GPIO_VSYNC_MAX) = std_period; // back to standard timing on next period
        *(volatile int*)(GPIO_VSYNC_UPDATE) = 1;
        msleep(40);
//    #endif
//}
// Commented out code removed
        sync_counter++ ;
        usb_sync_wait = 0 ;
        usb_remote_status_led(0);       // alert the user that we are all done

}
Incidentally,  that's not a patch of the code that is now in the 1.3.0 trunk.   Regardless, as reyalp said in the previous post,  calling kbd_is_key_pressed() just looks at an array of key values, none of which will change because wait_until_remote_button_is_released() has you locked in a tight loop hogging the processor.

I probably missed it, but why are you trying to do this?
« Last Edit: 06 / March / 2014, 23:02:20 by waterwingz »
Ported :   A1200    SD940   G10    Powershot N    G16

 

Related Topics