Secrets File Setup for Adafruit IO
If you don't have a secrets.py file in your CIRCUITPY drive yet, create one and add the information about your wifi connection.
Then, add the following code to your secrets.py file, replacing _your_adafruit_io_username
with your Adafruit IO username.
Then, replace _your_big_huge_super_long_aio_key_
with your Adafruit IO Active Key.
secrets = { 'ssid' : '_your_wifi_ssid_', 'password' : '_your_wifi_password_', 'aio_username' : '_your_adafruit_io_username_', 'aio_key' : '_your_big_huge_super_long_aio_key_', }
Make sure you save this file before proceeding as secrets.py in the root directory of your board CIRCUITPY drive.
Upload the code
Click "Download Project Bundle" below and unzip it on your Espressif Kaluga's CIRCUITPY drive. It will automatically start the code and upload a 640x480 JPEG to Adafruit IO every 3 seconds or so. If you run into trouble, open up the REPL to look for clues. Carefully double-check your WIFI and Adafruit IO login information, and that you properly created & configured the Adafruit IO Feed and Dashboard.

# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # SPDX-FileCopyrightText: Copyright (c) 2021 Jeff Epler for Adafruit Industries # # SPDX-License-Identifier: Unlicense """ The Kaluga development kit comes in two versions (v1.2 and v1.3); this demo is tested on v1.3. The audio board must be mounted between the Kaluga and the LCD, it provides the I2C pull-ups(!) This example requires that your WIFI and Adafruit IO credentials be configured in CIRCUITPY/secrets.py, and that you have created a feed called "image" with history disabled. The maximum image size is 100kB after base64 encoding, or about 65kB before base64 encoding. In practice, "SVGA" (800x600) images are typically around 40kB even though the "capture_buffer_size" (theoretical maximum size) is (width*height/5) bytes or 96kB. """ import binascii import ssl import time from secrets import secrets # pylint: disable=no-name-in-module import board import busio import wifi import socketpool import adafruit_minimqtt.adafruit_minimqtt as MQTT from adafruit_io.adafruit_io import IO_MQTT import adafruit_ov2640 feed_name = "image" print("Connecting to WIFI") wifi.radio.connect(secrets["ssid"], secrets["password"]) pool = socketpool.SocketPool(wifi.radio) print("Connecting to Adafruit IO") mqtt_client = MQTT.MQTT( broker="io.adafruit.com", username=secrets["aio_username"], password=secrets["aio_key"], socket_pool=pool, ssl_context=ssl.create_default_context(), ) mqtt_client.connect() io = IO_MQTT(mqtt_client) bus = busio.I2C(scl=board.CAMERA_SIOC, sda=board.CAMERA_SIOD) cam = adafruit_ov2640.OV2640( bus, data_pins=board.CAMERA_DATA, clock=board.CAMERA_PCLK, vsync=board.CAMERA_VSYNC, href=board.CAMERA_HREF, mclk=board.CAMERA_XCLK, mclk_frequency=20_000_000, size=adafruit_ov2640.OV2640_SIZE_QVGA, ) cam.flip_x = False cam.flip_y = False cam.test_pattern = False cam.size = adafruit_ov2640.OV2640_SIZE_SVGA cam.colorspace = adafruit_ov2640.OV2640_COLOR_JPEG jpeg_buffer = bytearray(cam.capture_buffer_size) while True: jpeg = cam.capture(jpeg_buffer) print(f"Captured {len(jpeg)} bytes of jpeg data") # b2a_base64() appends a trailing newline, which IO does not like encoded_data = binascii.b2a_base64(jpeg).strip() print(f"Expanded to {len(encoded_data)} for IO upload") io.publish("image", encoded_data) print("Waiting 3s") time.sleep(3)
Watch the camera feed
Just open up the Dashboard on Adafruit IO. The image in your browser will update shortly after each new image is uploaded from the ESP32-S2.
Take it Further
Here are some improvements and changes you might want to make to the code:
- WiFi camera: Add a button to take a photo, and an LCD to act as a viewfinder.
- Add a button to the Adafruit IO Dashboard that signals the camera to upload a fresh photo
- Video Doorbell: Add a button to take a photo, and send you a notification on your phone (requires an IFTTT account)
- Use a PC or Raspberry Pi to download & analyze the images