> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dwe.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Bildesynkronisering av flere kameraer

> En veiledning for hvordan du synkroniserer stellarHD-kameraer.

<Icon icon="triangle-person-digging" color="#FFC107" iconType="regular" size={32} /> ***Denne dokumentasjonen er fortsatt under forbedring og bygging!***

<Note>
  Både **elektrisk** og **programvarebasert** synkronisering kreves. Se nedenfor for detaljerte instruksjoner.
</Note>

# Veiledning for elektrisk kabling

<Tabs>
  <Tab title="Leader-Follower-modus">
    ## Oversikt

    Denne modusen er laget for konfigurasjoner **som ikke bruker et eksternt klokkesignal**.

    Du vil bruke ett kamera i `leader`-modus (som sender ut et synkroniseringssignal) og alle resterende kameraer i `follower`-modus.

    <Card title="Veiledning for Leader/Follower-fastvare" icon="link" href="/no/stellarHD/guides/stellarHD-firmware">
      Klikk her for å se veiledningen for å oppdatere kameraet ditt mellom Leader- og Follower-modus.
    </Card>

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-light.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=4c5823a5d745629d5a62fb7dd84a1a49" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-light.svg" />

      <img className="hidden dark:block" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-dark.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=1ae7234422717f420009665eb9043f22" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-dark.svg" />
    </Frame>

    ***

    ## Kabling

    <Frame>
      <img width="800px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Diagram.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=5b0ab2de70b284309a3f13901f0a77b9" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Diagram.svg" />
    </Frame>

    ### Eksempel

    <Frame caption="Et eksempel på ledninger fra to kameraer koblet for bildesynkronisering.">
      <img width="400px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Example.jpg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=8fedebc8290229dd132d773e49a63a49" data-path="stellarHD/guides/images/syncing-multiple-cameras/Leader-Follower-Wiring-Example.jpg" />
    </Frame>
  </Tab>

  <Tab title="Follower-Only-modus (eksternt klokkesignal)">
    ## Oversikt

    Denne modusen er laget for konfigurasjoner **som bruker et eksternt klokkesignal** for å sende ut synkroniseringssignalet til alle kameraer.

    I denne modusen må alle kameraer settes til `follower`-modus.

    <Card title="Veiledning for Leader/Follower-fastvare" icon="link" href="/no/stellarHD/guides/stellarHD-firmware">
      Klikk her for å se veiledningen for å oppdatere kameraet ditt mellom Leader- og Follower-modus.
    </Card>

    <Frame>
      <img className="block dark:hidden" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-light.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=362833b4adcee1048a3833f297c67770" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-light.svg" />

      <img className="hidden dark:block" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-dark.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=fd356395a3435524d7647e4928f2126c" width="800" height="300" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Follower-dark.svg" />
    </Frame>

    ***

    ## Kabling

    Sjekk produktsiden for din spesifikke enhet for spesifikasjoner for ekstern bildesynkronisering.

    <Frame>
      <img width="800px" src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Wiring-Diagram.svg?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=b49517610c550da641202bb88f6441ab" data-path="stellarHD/guides/images/syncing-multiple-cameras/External-Signal-Wiring-Diagram.svg" />
    </Frame>

    ***

    ## Generering av eksternt klokkesignal

    ### Arduino-integrasjon

    <Note>
      **Arduino Uno (ATmega328P)** er for øyeblikket det eneste *bekreftede* fungerende kortet for denne konfigurasjonen.
    </Note>

    <Steps>
      <Step title="Last ned PWM-biblioteket">
        Last ned kildekoden for PWM-biblioteket her: [ArduinoPWM v1.0.0](https://github.com/DeepWaterExploration/ArduinoPWM/archive/refs/tags/v1.0.0.zip)
      </Step>

      <Step title="Legg til .ZIP-biblioteket">
        Importer det nedlastede `.ZIP`-biblioteket i Arduino IDE.

        <Frame>
          <img src="https://mintcdn.com/deepwaterexplorationinc/PotJvdv7IDe7YzbV/stellarHD/guides/images/syncing-multiple-cameras/ArduinoPWM-Library.png?fit=max&auto=format&n=PotJvdv7IDe7YzbV&q=85&s=ae6bb3c799a2b3d3dba92d8696fa9dce" width="1210" height="933" data-path="stellarHD/guides/images/syncing-multiple-cameras/ArduinoPWM-Library.png" />
        </Frame>
      </Step>

      <Step title="Last opp skissen">
        Last opp en av de to skissene nedenfor til din Arduino.

        * **Enkel kontroll:** Den raskeste måten å komme i gang på, men krever ny flashing av fastvaren for å justere FPS.
        * **Seriell kontroll:** Lar deg justere frekvens og driftssyklus i sanntid uten å reflashe (innstillinger nullstilles hvis enheten mister strøm).

        <Tabs>
          <Tab title="Enkel kontroll">
            ```cpp theme={null}
            #include <PWM.h>

            // Pin configuration
            int pin = 9;       // Pin
            int value = 127;   // Initial value for the PWM duty cycle

            // SET FREQUENCY HERE
            float frequency = 60; // Initial frequency in Hz

            void setup()
            {
                // Initialize all timers except for timer0 to save timekeeping tasks
                InitTimersSafe();

                // Set the initial PWM frequency and duty cycle
                if (SetPinFrequencySafe(pin, frequency))
                {
                    pwmWrite(pin, value);
                    Serial.println("PWM frequency and initial duty cycle set.");
                }
                else
                {
                    Serial.println("Failed to set frequency.");
                }
            }
            ```
          </Tab>

          <Tab title="Seriekommandoer">
            ```cpp theme={null}
            #include <PWM.h>

            // Pin configuration
            int pin = 9;          // Pin
            int value = 127;      // Initial value for the PWM duty cycle
            float frequency = 60; // Initial frequency in Hz

            void setup()
            {
                Serial.begin(9600);

                // Initialize all timers except for timer0 to save timekeeping tasks
                InitTimersSafe();

                // Set the initial PWM frequency and duty cycle
                if (SetPinFrequencySafe(pin, frequency))
                {
                    pwmWrite(pin, value);
                    Serial.println("PWM frequency and initial duty cycle set.");
                }
                else
                {
                    Serial.println("Failed to set frequency.");
                }
            }

            void loop()
            {
                if (Serial.available())
                {
                    // Read frequency and duty cycle values over Serial
                    String inputString = Serial.readStringUntil('\n'); 
                    inputString.trim();                                
                    int freqDutySplitIndex = inputString.indexOf(',');

                    if (freqDutySplitIndex != -1)
                    {
                        String freqStr = inputString.substring(0, freqDutySplitIndex);  
                        String dutyStr = inputString.substring(freqDutySplitIndex + 1); 

                        // Parse floats
                        float newFrequency = freqStr.toFloat();
                        int newDutyCycle = dutyStr.toInt();

                        // Validate frequency range
                        if (newFrequency >= 1 && newFrequency <= 2000000)
                        {
                            // Set the PWM frequency and apply duty cycle
                            if (SetPinFrequencySafe(pin, newFrequency))
                            {
                                value = map(constrain(newDutyCycle, 0, 100), 0, 100, 0, 255);
                                pwmWrite(pin, value);
                                Serial.print("Set frequency to: ");
                                Serial.print(newFrequency);
                                Serial.print(" Hz, duty cycle to: ");
                                Serial.print(newDutyCycle);
                                Serial.println("%");
                            }
                            else
                            {
                                Serial.println("Failed to set new frequency.");
                            }
                        }
                        else
                        {
                            Serial.println("Invalid frequency value.");
                        }
                    }
                    else
                    {
                        Serial.println("Invalid input format. Use frequency,dutycycle (e.g., 60,50).");
                    }
                }
            }
            ```

            Denne koden lar deg endre PWM-signalet i sanntid. Åpne den serielle monitoren på `9600` baud og send kommandoer i formatet `{FREKVENS},{DRIFTSSYKLUS}` (f.eks. `60,50` for 60 Hz med 50 % driftssyklus).
          </Tab>
        </Tabs>
      </Step>
    </Steps>
  </Tab>
</Tabs>

***

## Python-bibliotek for synkronisert video (Linux)

I tillegg til vår kommende SDK tilbyr vi for øyeblikket en enkel Python-prosess for å hente synkroniserte bilder fra dine kameraoppsett. *(Merk: Dette kan bli faset ut til fordel for den fullt utrustede SDK-en i fremtiden.)*

<Card title="Python-bibliotek for synkronisert video" icon="github" href="https://github.com/DeepWaterExploration/synchronized_camera_python">
  Følg vår GitHub-veiledning for å installere og bruke vårt egendefinerte Python-bibliotek for Linux.
</Card>

***

## Synkronisert sammensydd video

Dette vil gå gjennom bruk av GStreamer for å synkronisere og sette sammen to videostrømmer.
Deretter opprette en virtuell enhet som kan brukes i andre programmer.

<Tabs>
  <Tab title="Linux">
    <Steps>
      <Step title="Installer nødvendige pakker">
        Installer de nødvendige avhengighetene med følgende kommando:

        ```bash theme={null}
        sudo apt install -y libx264-dev libjpeg-dev \
        libglib2.0-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
        gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
        gstreamer1.0-plugins-bad gstreamer1.0-libav libgstreamer-plugins-bad1.0-dev \
        gstreamer1.0-plugins-ugly gstreamer1.0-gl \
        v4l-utils
        ```
      </Step>

      <Step title="List opp gjeldende kameraenheter">
        Kjør følgende kommando for å finne dine tilkoblede kameraer:

        ```bash theme={null}
        v4l2-ctl --list-devices
        ```

        **Eksempel på utdata:**

        ```text theme={null}
        stellarHD Leader: stellarHD Lea (usb-0000:00:14.0-8.3):
            /dev/video0
            /dev/video1
            /dev/media0

        stellarHD Follower: stellarHD F (usb-0000:00:14.0-8.4):
            /dev/video2
            /dev/video3
            /dev/media1
        ```
      </Step>

      <Step title="Opprett en virtuell enhet">
        Identifiser enhets-ID-ene til de to kameraene du vil bruke, og velg deretter et enhets-ID-nummer som **ikke** er oppført.

        I dette eksempelet vil vi bruke `9` (siden det er ubrukt ovenfor) for å opprette en virtuell enhet kalt `stellarHD_stitched`. Oppdater `9` i kommandoen nedenfor for å matche den ubrukte ID-en du har valgt:

        ```bash theme={null}
        sudo modprobe v4l2loopback video_nr=9 \
        card_label=stellarHD_stitched exclusive_caps=1
        ```
      </Step>

      <Step title="Start GStreamer-pipelinen">
        Start pipelinen for å opprette den sammensydde videoen og send strømmen til den nye virtuelle enheten:

        ```bash theme={null}
        gst-launch-1.0 -v \
        compositor name=mix \
            sink_0::xpos=0    sink_0::ypos=0   sink_0::alpha=1 \
            sink_1::xpos=1600 sink_1::ypos=0   sink_1::alpha=1 \
        ! jpegenc ! jpegdec ! videoconvert ! v4l2sink device=/dev/video9 \
        v4l2src device=/dev/video0 ! image/jpeg,width=1600,framerate=60/1 ! jpegdec ! videorate ! mix.sink_0 \
        v4l2src device=/dev/video2 ! image/jpeg,width=1600,framerate=60/1 ! jpegdec ! videorate ! mix.sink_1
        ```

        <Note>
          Du må la denne kommandoen kjøre mens du bruker de synkroniserte, sammensydde videoene. Du kan endre denne kommandoen for å legge til flere kameraer, endre oppløsninger/bildefrekvenser eller endre oppsettet.
        </Note>
      </Step>

      <Step title="Bruk den virtuelle enheten i OpenCV">
        <Card title="OpenCV-startkode" icon="github" href="https://github.com/DeepwaterExploration/opencv-guides">
          Følg eksempelkoden vår for å bruke `/dev/video9` i OpenCV.
        </Card>
      </Step>

      <Step title="Fjern loopback-enheten">
        For å fjerne loopback-enheten på en trygg måte kan du enten starte datamaskinen på nytt eller kjøre følgende sekvens av kommandoer:

        **1. Identifiser programmer som for øyeblikket bruker loopback-enheten:**

        ```bash theme={null}
        sudo lsof /dev/video*
        ```

        **2. Avslutt prosessene ved hjelp av PID-numrene (Process ID):**

        ```bash theme={null}
        sudo kill <INSERT_PID_NUMBER>
        ```

        **3. Fjern loopback-enheten:**

        ```bash theme={null}
        sudo modprobe -r v4l2loopback
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>
