### Build and Run Project Examples Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md These commands demonstrate how to build the Rust project in release mode and run basic examples. It also shows how to set environment variables to configure the sensor type. ```bash # Build the project car go build --release # Run a basic example car go run --release --example basic_read # Run with environment variables SENSOR_TYPE=dht22 cargo run --release ``` -------------------------------- ### Example: Reading Humidity Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Shows how to read humidity data from a DHT sensor. This example initializes a DHT sensor, performs a read operation, and then extracts the humidity percentage. ```rust use dht_mmap_rust::{Dht, DhtType}; let mut dht = Dht::new(DhtType::Dht11, 23).unwrap(); if let Ok(reading) = dht.read() { let humidity = reading.humidity(); println!("Current humidity: {:.0} %RH", humidity); } ``` -------------------------------- ### Example: Using Reading Traits (Copy, Debug, PartialEq) Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Illustrates the usage of `Copy`, `Debug`, and `PartialEq` traits implemented for the `Reading` struct. This example shows how to copy, print, and compare sensor readings. ```rust use dht_mmap_rust::{Dht, DhtType}; let mut dht = Dht::new(DhtType::Dht22, 17).unwrap(); if let Ok(reading1) = dht.read() { // Copy the reading to another variable let reading2 = reading1; // Print with Debug trait println!("Reading: {:?}", reading1); // Compare readings if reading1 == reading2 { println!("Readings are identical"); } println!("Temp: {:.1}°C, Humidity: {:.1}%RH", reading1.temperature(), reading1.humidity()); } ``` -------------------------------- ### Run as User (Requires Group Setup) Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md This command demonstrates running the project as a regular user. It assumes that the necessary group permissions (e.g., 'gpio' group) have been pre-configured. ```bash # Option 2: Run as user (requires group setup) car go run --release ``` -------------------------------- ### Run as root Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/errors.md Example command to run a Rust program with root privileges using sudo. ```Bash sudo cargo run ``` -------------------------------- ### Build Optimized Release Binary Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Use this command to produce an optimized binary for production environments. Ensure you have the Rust toolchain installed. ```bash cargo build --release ``` -------------------------------- ### Example: Reading Temperature Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Demonstrates how to initialize a DHT sensor, read its data, and extract the temperature value. This snippet shows basic usage of `Dht::read()` and `Reading::temperature()`. ```rust use dht_mmap_rust::{Dht, DhtType}; let mut dht = Dht::new(DhtType::Dht22, 17).unwrap(); if let Ok(reading) = dht.read() { let temp = reading.temperature(); println!("Current temperature: {:.1} °C", temp); } ``` -------------------------------- ### Example Usage of Reading Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/types.md Demonstrates how to read temperature and humidity from a `Reading` object and print the values. Ensure a successful read operation before accessing these methods. ```rust let reading = dht.read()?; let temp_celsius = reading.temperature(); let humidity_percent = reading.humidity(); println!("Temp: {:.1}°C, Humidity: {:.1}%", temp_celsius, humidity_percent); ``` -------------------------------- ### Example Error Handling for GpioOpenError Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/types.md Demonstrates how to handle GpioOpenError variants when initializing a DHT sensor. It provides specific error messages for file opening and memory mapping failures. ```rust match Dht::new(DhtType::Dht22, 17) { Ok(dht) => { /* sensor ready */ } Err(GpioOpenError::OpenGpioFileFailed(io_err)) => { eprintln!("Cannot open /dev/gpiomem: {}", io_err); eprintln!("Check permissions or verify you're on a Raspberry Pi"); } Err(GpioOpenError::CreateMmapError(io_err)) => { eprintln!("Memory mapping failed: {}", io_err); } } ``` -------------------------------- ### Initialize DHT and Validate Readings Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Initialize a DHT sensor and perform basic sanity checks on the temperature and humidity readings. This example is specific to DHT22 sensors. ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).expect("Init failed"); match dht.read() { Ok(reading) => { let temp = reading.temperature(); let humidity = reading.humidity(); // Sanity checks for DHT22 if temp < -40.0 || temp > 80.0 { eprintln!("Temperature out of range: {{:.1}}°C", temp); } else if humidity < 0.0 || humidity > 100.0 { eprintln!("Humidity out of range: {{:.1}}%RH", humidity); } else { println!("✓ Valid reading: {{:.1}}°C, {{:.1}}%RH", temp, humidity); } } Err(e) => eprintln!("Read failed: {{:?}}", e), } } ``` -------------------------------- ### Internal Example of HighThreadPriorityGuard Usage Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/high_thread_priority_guard.md An internal example demonstrating how HighThreadPriorityGuard is used to temporarily elevate thread priority within a specific scope. This ensures critical timing code runs without interruption. ```rust // This is internal to the library // Used automatically in Dht::read() use dht_mmap_rust::scoped_thread_priority::HighThreadPriorityGuard; fn internal_example() { { let _guard = HighThreadPriorityGuard::new(); // Thread runs at maximum SCHED_FIFO priority here println!("Running critical timing code"); } // Guard is dropped here, priority is restored println!("Back to normal priority"); } ``` -------------------------------- ### DHT Sensor Error Handling Example Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/types.md Demonstrates how to handle potential errors returned by the DHT sensor read operation using a match statement. This example covers specific error variants like ReadTimeoutEarly, ReadTimeoutData, and ChecksumMismatch. ```rust match dht.read() { Ok(reading) => { /* process */ } // Process successful reading Err(DhtError::ReadTimeoutEarly) => { eprintln!("Sensor not responding, check connection"); } Err(DhtError::ReadTimeoutData) => { eprintln!("Transmission interrupted, will retry"); } Err(DhtError::ChecksumMismatch) => { eprintln!("Data corrupted, will retry"); } } ``` -------------------------------- ### Cross-Compile for Raspberry Pi (ARM) Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Instructions for cross-compiling the project for Raspberry Pi. This involves installing the necessary toolchain and specifying the target architecture. ```bash curl https://sh.rustup.rs -sSf | sh rustup target add arm-unknown-linux-gnueabihf # Build for 32-bit Pi cargo build --release --target arm-unknown-linux-gnueabihf # Or for 64-bit Pi 4 rustup target add aarch64-unknown-linux-gnu cargo build --release --target aarch64-unknown-linux-gnu ``` -------------------------------- ### Example: Storing and Averaging Readings Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Demonstrates collecting multiple DHT sensor readings, storing them in a vector, and calculating the average temperature and humidity. This snippet includes error handling for read operations and retries. ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).unwrap(); let mut readings = Vec::new(); // Collect multiple readings with retries for attempt in 0..10 { match dht.read() { Ok(reading) => { readings.push(reading); if readings.len() >= 3 { break; } } Err(_) => { continue; } } } if !readings.is_empty() { let avg_temp = readings.iter() .map(|r| r.temperature()) .sum::() / readings.len() as f32; let avg_humidity = readings.iter() .map(|r| r.humidity()) .sum::() / readings.len() as f32; println!("Average temperature: {:.2}°C", avg_temp); println!("Average humidity: {:.2}%RH", avg_humidity); } } ``` -------------------------------- ### Read DHT Sensor Data in Rust Source: https://github.com/krusema/dht-mmap-rust/blob/main/README.md Example of initializing a DHT sensor and reading temperature and humidity. Note that DHT sensor reads can fail, so retries are recommended in production code. ```rust fn main() { // The sensor is a DHT11 connected on pin 23 let mut dht = Dht::new(DhtType::Dht11, 23).unwrap(); // Important: DHT sensor reads fail sometimes. In an actual program, if a read fails you should retry multiple times until // the read succeeds. // For more information, see documentation on `read()` let reading = dht.read().unwrap(); println!( "Temperature {} °C, Humidity {}%RH", reading.temperature(), reading.humidity() ); } ``` -------------------------------- ### Read Temperature and Humidity with Retries Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/dht.md Attempts to read temperature and humidity from the DHT sensor. Due to the inherent unreliability of DHT sensors, this example includes a retry loop. Expect occasional communication or checksum errors. ```rust use dht_mmap_rust::{Dht, DhtType, DhtError}; fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).unwrap(); // Retry logic for unreliable reads for attempt in 1..=5 { match dht.read() { Ok(reading) => { println!("Temperature: {} °C", reading.temperature()); println!("Humidity: {} %RH", reading.humidity()); break; } Err(e) => { eprintln!("Attempt {} failed: {:?}", attempt, e); if attempt == 5 { eprintln!("All retry attempts failed"); } } } } } ``` -------------------------------- ### Run Project with Root Privileges Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md The simplest way to run the project is using sudo. This grants the program full system privileges. ```bash sudo cargo run --release ``` -------------------------------- ### Build and Run Release Version Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Compile the project in release mode and run the executable on a Raspberry Pi. ```bash cargo build --release ./target/release/my_program ``` -------------------------------- ### Get Humidity from Reading Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Retrieves the relative humidity measurement as a percentage from a `Reading` struct. This method is used for accessing humidity data. ```rust pub fn humidity(&self) -> f32 ``` -------------------------------- ### Build and Test Library Locally Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md On non-ARM systems like x86_64, you can verify compilation and run non-hardware tests for the library. ```bash cargo build cargo test --lib # Runs non-hardware tests # Hardware tests will be skipped due to architecture check ``` -------------------------------- ### Get Temperature from Reading Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/reading.md Retrieves the temperature measurement in degrees Celsius from a `Reading` struct. This method is useful for displaying or processing temperature data. ```rust pub fn temperature(&self) -> f32 ``` -------------------------------- ### Dht::new() Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/COMPLETION-REPORT.txt Constructs a new Dht instance. This is the primary entry point for interacting with the DHT sensor. ```APIDOC ## Dht::new() ### Description Initializes and returns a new `Dht` instance, ready for sensor readings. ### Method `Dht::new()` ### Parameters None ### Response - **Dht** (struct) - A new instance of the Dht struct. ### Request Example ```rust let dht = Dht::new(); ``` ### Response Example ```rust // Successful instantiation ``` ``` -------------------------------- ### Granting CAP_SYS_NICE Capability Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/errors.md Use this command to grant the necessary capability for real-time priority on non-Raspberry Pi platforms. Ensure you replace `./my_program` with the actual path to your executable. ```bash sudo setcap cap_sys_nice=ep ./my_program ``` -------------------------------- ### DHT Sensor Initialization Timing Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/protocol.md Illustrates the timing sequence for initializing communication with a DHT sensor, involving host pull-down and stabilization periods. ```text 500ms 20ms Host: ═══════════════════HIGH ═════════LOW ``` -------------------------------- ### Retry DHT Sensor Reads (Rust) Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/README.md Implements a retry mechanism for reading DHT sensor data, as reads can be unreliable. This example retries up to 5 times with a short delay between attempts. ```rust for attempt in 1..=5 { match dht.read() { Ok(reading) => { println!("Success: {:.1}°C", reading.temperature()); break; } Err(e) => { eprintln!("Attempt {} failed: {:?}", attempt, e); std::thread::sleep(std::time::Duration::from_millis(100)); } } } ``` -------------------------------- ### Preventing GPIO Pin Out of Range Panic Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/errors.md Validate GPIO pin numbers before constructing the DHT sensor to prevent panics. This example shows a pre-check to ensure the pin number is within the safe range. ```rust if gpio_pin > 57 { eprintln!("Invalid GPIO pin: {}", gpio_pin); std::process::exit(1); } let dht = Dht::new(DhtType::Dht22, gpio_pin)?; ``` -------------------------------- ### GpioMmapAccess Constructor Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/gpio_mmap_access.md Opens /dev/gpiomem and maps the GPIO register region into memory. This function is internal and not intended for direct use by library consumers. Ensure proper permissions and that the program is running on a Raspberry Pi. ```rust pub fn new() -> Result ``` ```rust use dht_mmap_rust::mmap_gpio::GpioMmapAccess; fn internal_example() { match GpioMmapAccess::new() { Ok(gpio) => println!("GPIO memory map established"), Err(e) => eprintln!("Failed to access GPIO: {:?}", e), } } ``` -------------------------------- ### Run with Root Permissions Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md This command shows how to run the compiled Rust project with root privileges, which may be necessary for accessing hardware resources on some systems. ```bash # Option 1: Run as root sudo cargo run --release ``` -------------------------------- ### Build Debug Binary Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Use this command to build a non-optimized binary with debug symbols. This is useful for development and debugging. ```bash cargo build ``` -------------------------------- ### Initialize DHT Sensor (Rust) Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/README.md Initializes a DHT sensor of a specified type and GPIO pin. Ensure the DhtType matches your hardware and the gpio_pin is correct. ```rust use dht_mmap_rust::{Dht, DhtType}; let mut dht = Dht::new(DhtType::Dht22, 17)?; ``` -------------------------------- ### Run Tests with Cargo Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/README.md Execute the project's tests in release mode. This requires a Raspberry Pi with DHT sensors connected to specific GPIO pins. ```bash sudo cargo test --release ``` -------------------------------- ### Dht::new() Constructor Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt Initializes a new Dht sensor instance. It requires specifying the sensor type and the GPIO pin to which it is connected. This operation can fail if there are issues opening the GPIO file or creating the memory map. ```APIDOC ## Dht::new() ### Description Initializes a new DHT sensor instance, specifying the sensor type and GPIO pin. ### Method `Dht::new(typ: DhtType, gpio_pin: usize) -> Result` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **typ** (DhtType) - Required - The type of DHT sensor (Dht11 or Dht22). - **gpio_pin** (usize) - Required - The GPIO pin number the sensor is connected to. ### Response #### Success Response (Dht) - Returns a `Dht` struct instance on successful initialization. #### Error Response (GpioOpenError) - `GpioOpenError::OpenGpioFileFailed`: Failed to open the GPIO file. - `GpioOpenError::CreateMmapError`: Failed to create the memory map for GPIO access. ### Request Example ```rust use dht_mmap_rust::{Dht, DhtType, GpioOpenError}; let dht_sensor = Dht::new(DhtType::Dht22, 4)?; ``` ### Response Example ```rust // On success: let dht_sensor: Dht = Dht::new(DhtType::Dht22, 4).unwrap(); // On failure: match Dht::new(DhtType::Dht22, 4) { Ok(dht) => println!("DHT sensor initialized successfully."), Err(GpioOpenError::OpenGpioFileFailed) => eprintln!("Error: Failed to open GPIO file."), Err(GpioOpenError::CreateMmapError) => eprintln!("Error: Failed to create memory map."), } ``` ``` -------------------------------- ### Handle OpenGpioFileFailed Error Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/errors.md Demonstrates how to catch and handle the OpenGpioFileFailed error when initializing a DHT sensor. This error typically occurs if the /dev/gpiomem file cannot be accessed. ```Rust use dht_mmap_rust::{Dht, DhtType, GpioOpenError}; match Dht::new(DhtType::Dht22, 17) { Err(GpioOpenError::OpenGpioFileFailed(e)) => { eprintln!("Failed to open /dev/gpiomem: {}", e); eprintln!("Solutions:"); eprintln!(" 1. Run as root: sudo ./my_program"); eprintln!(" 2. Add user to gpio group: sudo usermod -a -G gpio $USER"); eprintln!(" 3. Verify running on Raspberry Pi (not x86/ARM desktop)"); } _ => {} } ``` -------------------------------- ### Verify CAP_SYS_NICE Capability Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Verify that the 'CAP_SYS_NICE' capability has been successfully granted to a program. ```bash getcap /path/to/program # Output: /path/to/program = cap_sys_nice+ep ``` -------------------------------- ### Dht::new Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/INDEX.md Constructs a new Dht instance. It takes a DhtType and a GPIO pin number as input and returns a Result containing either a Dht instance or a GpioOpenError. ```APIDOC ## Dht::new ### Description Constructs a new Dht instance. It takes a DhtType and a GPIO pin number as input and returns a Result containing either a Dht instance or a GpioOpenError. ### Signature (DhtType, usize) -> Result ### Document [api-reference/dht.md](api-reference/dht.md#constructor) ``` -------------------------------- ### Initialize DHT Sensor Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/dht.md Creates a new DHT sensor handle. Specify the sensor type (Dht11 or Dht22) and the GPIO pin number. Ensure correct permissions for /dev/gpiomem. ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { match Dht::new(DhtType::Dht11, 23) { Ok(dht) => { println!("DHT sensor initialized on pin 23"); } Err(e) => { eprintln!("Failed to initialize sensor: {:?}", e); } } } ``` -------------------------------- ### Dht::new Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/README.md Initializes a new DHT sensor handle. This method requires specifying the type of DHT sensor and the GPIO pin number it is connected to. ```APIDOC ## Dht::new ### Description Initializes a new DHT sensor handle. This method requires specifying the type of DHT sensor and the GPIO pin number it is connected to. ### Signature `(DhtType, usize) -> Result` ### Parameters #### Path Parameters - **dht_type** (DhtType) - Required - The type of DHT sensor (e.g., `Dht11`, `Dht22`). - **gpio_pin** (usize) - Required - The GPIO pin number the sensor is connected to. ### Returns - `Result` - Returns a `Dht` handle on success, or a `GpioOpenError` if the GPIO initialization fails. ``` -------------------------------- ### Reconfigure DHT Instance Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md To change configuration parameters like the GPIO pin, you must drop the existing DHT instance and create a new one with the desired settings. ```rust // Switch from pin 17 to pin 23 drop(dht); // Explicitly release the first instance let dht = Dht::new(DhtType::Dht22, 23)?; ``` -------------------------------- ### Add User to GPIO Group Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Recommended for secure, persistent, user-specific access. Add the current user to the 'gpio' group and verify membership. ```bash sudo usermod -a -G gpio $USER # Log out and back in for changes to take effect groups $USER # verify gpio group membership cargo run --release ``` -------------------------------- ### Troubleshoot GPIO Access Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Verify GPIO group membership and check permissions for the /dev/gpiomem device. This helps diagnose issues related to hardware access. ```bash # Verify GPIO group membership groups # Test GPIO access ls -l /dev/gpiomem # Verify sensor connection (DHT22 on GPIO 17) # No automated test exists, but you should see: # - 3.3V power on VCC pin # - GND on GND pin # - Data line on GPIO 17 # - Pull-up resistor (4.7kΩ) between data and 3.3V ``` -------------------------------- ### Project Module Organization Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/README.md Illustrates the directory structure and main files within the dht-mmap-rust project. It shows the public API and internal module organization. ```text dht-mmap-rust/ ├── src/ │ ├── lib.rs # Public API: Dht, Reading, DhtType, DhtError │ ├── mmap_gpio.rs # Internal: GpioMmapAccess │ └── scoped_thread_priority.rs # Internal: HighThreadPriorityGuard └── Cargo.toml ``` -------------------------------- ### Basic DHT Sensor Reading Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Initializes a DHT22 sensor on a specified GPIO pin and performs a single read operation. Handles potential initialization and read errors. ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { // Initialize a DHT22 sensor on GPIO pin 17 let mut dht = match Dht::new(DhtType::Dht22, 17) { Ok(sensor) => sensor, Err(e) => { eprintln!("Failed to initialize sensor: {:?}", e); std::process::exit(1); } }; // Read the sensor match dht.read() { Ok(reading) => { println!("Temperature: {:.1}°C", reading.temperature()); println!("Humidity: {:.1}%RH", reading.humidity()); } Err(e) => { eprintln!("Failed to read sensor: {:?}", e); } } } ``` -------------------------------- ### Handle GPIO Permissions Errors Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md This snippet shows how to gracefully handle errors when accessing GPIO memory, such as when /dev/gpiomem is not accessible. It suggests solutions like running as root or adding the user to the 'gpio' group. ```rust use dht_mmap_rust::{Dht, DhtType, GpioOpenError}; fn main() { match Dht::new(DhtType::Dht22, 17) { Ok(mut dht) => { if let Ok(reading) = dht.read() { println!("Success: {:.1}°C", reading.temperature()); } } Err(GpioOpenError::OpenGpioFileFailed(e)) => { eprintln!("GPIO access failed: {}", e); eprintln!("\nPossible solutions:"); eprintln!("1. Run as root: sudo ./program"); eprintln!("2. Add user to gpio group: sudo usermod -a -G gpio $USER"); eprintln!("3. Verify running on Raspberry Pi"); std::process::exit(1); } Err(GpioOpenError::CreateMmapError(e)) => { eprintln!("Memory mapping failed: {}", e); std::process::exit(1); } } } ``` -------------------------------- ### Dht::new Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/api-reference/dht.md Creates a new DHT sensor handle for reading temperature and humidity data. It requires the sensor type and the GPIO pin number. ```APIDOC ## Dht::new ### Description Creates a new DHT sensor handle for reading temperature and humidity data. ### Parameters #### Path Parameters - **typ** (DhtType) - Required - Sensor type: `DhtType::Dht11` or `DhtType::Dht22` - **gpio_pin** (usize) - Required - GPIO pin number (0-39 on current hardware, but accepts 0-57). Specifying the wrong pin will cause incorrect reads. ### Returns - `Result` On success, returns a new `Dht` struct ready for reading. On failure, returns a `GpioOpenError` if `/dev/gpiomem` cannot be accessed. ### Throws/Panics - `GpioOpenError::OpenGpioFileFailed` — The `/dev/gpiomem` file could not be opened. Ensure the program runs as root or has group-based access to the file. - `GpioOpenError::CreateMmapError` — Memory mapping of the GPIO register failed. - `panic!` — If `gpio_pin > 57`, a panic occurs to prevent memory overwrites. ### Example ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { match Dht::new(DhtType::Dht11, 23) { Ok(dht) => { println!("DHT sensor initialized on pin 23"); } Err(e) => { eprintln!("Failed to initialize sensor: {:?}", e); } } } ``` ``` -------------------------------- ### Handle CreateMmapError Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/errors.md Shows how to catch and handle the CreateMmapError when memory mapping the GPIO register region fails. This error often points to insufficient permissions. ```Rust use dht_mmap_rust::{Dht, DhtType, GpioOpenError}; match Dht::new(DhtType::Dht22, 17) { Err(GpioOpenError::CreateMmapError(e)) => { eprintln!("Memory mapping failed: {}", e); eprintln!("This usually indicates insufficient permissions"); eprintln!("Try: sudo ./my_program"); } _ => {} } ``` -------------------------------- ### Robust DHT Sensor Reading with Retries Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Demonstrates a robust method for reading DHT sensors by implementing a retry mechanism with delays. This is useful because DHT sensors are known for unreliable readings. ```rust use dht_mmap_rust::{Dht, DhtType, DhtError}; use std::thread; use std::time::Duration; fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).expect("GPIO init failed"); // Retry up to 5 times with brief delays between attempts for attempt in 1..=5 { match dht.read() { Ok(reading) => { println!("✓ Read succeeded on attempt {}", attempt); println!("Temperature: {:.1}°C", reading.temperature()); println!("Humidity: {:.1}%RH", reading.humidity()); return; } Err(DhtError::ReadTimeoutEarly) => { eprintln!("Attempt {}: Sensor not responding", attempt); } Err(DhtError::ReadTimeoutData) => { eprintln!("Attempt {}: Transmission interrupted", attempt); // Brief delay before retry helps with timing-sensitive errors if attempt < 5 { thread::sleep(Duration::from_millis(100)); } } Err(DhtError::ChecksumMismatch) => { eprintln!("Attempt {}: Data corrupted (checksum failed)", attempt); } } } eprintln!("✗ All 5 read attempts failed"); std::process::exit(1); } ``` -------------------------------- ### Grant CAP_SYS_NICE Capability Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Use Linux capabilities to grant the 'CAP_SYS_NICE' capability to the program for real-time scheduling priority elevation without full root access. This is a persistent and least-privilege approach. ```bash sudo setcap cap_sys_nice=ep ./target/release/my_program ./target/release/my_program ``` -------------------------------- ### Change /dev/gpiomem Permissions Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Directly change the permissions of the /dev/gpiomem file to allow read/write access. This change resets on reboot and is not recommended due to security risks. ```bash sudo chmod 666 /dev/gpiomem ``` -------------------------------- ### Add User to GPIO Group Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md On Raspberry Pi, add the current user to the 'gpio' group to grant necessary permissions for GPIO access. Remember to log out and back in for the changes to take effect. ```bash sudo usermod -a -G gpio $USER # Log out and back in ``` -------------------------------- ### DHT Sensor Wiring Diagram Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/protocol.md Illustrates the typical wiring for a DHT sensor, including the 3.3V supply, GND, data line connection to a GPIO pin, and the required 4.7kΩ pull-up resistor. ```text 4.7kΩ 3.3V ───/\/\/\/───┬─── Data → GPIO Pin │ DHT22/11 ┌──┐ │VCC├─ 3.3V │GND├─ GND │DAT├─ Data (GPIO Pin) └──┘ ``` -------------------------------- ### Apply Calibration Offsets to DHT Readings Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Applies experimental calibration offsets to temperature and humidity readings from a DHT sensor. Clamps humidity to a valid range. Useful for correcting sensor drift. ```rust use dht_mmap_rust::{Dht, DhtType, Reading}; // Calibration offsets determined experimentally const TEMP_OFFSET: f32 = 0.5; // DHT reads 0.5°C too high const HUMIDITY_OFFSET: f32 = -3.0; // DHT reads 3% too high fn calibrate(reading: Reading) -> Reading { // Note: Reading is not mutable by default, so we create a new one // (This is a workaround; ideally we'd modify the struct directly) let raw_temp = reading.temperature() - TEMP_OFFSET; let raw_humidity = reading.humidity() - HUMIDITY_OFFSET; // Clamp humidity to valid range let clamped_humidity = raw_humidity.max(0.0).min(100.0); println!("Raw: {:.1}°C, {:.1}%RH", reading.temperature(), reading.humidity()); println!("Cal: {:.1}°C, {:.1}%RH", raw_temp, clamped_humidity); reading // Return as-is for now; real code would reconstruct with calibrated values } fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).expect("Init failed"); for _ in 0..3 { if let Ok(reading) = dht.read() { calibrate(reading); } std::thread::sleep(std::time::Duration::from_secs(1)); } } ``` -------------------------------- ### Collect and Average DHT Sensor Readings Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Collect multiple readings from a single DHT sensor and calculate the average temperature and humidity. Includes retry logic for sensor reads. ```rust use dht_mmap_rust::{Dht, DhtType}; use std::thread; use std::time::Duration; fn main() { let mut dht = Dht::new(DhtType::Dht22, 17).expect("GPIO init failed"); const SAMPLES: usize = 5; let mut readings = Vec::with_capacity(SAMPLES); // Collect multiple readings for i in 0..SAMPLES { for attempt in 1..=3 { match dht.read() { Ok(reading) => { readings.push(reading); println!("Sample {}/{}: {:.1}°C", i + 1, SAMPLES, reading.temperature()); break; } Err(_) if attempt < 3 => { thread::sleep(Duration::from_millis(100)); } Err(e) => { eprintln!("Failed to read sensor: {:?}", e); } } } } // Calculate averages if !readings.is_empty() { let avg_temp = readings.iter() .map(|r| r.temperature()) .sum::() / readings.len() as f32; let avg_humidity = readings.iter() .map(|r| r.humidity()) .sum::() / readings.len() as f32; println!("\nAverages ({} samples):", readings.len()); println!("Temperature: {:.2}°C", avg_temp); println!("Humidity: {:.2}%RH", avg_humidity); } } ``` -------------------------------- ### Read from Multiple DHT Sensors Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/example-usage.md Initialize and read data from multiple DHT sensors connected to different GPIO pins. Handles initialization and read errors for each sensor. ```rust use dht_mmap_rust::{Dht, DhtType}; fn main() { // Multiple sensors on different GPIO pins let mut sensors = vec![ ("Outdoor", DhtType::Dht22, 17), ("Indoor", DhtType::Dht22, 18), ("Basement", DhtType::Dht11, 27), ]; for (name, sensor_type, gpio_pin) in sensors { match Dht::new(sensor_type, gpio_pin) { Ok(mut dht) => { for attempt in 1..=3 { match dht.read() { Ok(reading) => { println!("{}: {:.1}°C, {:.1}%RH", name, reading.temperature(), reading.humidity()); break; } Err(_) if attempt < 3 => { std::thread::sleep(std::time::Duration::from_millis(100)); } Err(e) => { eprintln!("{}: Read failed: {:?}", name, e); } } } } Err(e) => { eprintln!("{}: Init failed: {:?}", name, e); } } } } ``` -------------------------------- ### Grant CAP_SYS_NICE Capability for Scheduling Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/configuration.md Grant the 'CAP_SYS_NICE' capability to a program to allow real-time scheduling priority elevation. This is required for accurate sensor read timing. ```bash sudo setcap cap_sys_nice=ep /path/to/program ``` -------------------------------- ### Dht::read() Method Source: https://github.com/krusema/dht-mmap-rust/blob/main/_autodocs/DOCUMENTATION_SUMMARY.txt Reads the temperature and humidity data from the initialized DHT sensor. This method can return various errors related to communication timeouts or data integrity. ```APIDOC ## Dht::read() ### Description Reads the current temperature and humidity from the DHT sensor. ### Method `Dht::read(&mut self) -> Result` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - `self`: A mutable reference to the `Dht` instance. ### Response #### Success Response (Reading) - Returns a `Reading` struct containing the temperature and humidity values. #### Error Response (DhtError) - `DhtError::ReadTimeoutEarly`: The sensor did not respond within the expected early timeout period. - `DhtError::ReadTimeoutData`: The sensor did not send data within the expected timeout period. - `DhtError::ChecksumMismatch`: The checksum calculated from the received data does not match the checksum sent by the sensor. ### Request Example ```rust use dht_mmap_rust::{Dht, DhtType, DhtError}; let mut dht_sensor = Dht::new(DhtType::Dht22, 4)?; let reading = dht_sensor.read()?; ``` ### Response Example ```rust match dht_sensor.read() { Ok(reading) => { println!("Temperature: {:.1}°C", reading.temperature()); println!("Humidity: {:.1}%", reading.humidity()); }, Err(DhtError::ReadTimeoutEarly) => eprintln!("Error: Read timeout (early)."), Err(DhtError::ReadTimeoutData) => eprintln!("Error: Read timeout (data)."), Err(DhtError::ChecksumMismatch) => eprintln!("Error: Checksum mismatch."), } ``` ```