Compare commits
No commits in common. "0334c851f80af07ef99b75c10cdd84e3e03e4499" and "423690d076da30c0ea9d30586b9e1dc8cd5ed5a3" have entirely different histories.
0334c851f8
...
423690d076
|
|
@ -1,13 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "esp-camera-rs"
|
name = "esp-camera-rs"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
esp-idf-hal = "0.45.2"
|
esp-idf-hal = "0.43.1"
|
||||||
esp-idf-sys = "0.36.1"
|
esp-idf-sys = "0.34.1"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
esp-idf-sys = {git = "https://github.com/esp-rs/esp-idf-sys", branch = "master"}
|
esp-idf-sys = {git = "https://github.com/esp-rs/esp-idf-sys", branch = "master"}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
dependencies:
|
|
||||||
idf:
|
|
||||||
source:
|
|
||||||
type: idf
|
|
||||||
version: 5.4.3
|
|
||||||
manifest_hash: 06a76c1bdea0ee9953dbe66dc1eb5ea4b157dbc5999962e4b65153dbefdb7f21
|
|
||||||
target: esp32
|
|
||||||
version: 2.0.0
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 7aa37d4f22503fdac9ccd449e4678c4894c40055
|
Subproject commit e689c3b082985ee7b90198be32d330ce51ac5367
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
[build]
|
|
||||||
target = "xtensa-esp32-espidf"
|
|
||||||
|
|
||||||
[target.xtensa-esp32-espidf]
|
|
||||||
linker = "ldproxy"
|
|
||||||
# runner = "espflash --monitor" # Select this runner for espflash v1.x.x
|
|
||||||
runner = "espflash flash --monitor" # Select this runner for espflash v2.x.x
|
|
||||||
rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
|
|
||||||
|
|
||||||
[unstable]
|
|
||||||
build-std = ["std", "panic_abort"]
|
|
||||||
|
|
||||||
[env]
|
|
||||||
MCU="esp32"
|
|
||||||
# Note: this variable is not used by the pio builder (`cargo build --features pio`)
|
|
||||||
ESP_IDF_VERSION = "v5.1.3"
|
|
||||||
|
|
||||||
4
examples/camera-example/.gitignore
vendored
4
examples/camera-example/.gitignore
vendored
|
|
@ -1,4 +0,0 @@
|
||||||
.embuild/
|
|
||||||
target/
|
|
||||||
components_esp32.lock
|
|
||||||
Cargo.lock
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "camera-example"
|
|
||||||
version = "0.1.2"
|
|
||||||
authors = ["Mathias Pius <contact@pius.io>"]
|
|
||||||
edition = "2021"
|
|
||||||
rust-version = "1.71"
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
opt-level = "s"
|
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
debug = true # Symbols are nice and they don't increase the size on Flash
|
|
||||||
opt-level = "z"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
esp-camera-rs = { path = "../../", version = "*" }
|
|
||||||
|
|
||||||
log = { version = "0.4", default-features = false }
|
|
||||||
anyhow = "1.0.100"
|
|
||||||
esp-idf-svc = { version = "0.51.0", default-features = false, features = [
|
|
||||||
"binstart",
|
|
||||||
"std",
|
|
||||||
] }
|
|
||||||
esp-idf-sys = { version = "0.36.1" }
|
|
||||||
[build-dependencies]
|
|
||||||
embuild = "0.33.1"
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
This example assumes you have already set up all the tools necessary to compile Rust for ESP32.
|
|
||||||
|
|
||||||
When run using `cargo run`, it will compile and flash the program to an ESP32-CAM mounted on an
|
|
||||||
ESP32-CAM-MB board connected via USB to the host machine.
|
|
||||||
|
|
||||||
The program will:
|
|
||||||
|
|
||||||
1. Initialize the onboard OV2640 camera as well as the bright white LED (flash).
|
|
||||||
2. Turn on the flash.
|
|
||||||
3. Take a jpeg-encoded picture using the camera.
|
|
||||||
4. Print information about the image: width, height and size in bytes.
|
|
||||||
5. Enter deep sleep for 60 seconds, after which the device starts the process.
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
embuild::espidf::sysenv::output();
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[toolchain]
|
|
||||||
channel = "esp"
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
# I think larger stack size is required for rust? Not sure where I got this info
|
|
||||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000
|
|
||||||
|
|
||||||
# Enable PSRAM, which allows us to store larger images
|
|
||||||
CONFIG_ESP32_SPIRAM_SUPPORT=y
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
use esp_idf_svc::hal::{gpio::PinDriver, peripherals::Peripherals};
|
|
||||||
use esp_idf_sys::esp_deep_sleep;
|
|
||||||
use log::info;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
|
||||||
// It is necessary to call this function once. Otherwise some patches to the runtime
|
|
||||||
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
|
||||||
esp_idf_svc::sys::link_patches();
|
|
||||||
|
|
||||||
// Bind the log crate to the ESP Logging facilities
|
|
||||||
esp_idf_svc::log::EspLogger::initialize_default();
|
|
||||||
|
|
||||||
info!("initializing camera and flash");
|
|
||||||
let peripherals = Peripherals::take().unwrap();
|
|
||||||
|
|
||||||
// ESP32-CAM has an onboard Flash LED addressed at GPIO-4
|
|
||||||
let mut flash = PinDriver::output(peripherals.pins.gpio4)?;
|
|
||||||
flash.set_low()?;
|
|
||||||
|
|
||||||
// Initialize the camera
|
|
||||||
let camera = esp_camera_rs::Camera::new(
|
|
||||||
peripherals.pins.gpio32,
|
|
||||||
peripherals.pins.gpio0,
|
|
||||||
peripherals.pins.gpio5,
|
|
||||||
peripherals.pins.gpio18,
|
|
||||||
peripherals.pins.gpio19,
|
|
||||||
peripherals.pins.gpio21,
|
|
||||||
peripherals.pins.gpio36,
|
|
||||||
peripherals.pins.gpio39,
|
|
||||||
peripherals.pins.gpio34,
|
|
||||||
peripherals.pins.gpio35,
|
|
||||||
peripherals.pins.gpio25,
|
|
||||||
peripherals.pins.gpio23,
|
|
||||||
peripherals.pins.gpio22,
|
|
||||||
peripherals.pins.gpio26,
|
|
||||||
peripherals.pins.gpio27,
|
|
||||||
esp_idf_sys::camera::pixformat_t_PIXFORMAT_JPEG,
|
|
||||||
esp_idf_sys::camera::framesize_t_FRAMESIZE_UXGA,
|
|
||||||
esp_idf_sys::camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
info!("initialization complete!");
|
|
||||||
|
|
||||||
// Turn on the flash and take a picture.
|
|
||||||
// You probably want to keep it on for a while and adjust
|
|
||||||
// the camera exposure to get a good image, but this is
|
|
||||||
// mainly here to show that the program is working.
|
|
||||||
info!("taking a picture");
|
|
||||||
flash.set_high()?;
|
|
||||||
let framebuffer = camera.get_framebuffer();
|
|
||||||
flash.set_low()?;
|
|
||||||
|
|
||||||
if let Some(framebuffer) = framebuffer {
|
|
||||||
info!(
|
|
||||||
"took picture: {width}x{height} {size} bytes",
|
|
||||||
width = framebuffer.width(),
|
|
||||||
height = framebuffer.height(),
|
|
||||||
size = framebuffer.data().len(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// TODO: Do something with the framebuffer.
|
|
||||||
// the JPEG-encoded byte data is in framebuffer.data()
|
|
||||||
// so you can just dump this to a file or send it over
|
|
||||||
// the network as "image.jpeg" and it should work.
|
|
||||||
} else {
|
|
||||||
panic!("failed to take image");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Send the board into deep sleep. This will basically turn off everything
|
|
||||||
// and consume very little power, and then "reboot" the device, restarting
|
|
||||||
// the pin initialization and taking another picture.
|
|
||||||
let delay = Duration::from_secs(60);
|
|
||||||
info!("finished, entering deep sleep for {delay:#?}");
|
|
||||||
unsafe { esp_deep_sleep(delay.as_micros() as u64) }
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
[toolchain]
|
|
||||||
channel = "esp"
|
|
||||||
29
src/lib.rs
29
src/lib.rs
|
|
@ -83,13 +83,19 @@ impl<'a> CameraSensor<'a> {
|
||||||
esp!(unsafe { (*self.sensor).set_quality.unwrap()(self.sensor, quality) })
|
esp!(unsafe { (*self.sensor).set_quality.unwrap()(self.sensor, quality) })
|
||||||
}
|
}
|
||||||
pub fn set_colorbar(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_colorbar(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_colorbar.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_colorbar.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_whitebal(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_whitebal(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_whitebal.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_whitebal.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_gain_ctrl(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_gain_ctrl(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_gain_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_gain_ctrl.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_exposure_ctrl(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_exposure_ctrl(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe {
|
esp!(unsafe {
|
||||||
|
|
@ -97,7 +103,9 @@ impl<'a> CameraSensor<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn set_hmirror(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_hmirror(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_hmirror.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_hmirror.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_vflip(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_vflip(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_vflip.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe { (*self.sensor).set_vflip.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
||||||
|
|
@ -106,7 +114,9 @@ impl<'a> CameraSensor<'a> {
|
||||||
esp!(unsafe { (*self.sensor).set_aec2.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe { (*self.sensor).set_aec2.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
||||||
}
|
}
|
||||||
pub fn set_awb_gain(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_awb_gain(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_awb_gain.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_awb_gain.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_agc_gain(&self, gain: i32) -> Result<(), EspError> {
|
pub fn set_agc_gain(&self, gain: i32) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_agc_gain.unwrap()(self.sensor, gain) })
|
esp!(unsafe { (*self.sensor).set_agc_gain.unwrap()(self.sensor, gain) })
|
||||||
|
|
@ -133,7 +143,9 @@ impl<'a> CameraSensor<'a> {
|
||||||
esp!(unsafe { (*self.sensor).set_wpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe { (*self.sensor).set_wpc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
||||||
}
|
}
|
||||||
pub fn set_raw_gma(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_raw_gma(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_raw_gma.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe {
|
||||||
|
(*self.sensor).set_raw_gma.unwrap()(self.sensor, if enable { 1 } else { 0 })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
pub fn set_lenc(&self, enable: bool) -> Result<(), EspError> {
|
pub fn set_lenc(&self, enable: bool) -> Result<(), EspError> {
|
||||||
esp!(unsafe { (*self.sensor).set_lenc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
esp!(unsafe { (*self.sensor).set_lenc.unwrap()(self.sensor, if enable { 1 } else { 0 }) })
|
||||||
|
|
@ -230,7 +242,6 @@ impl<'a> Camera<'a> {
|
||||||
pin_scl: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
|
pin_scl: impl Peripheral<P = impl InputPin + OutputPin> + 'a,
|
||||||
pixel_format: camera::pixformat_t,
|
pixel_format: camera::pixformat_t,
|
||||||
frame_size: camera::framesize_t,
|
frame_size: camera::framesize_t,
|
||||||
fb_location: camera::camera_fb_location_t,
|
|
||||||
) -> Result<Self, esp_idf_sys::EspError> {
|
) -> Result<Self, esp_idf_sys::EspError> {
|
||||||
esp_idf_hal::into_ref!(
|
esp_idf_hal::into_ref!(
|
||||||
pin_pwdn, pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7,
|
pin_pwdn, pin_xclk, pin_d0, pin_d1, pin_d2, pin_d3, pin_d4, pin_d5, pin_d6, pin_d7,
|
||||||
|
|
@ -264,7 +275,7 @@ impl<'a> Camera<'a> {
|
||||||
fb_count: 1,
|
fb_count: 1,
|
||||||
grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY,
|
grab_mode: camera::camera_grab_mode_t_CAMERA_GRAB_WHEN_EMPTY,
|
||||||
|
|
||||||
fb_location,
|
fb_location: camera::camera_fb_location_t_CAMERA_FB_IN_PSRAM,
|
||||||
|
|
||||||
__bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 {
|
__bindgen_anon_1: camera::camera_config_t__bindgen_ty_1 {
|
||||||
pin_sccb_sda: pin_sda.pin(),
|
pin_sccb_sda: pin_sda.pin(),
|
||||||
|
|
@ -280,7 +291,7 @@ impl<'a> Camera<'a> {
|
||||||
Ok(Self { _p: PhantomData })
|
Ok(Self { _p: PhantomData })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_framebuffer(&self) -> Option<FrameBuffer<'_>> {
|
pub fn get_framebuffer(&self) -> Option<FrameBuffer> {
|
||||||
let fb = unsafe { camera::esp_camera_fb_get() };
|
let fb = unsafe { camera::esp_camera_fb_get() };
|
||||||
if fb.is_null() {
|
if fb.is_null() {
|
||||||
//unsafe { camera::esp_camera_fb_return(fb); }
|
//unsafe { camera::esp_camera_fb_return(fb); }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue