Simple test

Ensure your device works with this simple test.

examples/camera/code.py
  1# SPDX-FileCopyrightText: 2023 Jeff Epler for Adafruit Industries
  2# SPDX-FileCopyrightText: 2023 Limor Fried for Adafruit Industries
  3#
  4# SPDX-License-Identifier: Unlicense
  5
  6import time
  7import bitmaptools
  8import displayio
  9import gifio
 10import ulab.numpy as np
 11
 12import adafruit_pycamera
 13
 14pycam = adafruit_pycamera.PyCamera()
 15# pycam.live_preview_mode()
 16
 17settings = (
 18    None,
 19    "resolution",
 20    "effect",
 21    "mode",
 22    "led_level",
 23    "led_color",
 24    "timelapse_rate",
 25)
 26curr_setting = 0
 27
 28print("Starting!")
 29# pycam.tone(200, 0.1)
 30last_frame = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535)
 31onionskin = displayio.Bitmap(pycam.camera.width, pycam.camera.height, 65535)
 32timelapse_remaining = None
 33timelapse_timestamp = None
 34
 35while True:
 36    if pycam.mode_text == "STOP" and pycam.stop_motion_frame != 0:
 37        # alpha blend
 38        new_frame = pycam.continuous_capture()
 39        bitmaptools.alphablend(
 40            onionskin, last_frame, new_frame, displayio.Colorspace.RGB565_SWAPPED
 41        )
 42        pycam.blit(onionskin)
 43    elif pycam.mode_text == "GBOY":
 44        bitmaptools.dither(
 45            last_frame, pycam.continuous_capture(), displayio.Colorspace.RGB565_SWAPPED
 46        )
 47        pycam.blit(last_frame)
 48    elif pycam.mode_text == "LAPS":
 49        if timelapse_remaining is None:
 50            pycam.timelapsestatus_label.text = "STOP"
 51        else:
 52            timelapse_remaining = timelapse_timestamp - time.time()
 53            pycam.timelapsestatus_label.text = f"{timelapse_remaining}s /    "
 54        # Manually updating the label text a second time ensures that the label
 55        # is re-painted over the blitted preview.
 56        pycam.timelapse_rate_label.text = pycam.timelapse_rate_label.text
 57        pycam.timelapse_submode_label.text = pycam.timelapse_submode_label.text
 58
 59        # only in high power mode do we continuously preview
 60        if (timelapse_remaining is None) or (
 61            pycam.timelapse_submode_label.text == "HiPwr"
 62        ):
 63            pycam.blit(pycam.continuous_capture())
 64        if pycam.timelapse_submode_label.text == "LowPwr" and (
 65            timelapse_remaining is not None
 66        ):
 67            pycam.display.brightness = 0.05
 68        else:
 69            pycam.display.brightness = 1
 70        pycam.display.refresh()
 71
 72        if timelapse_remaining is not None and timelapse_remaining <= 0:
 73            # no matter what, show what was just on the camera
 74            pycam.blit(pycam.continuous_capture())
 75            # pycam.tone(200, 0.1) # uncomment to add a beep when a photo is taken
 76            try:
 77                pycam.display_message("Snap!", color=0x0000FF)
 78                pycam.capture_jpeg()
 79            except TypeError as e:
 80                pycam.display_message("Failed", color=0xFF0000)
 81                time.sleep(0.5)
 82            except RuntimeError as e:
 83                pycam.display_message("Error\nNo SD Card", color=0xFF0000)
 84                time.sleep(0.5)
 85            pycam.live_preview_mode()
 86            pycam.display.refresh()
 87            pycam.blit(pycam.continuous_capture())
 88            timelapse_timestamp = (
 89                time.time() + pycam.timelapse_rates[pycam.timelapse_rate] + 1
 90            )
 91    else:
 92        pycam.blit(pycam.continuous_capture())
 93    # print("\t\t", capture_time, blit_time)
 94
 95    pycam.keys_debounce()
 96    # test shutter button
 97    if pycam.shutter.long_press:
 98        print("FOCUS")
 99        print(pycam.autofocus_status)
100        pycam.autofocus()
101        print(pycam.autofocus_status)
102    if pycam.shutter.short_count:
103        print("Shutter released")
104        if pycam.mode_text == "STOP":
105            pycam.capture_into_bitmap(last_frame)
106            pycam.stop_motion_frame += 1
107            try:
108                pycam.display_message("Snap!", color=0x0000FF)
109                pycam.capture_jpeg()
110            except TypeError as e:
111                pycam.display_message("Failed", color=0xFF0000)
112                time.sleep(0.5)
113            except RuntimeError as e:
114                pycam.display_message("Error\nNo SD Card", color=0xFF0000)
115                time.sleep(0.5)
116            pycam.live_preview_mode()
117
118        if pycam.mode_text == "GBOY":
119            try:
120                f = pycam.open_next_image("gif")
121            except RuntimeError as e:
122                pycam.display_message("Error\nNo SD Card", color=0xFF0000)
123                time.sleep(0.5)
124                continue
125
126            with gifio.GifWriter(
127                f,
128                pycam.camera.width,
129                pycam.camera.height,
130                displayio.Colorspace.RGB565_SWAPPED,
131                dither=True,
132            ) as g:
133                g.add_frame(last_frame, 1)
134
135        if pycam.mode_text == "GIF":
136            try:
137                f = pycam.open_next_image("gif")
138            except RuntimeError as e:
139                pycam.display_message("Error\nNo SD Card", color=0xFF0000)
140                time.sleep(0.5)
141                continue
142            i = 0
143            ft = []
144            pycam._mode_label.text = "RECORDING"  # pylint: disable=protected-access
145
146            pycam.display.refresh()
147            with gifio.GifWriter(
148                f,
149                pycam.camera.width,
150                pycam.camera.height,
151                displayio.Colorspace.RGB565_SWAPPED,
152                dither=True,
153            ) as g:
154                t00 = t0 = time.monotonic()
155                while (i < 15) or not pycam.shutter_button.value:
156                    i += 1
157                    _gifframe = pycam.continuous_capture()
158                    g.add_frame(_gifframe, 0.12)
159                    pycam.blit(_gifframe)
160                    t1 = time.monotonic()
161                    ft.append(1 / (t1 - t0))
162                    print(end=".")
163                    t0 = t1
164            pycam._mode_label.text = "GIF"  # pylint: disable=protected-access
165            print(f"\nfinal size {f.tell()} for {i} frames")
166            print(f"average framerate {i/(t1-t00)}fps")
167            print(f"best {max(ft)} worst {min(ft)} std. deviation {np.std(ft)}")
168            f.close()
169            pycam.display.refresh()
170
171        if pycam.mode_text == "JPEG":
172            pycam.tone(200, 0.1)
173            try:
174                pycam.display_message("Snap!", color=0x0000FF)
175                pycam.capture_jpeg()
176                pycam.live_preview_mode()
177            except TypeError as e:
178                pycam.display_message("Failed", color=0xFF0000)
179                time.sleep(0.5)
180                pycam.live_preview_mode()
181            except RuntimeError as e:
182                pycam.display_message("Error\nNo SD Card", color=0xFF0000)
183                time.sleep(0.5)
184
185    if pycam.card_detect.fell:
186        print("SD card removed")
187        pycam.unmount_sd_card()
188        pycam.display.refresh()
189    if pycam.card_detect.rose:
190        print("SD card inserted")
191        pycam.display_message("Mounting\nSD Card", color=0xFFFFFF)
192        for _ in range(3):
193            try:
194                print("Mounting card")
195                pycam.mount_sd_card()
196                print("Success!")
197                break
198            except OSError as e:
199                print("Retrying!", e)
200                time.sleep(0.5)
201        else:
202            pycam.display_message("SD Card\nFailed!", color=0xFF0000)
203            time.sleep(0.5)
204        pycam.display.refresh()
205
206    if pycam.up.fell:
207        print("UP")
208        key = settings[curr_setting]
209        if key:
210            print("getting", key, getattr(pycam, key))
211            setattr(pycam, key, getattr(pycam, key) + 1)
212    if pycam.down.fell:
213        print("DN")
214        key = settings[curr_setting]
215        if key:
216            setattr(pycam, key, getattr(pycam, key) - 1)
217    if pycam.right.fell:
218        print("RT")
219        curr_setting = (curr_setting + 1) % len(settings)
220        if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelapse_rate":
221            curr_setting = (curr_setting + 1) % len(settings)
222        print(settings[curr_setting])
223        # new_res = min(len(pycam.resolutions)-1, pycam.get_resolution()+1)
224        # pycam.set_resolution(pycam.resolutions[new_res])
225        pycam.select_setting(settings[curr_setting])
226    if pycam.left.fell:
227        print("LF")
228        curr_setting = (curr_setting - 1 + len(settings)) % len(settings)
229        if pycam.mode_text != "LAPS" and settings[curr_setting] == "timelaps_rate":
230            curr_setting = (curr_setting + 1) % len(settings)
231        print(settings[curr_setting])
232        pycam.select_setting(settings[curr_setting])
233        # new_res = max(1, pycam.get_resolution()-1)
234        # pycam.set_resolution(pycam.resolutions[new_res])
235    if pycam.select.fell:
236        print("SEL")
237        if pycam.mode_text == "LAPS":
238            pycam.timelapse_submode += 1
239            pycam.display.refresh()
240    if pycam.ok.fell:
241        print("OK")
242        if pycam.mode_text == "LAPS":
243            if timelapse_remaining is None:  # stopped
244                print("Starting timelapse")
245                timelapse_remaining = pycam.timelapse_rates[pycam.timelapse_rate]
246                timelapse_timestamp = time.time() + timelapse_remaining + 1
247                # dont let the camera take over auto-settings
248                saved_settings = pycam.get_camera_autosettings()
249                # print(f"Current exposure {saved_settings=}")
250                pycam.set_camera_exposure(saved_settings["exposure"])
251                pycam.set_camera_gain(saved_settings["gain"])
252                pycam.set_camera_wb(saved_settings["wb"])
253            else:  # is running, turn off
254                print("Stopping timelapse")
255
256                timelapse_remaining = None
257                pycam.camera.exposure_ctrl = True
258                pycam.set_camera_gain(None)  # go back to autogain
259                pycam.set_camera_wb(None)  # go back to autobalance
260                pycam.set_camera_exposure(None)  # go back to auto shutter