Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ If you want to play arround with AI, take a look at the [micropython binding for

## Content

- [Precompiled firmware (the easy way)](#Precompiled-firmware-the-easy-way)
- [Precompiled firmware (the easy way)](#precompiled-firmware-the-easy-way)
- [Using the API](#using-the-api)
- [Importing the camera module](#importing-the-camera-module)
- [Creating a camera object](#creating-a-camera-object)
Expand All @@ -22,7 +22,7 @@ If you want to play arround with AI, take a look at the [micropython binding for
- [Camera reconfiguration](#camera-reconfiguration)
- [Freeing the buffer](#freeing-the-buffer)
- [Is a frame available](#is-frame-available)
- [Additional methods](#additional-methods)
- [Additional methods and examples](#additional-methods-and-examples)
- [I2C Integration](#i2c-integration)
- [Additional information](#additional-information)
- [Build your custom firmware](#build-your-custom-firmware)
Expand Down Expand Up @@ -130,10 +130,14 @@ The following keyword arguments have default values:

### Initializing the camera

The camera initializes when constructing the camera object per default. If you set init=False during construction, you need to call the init method manually:

```python
cam.init()
```

Note that most of the camera seeting can only be set or aquired after initialization.

### Capture image

The general way of capturing an image is calling the `capture` method:
Expand Down Expand Up @@ -192,14 +196,14 @@ This gives you the possibility of creating an asynchronous application without u
Here are just a few examples:

```python
cam.set_quality(90) # The quality goes from 0% to 100%, meaning 100% is the highest but has probably no compression
camera.get_brightness()
camera.set_vflip(True) #Enable vertical flip
cam.quality = 90 # The quality goes from 0% to 100%, meaning 100% is the highest but has probably no compression
print("cam.brightness =", cam.brightness)
camera.vflip = True #Enable vertical flip
```

See autocompletions in Thonny in order to see the list of methods.
If you want more insights in the methods and what they actually do, you can find a very good documentation [here](https://docs.circuitpython.org/en/latest/shared-bindings/espcamera/index.html).
Note that each method requires a "get_" or "set_" prefix, depending on the desired action.
If you want more insights in the methods and what they actually do, you can find a very good documentation [in circuitpython](https://docs.circuitpython.org/en/latest/shared-bindings/espcamera/index.html).
Note: "get_" and "set_" prefixed methods are deprecated and will be removed in a future release.

Take also a look in the examples folder.

Expand Down Expand Up @@ -233,7 +237,7 @@ print(f"I2C devices found: {devices}")
i2c.writeto(0x42, b'\x00\x01') # Write to another device

# Camera sensor communication works too
cam.set_saturation(1) # Uses the shared I2C bus
cam.saturation = 1 # Uses the shared I2C bus
```

#### Alternative: Camera Creates Its Own I2C (Default)
Expand Down Expand Up @@ -328,6 +332,7 @@ Example for Xiao sense:
#define MICROPY_CAMERA_GRAB_MODE (1) // 0=WHEN_EMPTY (might have old data, but less resources), 1=LATEST (best, but more resources)

```

#### Customize additional camera settings

If you want to customize additional camera setting or reduce the firmware size by removing support for unused camera sensors, then take a look at the kconfig file of the esp32-camera driver and specify these on the sdkconfig file of your board.
Expand Down Expand Up @@ -381,6 +386,7 @@ Using fb_count=2 theoretically can double the FPS (see JPEG with fb_count=2). Th
## Troubleshooting

You can find information on the following sites:

- [ESP-FAQ](https://docs.espressif.com/projects/esp-faq/en/latest/application-solution/camera-application.html)
- [ChatGPT](https://chatgpt.com/)
- [Issues in here](https://github.com/cnadler86/micropython-camera-API/issues?q=is%3Aissue)
Expand Down
2 changes: 1 addition & 1 deletion esp32-camera
57 changes: 51 additions & 6 deletions examples/CameraSettings.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,50 @@
<head>
<title>Micropython Camera Stream</title>
<style>
* {
box-sizing: border-box;
}
body {
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
height: 100vh;
min-height: 100vh;
margin: 0;
background-color: #f0f0f0;
}
.container {
display: flex;
flex-direction: row;
height: 100%;
width: 100%;
flex: 1;
}
.settings-container {
display: flex;
flex-direction: column;
padding: 20px;
padding: 15px;
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-top: 20px;
width: 300px;
overflow-y: auto;
}
.setting {
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}
.setting label {
font-size: 14px;
flex: 1;
}
.setting input[type="range"],
.setting select {
width: 100%;
}
.setting input[type="checkbox"] {
width: auto;
margin-left: 10px;
}
.hidden {
display: none;
Expand All @@ -37,18 +55,45 @@
display: flex;
justify-content: center;
align-items: center;
width: 100%;
flex: 1;
padding: 20px;
overflow: hidden;
}
img {
max-width: 100%;
max-height: 100%;
width: auto;
height: 100%;
height: auto;
}
.title-container {
width: 100%;
text-align: center;
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 10px;
}
.title-container h1 {
margin: 0;
font-size: 1.5em;
}
@media (max-width: 768px) {
.container {
flex-direction: column;
}
.settings-container {
width: 100%;
max-height: 40vh;
order: 2;
}
.video-container {
width: 100%;
min-height: 50vh;
padding: 10px;
order: 1;
}
.title-container h1 {
font-size: 1.2em;
}
}
</style>
<script>
Expand Down
30 changes: 17 additions & 13 deletions examples/CameraSettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
while not station.isconnected():
time.sleep(1)

print(f'Connected! IP: {station.ifconfig()[0]}. Open this IP in your browser')
print(f'Connected! IP: http://{station.ifconfig()[0]}. Open it in your browser')

try:
with open("CameraSettings.html", 'r') as file:
Expand Down Expand Up @@ -56,35 +56,39 @@ async def handle_client(reader, writer):
elif 'GET /set_' in request:
method_name = request.split('GET /set_')[1].split('?')[0]
value = int(request.split('value=')[1].split(' ')[0])
set_method = getattr(cam, f'set_{method_name}', None)
if callable(set_method):
try:
# Use property assignment instead of method call
setattr(cam, method_name, value)
print(f"setting {method_name} to {value}")
set_method(value)
response = 'HTTP/1.1 200 OK\r\n\r\n'
writer.write(response.encode())
await writer.drain()
else:
except (AttributeError, ValueError) as e:
# Fallback to reconfigure if property doesn't exist
try:
cam.reconfigure(**{method_name: value})
print(f"Camera reconfigured with {method_name}={value}")
print("This action restores all previous configuration!")
response = 'HTTP/1.1 200 OK\r\n\r\n'
except Exception as e:
print(f"Error with {method_name}: {e}")
writer.write(response.encode())
await writer.drain()
except Exception as e2:
print(f"Error setting {method_name}: {e2}")
response = 'HTTP/1.1 404 Not Found\r\n\r\n'
writer.write(response.encode())
await writer.drain()
writer.write(response.encode())
await writer.drain()

elif 'GET /get_' in request:
method_name = request.split('GET /get_')[1].split(' ')[0]
get_method = getattr(cam, f'get_{method_name}', None)
if callable(get_method):
value = get_method()
try:
# Use property access instead of method call
value = getattr(cam, method_name)
print(f"{method_name} is {value}")
response = f'HTTP/1.1 200 OK\r\n\r\n{value}'
writer.write(response.encode())
await writer.drain()
else:
except AttributeError as e:
print(f"Error getting {method_name}: {e}")
response = 'HTTP/1.1 404 Not Found\r\n\r\n'
writer.write(response.encode())
await writer.drain()
Expand Down
2 changes: 1 addition & 1 deletion manifest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Include the board's default manifest.
include("$(PORT_DIR)/boards/manifest.py")
# Add custom driver
module("src/acamera.py")
module("acamera.py", base_path="src")
2 changes: 0 additions & 2 deletions micropython.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ target_sources(usermod_mp_camera INTERFACE
idf_component_get_property(camera_dir esp32-camera COMPONENT_DIR)
target_include_directories(usermod_mp_camera INTERFACE
${camera_dir}/driver/include
${camera_dir}/driver/private_include
${camera_dir}/sensors/private_include
)

# # Set MP_CAMERA_DRIVER_VERSION if available
Expand Down
Loading