I am currently attempting to synchronize four raspberry pi 3s using Pi Camera V2s to take photos of a stopwatch at the same time. I am using a function generator to send a signal to the GPIO pin. The images are occasionally .033 seconds apart. I believe I have pinpointed the source of this. I used a profiler on a python script that simply captures an image. Looking at the processes, a "sleep" function of duration .033 seconds is being called usually 14 times. It sometimes, however, is called 15 times, which would account for the discrepancy. I believe this extra instance of sleep is occurring before the shutter begins to open, which would make the cameras images captured .033 seconds apart. I cannot, however, for the life of me, find how/where the shutter is triggered to open in the picamera python library. My thought is that if instead of it trying to decide how long to wait, I hard coded a wait period long enough to ensure everything is in order, the cameras will all capture the image at the same time. If anyone knows of where to find when the shutter is being opened or any other insight into the matter, that would help a lot. Thanks guys. I can attempt to further clarify or provide further information if needed.

  • This answer may shed some light on the situation. – Dave Jones Jul 23 '16 at 14:19
  • For initial clarification, we had the cameras pointed at a digital stopwatch. That is not quite what my problem is. All of the cameras start their capture at the same time. Occasionally, the sleep function running parallel to the encoding process will run 1 extra time causing one of the images to show a time .033 seconds later than the other camera. (It happens to either camera). The issue doesn't compound. Often times the next image is in sync. The issue does not compound because after every picture is taken, the python script waits for a trigger from a function generator before capturing. – MaxwellG Jul 25 '16 at 13:17
  • P.S. I was wondering if you plan on updating your picamera library for the camera v2, or if this has already been done. I ask because I had to update the picamera.array file myself to get it to work with the new camera, and I assume your work with that would be better than mine. – MaxwellG Jul 25 '16 at 13:18
  • picamera 1.11 was released a couple of weeks ago with V2 camera module support, but a bug with unencoded captures under Python 3 caused 1.12 to be released the week after (1.11's now in Raspbian, 1.12 not quite yet - both available on PyPI though). As to your sync issue, 0.033 seconds is about one frame's worth which is exactly what I'd expect to see from cameras with different init times but the same capture time (because capture doesn't actually start a capture, it just causes the camera to wait for the next complete frame and pass it back). – Dave Jones Jul 25 '16 at 13:50
  • Glad to see you're supporting it! I just checked it out. One of the fixes we had previously made to picamera.array was to remove the numpy delete function, as this took over 1 whole second to complete. Instead, we simply built a new array as we rebuild the 4 10-bit numbers from the 5 8-bit numbers. This shaved ~1.5 seconds off the time it took to save a raw image. We also had it save as a 2D array instead of 3D. The zeros in the 3D array cause the file to be much larger in size. Also, most debayering algorithms (such as Matlab's) take 2D raw data as an input. – MaxwellG Jul 25 '16 at 14:52

When you call the capture function of the picamera object it is starting the encoding and waiting for a callback to reset wait and so indicate it is complete (or for CAPTURE_TIMEOUT to be exceeded):

        # Wait for the callback to set the event indicating the end of
        # image capture
        if not encoder.wait(self.CAPTURE_TIMEOUT):
            raise PiCameraRuntimeError(
                'Timed out waiting for capture to end')

the encoder.wait function looks like this:

    result = self.event.wait(timeout)
    if result:
        # Check whether the callback set an exception
        if self.exception:
            raise self.exception
    return result

and if you look at how event.wait is implemented (here's a great SE question that goes into detail on it), it is made up of a number of smaller (than the timeout) delays (getting longer as time goes on) and after each one checking if the lock can be acquired.

I would expect there to be very small variances in the time that each Pi takes to acquire the lock, and possibly one occasionally rolls over to a 15th sleep.

So, in summary, not something that you have any control over...

  • Thank you for the response. So, the event basically tells the capture to wait until the encoding is complete. If I see that the process at most takes some arbitrary amount of time x, could I just have the pi's not use the event to be told how long to wait and instead tell them to all wait some arbitrary amount of time x + y. That way, they should all be waiting the same amount of time to continue instead of waiting 14 or 15 steps, thus desyncing. – MaxwellG Jul 24 '16 at 13:54
  • I don't believe that functionality is available in the picamera library. You could add it, or write your own, but that is a much bigger task... If your concern is that one camera is frequently going to take longer and drift more and more out of sync then adding a variable/compensated delay after each capture might help 'resync' them for the next capture... That said, I defer to the comment on the OP by @Dave Jones , he clearly understand the inner workings better than I do. – KennetRunner Jul 24 '16 at 14:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.