Hey guys, how can I put the OAK1 into IDLE or sleep mode, so it won't overuse the CPU while waiting 5 mins before taking another frame?

I used this approach:
1. Confiugre a pipeline (Create_pipeline())
2. go into a while loop up to total duration of 6 hours
2.1. capture()
2.2. time.sleep(5 mins)

But after a few times, I noticed that my PC experiences issues with identifying the hardware of the OAK1. Now it's constantly recognized but immediately disconnected from the PC. It's instable now. It's like this script fucked up the OAK1 camera? I dunno…

Is there some idle function in the camera, without having my PC disconnect from the camera over and over again?

    lerp
    The way I see it you have two options:

    • keep the script running
    • stop the pipeline in between each capture. 5 minutes is more than enough for the system work on on/off, especiall on USB devices. Don't use time.sleep() since it halts the frame readings and might interfere with the TCP connection.

    Thanks,
    Jaka

      jakaskerl Great input.
      I didn't know that time.sleep() might interfere with the connection.

      Here's my original script:

      import depthai as dai
      import time
      from datetime import datetime
      import cv2
      from utilities import create_session_directory
      
      # Function to create a pipeline
      def create_pipeline():
          pipeline = dai.Pipeline()
      
          cam_rgb = pipeline.createColorCamera()
          xout_rgb = pipeline.createXLinkOut()
      
          xout_rgb.setStreamName("rgb")
      
          cam_rgb.setBoardSocket(dai.CameraBoardSocket.CAM_A)
          cam_rgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_4_K)
          cam_rgb.setInterleaved(False)
          cam_rgb.setColorOrder(dai.ColorCameraProperties.ColorOrder.BGR)
      
          cam_rgb.initialControl.setAutoFocusMode(dai.CameraControl.AutoFocusMode.AUTO)
          cam_rgb.initialControl.setAutoExposureEnable()
          cam_rgb.initialControl.setAutoWhiteBalanceMode(dai.CameraControl.AutoWhiteBalanceMode.AUTO)
          cam_rgb.video.link(xout_rgb.input)
      
          return pipeline
      
      # Function to capture and save an image
      def capture_image(directory_path):
          pipeline = create_pipeline()
          with dai.Device(pipeline, maxUsbSpeed=dai.UsbSpeed.HIGH) as device:
              q_rgb = device.getOutputQueue(name="rgb", maxSize=4, blocking=False)
              timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
              for i in range(25):
                  q_rgb.get()
      
              in_rgb = q_rgb.get()
              frame = in_rgb.getCvFrame()
              
              # Get temperature readings
              temperature = device.getChipTemperature()
              # Save the frame
              filename = f"{directory_path}/{timestamp}.png"
              cv2.imwrite(filename, frame)
              print(f"Saved {filename} ------ Temperatures: CSS: {temperature.css:.2f}°C, MSS: {temperature.mss:.2f}°C, DSS: {temperature.dss:.2f}°C, Average: {temperature.average:.2f}°C")
      
      def main():
          total_duration = 5 * 60 * 60  # hour * minute * seconds
          capture_interval = 60*5 # 5 minutes
          start_time = time.time()
      
          directory_path = create_session_directory()   
          
          while (time.time() - start_time) < total_duration:
              capture_image(directory_path)
              time.sleep(capture_interval)
      
      if __name__ == "__main__":
          main()

      So if not using time.sleep(), how to create an efficient delay?

      thanks

        lerp
        If you keep the script running, you can use get and discard messages when not capturing them. Of course this would keep the bandwidth usage high at all times.

        Alternatively, you could use device.close() and device.startPipeline(pipeline) to manually stop/start the capture, then use external timer that is constantly running to only grab a frame when you want it. Outside of this, device is unbooted so no resources are used.

        Thanks,
        Jaka

        • lerp replied to this.

          jakaskerl
          Thanks,
          How do device.close() and device.startPipeline(pipeline) differ from:

          with dai.Device(pipeline, maxUsbSpeed=dai.UsbSpeed.HIGH) as device:

          Isn't it the same?
          I thought that with … as … : handles the entire thing of closing and starting the objects.

            lerp
            It's the same as the context manager. You can use that as well if you wish, just make sure you don't abruptly kill the process with SIGKILL since that doesn't call the destructor correctly iirc.

            Thanks,
            Jaka