20

I'm trying to trigger "many" raspberries together, while using raspistill is only for testing, i'm wondering why taking a picture is so slow, i made a test and, at the same time as i hit enter on this command:

raspistill -o /home/pi/test55.jpg -ex sports --nopreview

I start an iPhone chronometer in front of the camera. The result? 7 seconds, 09 (but sharp, so shutter speed etc was fine, i wasn't getting blurred number). What can i do for it to "not" take X seconds before taking the picture? I'm going to sync hundreds of RPI and i don't want some of them to take the picture at 4 and some other at 10 seconds so i'd like to understand just what is happening there.

Patrick Cook
  • 6,365
  • 7
  • 37
  • 63
Ronan Thibaudau
  • 360
  • 1
  • 3
  • 9

4 Answers4

7

You need to have the camera process running all the time.

This is the only way I could acheive results of (on average) 50ms. I looked everywhere for a solution. 1 second was just too slow for my motion sensor project.

@Dave Jones 's project helped me figure out how to do it.

Just 2 files:

a daemon, running all the time and a client.

The daemon is where you set all the camera settings.

picam-daemon.py

picam-client.py

python picam-daemon.py

import threading
import os, io, base64, time, socket, picamera, daemon
import daemon.runner

MAX_LENGTH = 50 # max length of any possible entry from "client"
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # setup socket
PORT = 10000 # port 10000
HOST = '127.0.0.1' # runs on local host
serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # this allows us to override port, prevents error
serversocket.bind((HOST, PORT)) # lock server to this port and host
serversocket.listen(10) # max 10 clients


# Waits for commands, such as "snap" and "ack"
# Runs over "sockets"
def handle(clientsocket):
    while 1:
        buf = clientsocket.recv(MAX_LENGTH)

        # Receive the SNAP command. Take a picture with PiCam.
        if buf == 'snap':
            start = time.time()
            camera.capture('/home/pi/ir/picam-latest-snap.jpg')
            finish = start - time.time()
            print finish
            print 'Picture Taken!'

        if buf == 'ack':
            print 'Ping: Hello!'

        if len(buf) == 0: break

# Camera is always loaded here
# The "magic" is in the camThread, this allows a picture to be captured, then it gracefully closed the camera connection and reopens it. This produces very fast captures (54ms vs 1.5s!)
while 1:
    # setup camera
    camera = picamera.PiCamera()
    camera.resolution = (640, 480)
    #camera.zoom = (0.2, 0.2, 1.0, 1.0)
    camera.exposure_mode = 'sports'
    print('Camera server running')

    # accept connections from outside, in order to receive commands
    (clientsocket, address) = serversocket.accept()
    ct = threading.Thread(target=handle, args=(clientsocket,))
    ct.run() # this can be run(), because it can be scaled.

    print 'Camera thread starting.'
    camThread = threading.Thread()
    while camThread.is_alive():
        camThread.join(1)
    camThread.run() # this must be start(), otherwise PiCam will crash. This is because PiCam cannot receive more than 1 connection.
    print 'Camera thread ended'
    camera.close() # Gracefully close PiCam if client disconnects

(in a second terminal) python picam-client.py

import socket
import sys


HOST = '127.0.0.1'
PORT = 10000
s = socket.socket()
s.connect((HOST, PORT))

print s

while 1:
    msg = raw_input("Command To Send: ")
    if msg == "close":
       s.close()
       sys.exit(0)
    s.send(msg)

I'm posting this answer because I found this in Google, trying to find an answer myself. I couldn't find one, so I had to dig around some projects and come up with something myself.

Entryton
  • 106
  • 1
  • 8
  • When encountering the same problem, I came up with the same solution, but hadn't gotten anywhere near writing the code yet. Glad to see that someone else beat me to it! – Nick Coons Apr 06 '19 at 00:42
  • Such helpful code. Thank you! Updated for python3 and some additional commands for picture, filenames and video. Daemon: https://gist.github.com/swerty24/68fbe9c330d41d72303d2bfafcd97da5 Client: https://gist.github.com/swerty24/0448a38a2800d426ae9bec67d09b49ba – MethodMan Sep 21 '21 at 05:43
6

You need to specify a timeout of 0.

From the raspistill help

-timeout "Time (in ms) before takes picture and shuts down (if not specified, set to 5s)

To test how long a command takes to execute you can use "time"

time raspistill -o /home/pi/test55.jpg -ex sports --nopreview --timeout 0
rob
  • 2,803
  • 2
  • 21
  • 31
  • This removes the default timeout of 5 second but the issue is i'm getting more than that, from what i understand on the forum there is no real way using raspistill as is to get no delay images – Ronan Thibaudau Oct 06 '14 at 13:16
  • 8
    In my Raspberry, specifying timeout of 0 seems to mean "infinite", while specifying a timeout of "1" seems to do the trick – DWilches Apr 13 '15 at 23:25
  • 4
    Also, using such a low timeout doesn't give the camera enough time to expose the collectors, resulting in a darkened image. I find I can't go lower than around 300 before the image starts getting dark and blurry. – Cerin Oct 17 '15 at 21:57
  • 2
    If not severely necessary leave the -t option out. As @Cerin states this somehow destroys the image if set too low. To be honest the Raspberry Pi's documentation has way too little information about this option and leads to the false assumption that the timeout is a simple "delay" / "time trigger" which it clearly is not. – Flatron May 21 '16 at 15:15
5

I have specified the following alias in my .bash_profile to allow for easy and fast camera shots:

alias shot='SHOTTIME=$(date +"%Y-%m-%d_%H%M") && raspistill -o shot-$SHOTTIME.jpg --nopreview --exposure sports --timeout 1

Whenever I type shot on command line, an image with time stamp is saved, for example shot-2016-02-27_0934.jpg.

NDB
  • 269
  • 3
  • 8
  • 1
    Welcome to the Raspberry Pi Stack Exchange community! Even with the --timeout 1 argument(?) I'd be surprised if it was that quick - but as I haven't (yet) got my system to such a state that it takes a snap-shot of who ever tries to unlock my front-door I can't really pick-nits! 8-) Good use of command line though (assuming the clock has been set) - including putting the datetime stamp with the most significant values first so the alpha-numeric sort-order is the same as date sort-order! – SlySven Feb 27 '16 at 19:54
  • 1
    ~$ time shot real 0m0.040s user 0m0.010s sys 0m0.020s

    q. e. d. ;)

    – NDB Feb 28 '16 at 19:32
  • 2
    0.040 seconds is unfortunately far to fast to be true.. The usage of the time command above is flawed, it will actually only measure the time taken to assign the SHOTTIME variable, not capturing the image. The real time is ~1 seconds. – slackhacker Aug 20 '16 at 13:52
  • Thank you for your comment, you are right. I have removed the time it takes from my original text. – NDB Aug 24 '16 at 20:02
2

You might want to have a look at the compoundpi project (full disclosure: I'm the author). It's intended for triggering captures from numerous Pi's with camera modules and uses UDP broadcast packets to get them all triggering as close together as possible. A daemon runs on each Pi which fires up the camera and triggers captures upon receipt of a UDP packet containing the CAPTURE command (other commands are available to configure the camera; the protocol is fairly well documented). A setup using Ethernet is ideal, but wifi will work as well, although you may have to use the time-delay functionality to get decent synchronization in that case (due to packet loss / variable latency).

I can't say it's been tested with 100 Pi's - at the moment the biggest setup using it involves 20, but I'd be interested to hear of any issues involving larger scales.

The project includes a command line client, a GUI client (written in Qt so it should work on Linux/Mac/Windows but it's only been tested on Ubuntu at this point, and it's still undocumented), and a Python-based client library for writing batch jobs.

Dave Jones
  • 3,978
  • 15
  • 22
  • I'm not very worried about the udp part nor the client (i don't want to control them by hand, they're controlled by a much larger project) but does compoundpi use something that takes near instant capture or does it also have a delay like raspistill? – Ronan Thibaudau Oct 06 '14 at 13:17
  • Dave, it seems you're the author of projects that revolve around what i need, is there any chance we could have a Skype or email discussion? – Ronan Thibaudau Oct 06 '14 at 13:18
  • Certainly - do feel free to email me directly (my e-mail address should visible on my GitHub profile) – Dave Jones Oct 06 '14 at 13:21
  • 1
    Oh, and on your other question: it's near instant. When the compoundpi daemon is started it initializes and configures the camera (which is where a lot of delay in raspistill comes from) then awaits a capture command. The capture command can either instantly cause a capture or wait until a specified timestamp before capturing. In the instant case, the delay between receipt of command and capture should be milliseconds. – Dave Jones Oct 06 '14 at 13:27
  • Dave Jones, this idea of initialising the camera before taking the capture, can you give more info? Can we do this from the commandline? – Ollie Mar 27 '15 at 06:44