Skip to content

Commit 5780e46

Browse files
authored
Merge pull request #4089 from njhollinghurst/camera_sync_again
Updates for synchronous and externally triggered cameras
2 parents 6f4aaa1 + abfe8ee commit 5780e46

File tree

2 files changed

+85
-68
lines changed

2 files changed

+85
-68
lines changed

documentation/asciidoc/accessories/camera/external_trigger.adoc

+26-15
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,6 @@ We can use a Raspberry Pi Pico to provide the trigger. Connect any Pico GPIO pin
2121

2222
image::images/pico_wiring.jpg[alt="Image showing Raspberry Pi Pico wiring",width="50%"]
2323

24-
==== Boot up the Raspberry Pi with the camera connected.
25-
26-
Enable external triggering through superuser mode:
27-
28-
[source,console]
29-
----
30-
$ sudo su
31-
$ echo 1 > /sys/module/imx296/parameters/trigger_mode
32-
$ exit
33-
----
34-
3524
==== Raspberry Pi Pico MicroPython Code
3625

3726
[source,python]
@@ -55,15 +44,37 @@ The low pulse width is equal to the shutter time, and the frequency of the PWM e
5544

5645
NOTE: In this example, Pin 28 connects to the XTR touchpoint on the GS camera board.
5746

58-
=== Operation
47+
=== Camera driver configuration
48+
49+
This step is only necessary if you have more than one camera with XTR wired in parallel.
50+
51+
Edit `/boot/firmware/config.txt`. Change `camera_auto_detect=1` to `camera_auto_detect=0`.
52+
53+
Append this line:
54+
[source]
55+
----
56+
dtoverlay=imx296,always-on
57+
----
58+
When using the CAM0 port on a Raspberry Pi 5, CM4 or CM5, append `,cam0` to that line without a space. If both cameras are on the same Raspberry Pi you will need two dtoverlay lines, only one of them ending with `,cam0`.
59+
60+
If the external trigger will not be started right away, you also need to increase the libcamera timeout xref:camera.adoc#libcamera-configuration[as above].
61+
62+
=== Starting the camera
63+
64+
Enable external triggering:
65+
66+
[source,console]
67+
----
68+
$ echo 1 | sudo tee /sys/module/imx296/parameters/trigger_mode
69+
----
5970

60-
Run the code on the Pico, and set the camera running:
71+
Run the code on the Pico, then set the camera running:
6172

6273
[source,console]
6374
----
6475
$ rpicam-hello -t 0 --qt-preview --shutter 3000
6576
----
6677

67-
Every time that the Pico pulses the pin, it should generate a frame. To control the framerate, vary the duration between pulses.
78+
Every time the Pico pulses the pin, it should capture a frame. However, if `--gain` and `--awbgains` are not set, some frames will be dropped to allow AGC and AWB algorithms to settle.
6879

69-
NOTE: When running `rpicam-apps`, always specify a fixed shutter duration to ensure the AGC does not adjust the camera's shutter speed. The duration does not matter, since it is actually controlled by the external trigger pulse.
80+
NOTE: When running `rpicam-apps`, always specify a fixed shutter duration, to ensure the AGC does not try to adjust the camera's shutter speed. The value is not important, since it is actually controlled by the external trigger pulse.
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,108 @@
11
== Synchronous Captures
22

3-
Both the HQ Camera and the Global Shutter Camera, have support for synchronous captures.
4-
Making use of the XVS pin (Vertical Sync) allows one camera to pulse when a frame capture is initiated.
5-
The other camera can then listen for this sync pulse, and capture a frame at the same time as the other camera.
3+
The High Quality (HQ) Camera supports synchronous captures.
4+
One camera (the "source") can be configured to generate a pulse on its XVS (Vertical Sync) pin when a frame capture is initiated.
5+
Other ("sink") cameras can listen for this pulse, and capture a frame at the same time as the source camera.
66

7-
=== Using the HQ Camera
7+
This method is largely superseded by xref:../computers/camera_software.adoc#software-camera-synchronisation[software camera synchronisation] which can operate over long distances without additional wires and has sub-millisecond accuracy. But when cameras are physically close, wired synchronisation may be used.
88

9-
For correct operation, both cameras require a 1.65V pull up voltage on the XVS line, which is created by a potential divider through the 3.3V and GND pins on the Raspberry Pi.
9+
NOTE: Global Shutter (GS) Cameras can also be operated in a synchronous mode. However, the source camera will record one extra frame. Instead, for GS Cameras we recommend using an xref:camera.adoc#external-trigger-on-the-gs-camera[external trigger source]. You cannot synchronise a GS Camera and an HQ Camera.
1010

11-
image::images/synchronous_camera_wiring.jpg[alt="Image showing potential divider setup",width="50%"]
11+
=== Connecting the cameras
1212

13-
Create a potential divider from two 10kΩ resistors to 3.3V and ground (to make 1.65V with an effective source impedance of 5kΩ). This can be connected to either Raspberry Pi.
13+
Solder a wire to the XVS test point of each camera, and connect them together.
1414

15-
Solder the GND and XVS test points of each HQ Camera board to each other.
15+
Solder a wire to the GND test point of each camera, and connect them together.
1616

17-
Connect the XVS wires to the 1.65V potential divider pull-up.
17+
*For GS Cameras only,* you will also need to connect the XHS (Horizontal Sync) test point of each camera together. On any GS Camera that you wish to act as a sink, bridge the two halves of the MAS pad with solder.
1818

19-
==== Boot up both Raspberry Pis
19+
NOTE: An earlier version of this document recommended an external pull-up for XVS. This is no longer recommended. Instead, ensure you have the latest version of Raspberry Pi OS and set the `always-on` property for all connected cameras.
2020

21-
The file `/sys/module/imx477/parameters/trigger_mode` determines which board outputs pulses, or waits to receive pulses (source and sink).
22-
This parameter can only be altered in superuser mode.
21+
=== Driver configuration
2322

24-
Run the following commands to configure the sink:
23+
You will need to configure the camera drivers to keep their 1.8V power supplies on when not streaming, and optionally to select the source and sink roles.
2524

26-
[source,console]
25+
==== For the HQ Camera
26+
27+
Edit `/boot/firmware/config.txt`. Change `camera_auto_detect=1` to `camera_auto_detect=0`.
28+
29+
Append this line for a source camera:
30+
[source]
2731
----
28-
$ sudo su
29-
$ echo 2 > /sys/module/imx477/parameters/trigger_mode
30-
$ exit
32+
dtoverlay=imx477,always-on,sync-source
3133
----
3234

33-
Run the following commands to configure the source:
34-
35-
[source,console]
35+
Or for a sink:
36+
[source]
3637
----
37-
$ sudo su
38-
$ echo 1 > /sys/module/imx477/parameters/trigger_mode
39-
$ exit
38+
dtoverlay=imx477,always-on,sync-sink
4039
----
4140

42-
Run the following command to start the sink:
41+
When using the CAM0 port on a Raspberry Pi 5, CM4 or CM5, append `,cam0` to that line without a space. If two cameras are on the same Raspberry Pi you will need two dtoverlay lines, only one of them ending with `,cam0`.
42+
43+
Alternatively, if you wish to swap the cameras' roles at runtime (and they are not both connected to the same Raspberry Pi), omit `,sync-source` or `,sync-sink` above. Instead you can set a module parameter before starting each camera:
4344

45+
For the Raspbery Pi with the source camera:
4446
[source,console]
4547
----
46-
$ rpicam-vid --frames 300 --qt-preview -o sink.h264
48+
$ echo 1 | sudo tee /sys/module/imx477/parameters/trigger_mode
4749
----
4850

49-
Run the following command to start the source:
50-
51+
For the Raspberry Pi with the sink camera:
5152
[source,console]
5253
----
53-
$ rpicam-vid --frames 300 --qt-preview -o source.h264
54+
$ echo 2 | sudo tee /sys/module/imx477/parameters/trigger_mode
5455
----
56+
You will need to do this every time the system is booted.
5557

56-
Frames should be synchronous. Use `--frames` to ensure the same number of frames are captured, and that the recordings are exactly the same length.
57-
Running the sink first ensures that no frames are missed.
58-
59-
NOTE: The potential divider is needed to pull up the XVS pin to high whilst the source is in an idle state. This ensures that no frames are created or lost upon startup. The source whilst initialising goes from LOW to HIGH which can trigger a false frame.
60-
61-
=== Use the GS Camera
58+
==== For the GS Camera
6259

63-
NOTE: The Global Shutter (GS) camera can also be operated in a synchronous mode. However, the source camera will record one extra frame. A much better alternative method to ensure that both cameras capture the same amount of frames is to use the xref:camera.adoc#external-trigger-on-the-gs-camera[external trigger method].
60+
Edit `/boot/firmware/config.txt`. Change `camera_auto_detect=1` to `camera_auto_detect=0`.
6461

65-
To operate as source and sink together, the Global Shutter Cameras also require connection of the XHS (horizontal sync) pins together. However, these do not need connection to a pullup resistor.
66-
67-
The wiring setup is identical to the xref:camera.adoc#using-the-hq-camera[HQ Camera method], except that you will also need to connect the XHS pins together.
68-
69-
Create a potential divider from two 10kΩ resistors to 3.3V and ground (to make 1.65V with an effective source impedance of 5kΩ). This can be connected to either Raspberry Pi.
70-
71-
Solder 2 wires to the XVS test points on each board and connect both of these wires together to the 1.65V potential divider.
62+
For either a source or a sink, append this line:
63+
[source]
64+
----
65+
dtoverlay=imx296,always-on
66+
----
67+
When using the CAM0 port on a Raspberry Pi 5, CM4 or CM5, append `,cam0` to that line without a space. If two cameras are on the same Raspberry Pi you will need two dtoverlay lines, only one of them ending with `,cam0`.
7268

73-
Solder the GND of each Camera board to each other. Also solder 2 wires to the XHS test points on each board and connect these. No pullup is needed for XHS pin.
69+
On the GS Camera, the sink role is enabled by the MAS pin and cannot be configured by software ("trigger_mode" and "sync-sink" relate to the xref:camera.adoc#external-trigger-on-the-gs-camera[external trigger method], and should _not_ be set for this method).
7470

75-
On the boards that you wish to act as sinks, solder the two halves of the MAS pad together. This tells the sensor to act as a sink, and will wait for a signal to capture a frame.
71+
=== Libcamera configuration
7672

77-
==== Boot up source and sink
73+
If the cameras are not all started within 1 second, the `rpicam` applications can time out. To prevent this, you must edit a configuration file on any Raspberry Pi(s) with sink cameras.
7874

79-
Run the following command to start the sink:
75+
On Raspberry Pi 5 or CM5:
76+
[source,console]
77+
----
78+
$ cp /usr/share/libcamera/pipeline/rpi/pisp/example.yaml timeout.yaml
79+
----
8080

81+
On other Raspberry Pi models:
8182
[source,console]
8283
----
83-
$ rpicam-vid --frames 300 -o sync.h264
84+
$ cp /usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml timeout.yaml
8485
----
8586

86-
Due to the limitations of the IMX296 sensor, the sink cannot record exactly the same number of frames as the source. **The source records one extra frame before the sink starts recording**. Because of this, you need to specify that the sink records one less frame with the `--frames` option.
87+
Now edit the copy. In both cases, delete the `#` (comment) from the `"camera_timeout_value_ms":` line, and change the number to `60000` (60 seconds).
8788

88-
Wait at least two seconds before you start the source.
89+
=== Starting the cameras
8990

90-
After waiting two seconds, run the following command to start the source:
91+
Run the following commands to start the sink:
9192

9293
[source,console]
9394
----
94-
$ rpicam-vid --frames 299 -o sync.h264
95+
$ export LIBCAMERA_RPI_CONFIG_FILE=timeout.yaml
96+
$ rpicam-vid --frames 300 --qt-preview -o sink.h264
9597
----
9698

97-
Because the sink and source record a different number of frames, use `ffmpeg` to resync the videos. By dropping the first frame from the source, we then get two recordings with the same starting point and frame length:
99+
Wait a few seconds, then run the following command to start the source:
98100

99101
[source,console]
100102
----
101-
$ ffmpeg -i source.h264 -vf select="gte(n\, 1)" source.h264
103+
$ rpicam-vid --frames 300 --qt-preview -o source.h264
102104
----
105+
Frames should be synchronised. Use `--frames` to ensure the same number of frames are captured, and that the recordings are exactly the same length.
106+
Running the sink first ensures that no frames are missed.
107+
108+
NOTE: When using the GS camera in synchronous mode, the sink will not record exactly the same number of frames as the source. **The source records one extra frame before the sink starts recording**. Because of this, you need to specify that the sink records one less frame with the `--frames` option.

0 commit comments

Comments
 (0)