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
  • 8
  • 38
  • 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
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,813
  • 4
  • 22
  • 31
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
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,988
  • 16
  • 22