diff --git a/Cargo.lock b/Cargo.lock index c2ae476..ee99d32 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,31 +3,39 @@ version = 3 [[package]] -name = "bitflags" -version = "2.5.0" +name = "ads1x1x" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "6b44310e48193933db0cd788961f450a86f35fdad022e4373883fa8e4640488e" +dependencies = [ + "embedded-hal 0.2.7", + "nb 1.1.0", +] [[package]] -name = "cfg-if" -version = "1.0.0" +name = "embedded-hal" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] [[package]] -name = "cfg_aliases" -version = "0.1.1" +name = "embedded-hal" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" [[package]] -name = "interrupts" -version = "0.1.5" +name = "embedded-hal-nb" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ccb0bdc9cefc5772ebc23d9bd94aabf408ab6753735f1936ac6ed7e714c8c6" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" dependencies = [ - "cfg-if", - "nix", + "embedded-hal 1.0.0", + "nb 1.1.0", ] [[package]] @@ -37,31 +45,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "linux_realtime" -version = "0.1.0" +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" dependencies = [ - "libc", + "nb 1.1.0", ] [[package]] -name = "nix" -version = "0.28.0" +name = "nb" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" [[package]] name = "rpitest" version = "0.1.0" dependencies = [ - "interrupts", + "ads1x1x", "libc", - "linux_realtime", + "nb 1.1.0", "rppal", ] @@ -71,5 +75,99 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dc171bbe325b04172e18d917c58c2cf1fb5adfd9ffabb1d6b3d62ba4c1c1331" dependencies = [ + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-nb", "libc", + "nb 0.1.3", + "spin_sleep", + "void", +] + +[[package]] +name = "spin_sleep" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368a978649eaf70006b082e79c832bd72556ac1393eaf564d686e919dca2347f" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", ] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml index 6df969c..65e877a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,10 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rppal = "0.17.1" +rppal = { version = "0.17", features = ["hal"] } #rumqttc = "0.24.0" -interrupts = "0.1.5" -libc = "0.2.153" - -[dependencies.linux_realtime] -path = "../linux_realtime" +libc = "0.2" +ads1x1x = "0.2" +nb = "1.1.0" diff --git a/src/main.rs b/src/main.rs index d057be8..0735780 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,35 +1,127 @@ -use std::{error::Error, time::Duration}; - -use dht11::Dht11Sensor; -use linux_realtime::ThreadAttributes; - -mod dht11; - -fn main() -> Result<(), Box> { - let mut sensor = Dht11Sensor::new(2)?; - let t = linux_realtime::JoinHandle::spawn( - ThreadAttributes { - stack_size: libc::PTHREAD_STACK_MIN, - scheduler_policy: linux_realtime::SchedulerPolicy::Fifo, - thread_priority: 99, - }, - move || -> Result<(), Box> { - loop { - let mut rtclock = linux_realtime::Clock::new()?; - match sensor.read() { - Ok(data) => println!( - "Humidity: {}; Temperature: {}", - data.humidity, data.temperature - ), - Err(msg) => println!("Error: {}", msg), - } - for n in 1..10 { - rtclock.sleep(Duration::from_millis(500))?; +use std::{error::Error, io, thread, time::Duration}; + +use ads1x1x::{Ads1x1x, ChannelSelection, DynamicOneShot}; +use nb::block; +use rppal::{ + gpio::{Gpio, OutputPin}, + i2c::I2c, +}; + +type GenericResult = Result>; + +struct ProgramState { + water_pin: OutputPin, + light_pin: OutputPin, + fan_pin: OutputPin, +} + +fn setup_program_state() -> GenericResult { + let mut water_pin = Gpio::new()?.get(22)?.into_output(); + let mut light_pin = Gpio::new()?.get(17)?.into_output(); + let mut fan_pin = Gpio::new()?.get(27)?.into_output(); + + water_pin.set_high(); + light_pin.set_high(); + fan_pin.set_high(); + + Ok(ProgramState { + water_pin, + light_pin, + fan_pin, + }) +} + +fn main() -> GenericResult<()> { + let mut program_state: ProgramState = setup_program_state()?; + + loop { + println!("Enter command: "); + let mut input_string = String::new(); + io::stdin().read_line(&mut input_string)?; + + match process_command(input_string, &mut program_state) { + Ok(to_exit) => { + if to_exit { + break; } } - }, - )?; - _ = t.join(); + Err(err) => println!("Error: {}", err), + } + } + + Ok(()) +} + +fn process_command(command: String, program_state: &mut ProgramState) -> GenericResult { + let command = command + .strip_suffix('\n') + .ok_or("Couldn't strip whitespace")?; + let args = command.split(' ').collect::>(); + + let main_command = *args.first().ok_or("No command found")?; + match main_command { + "water" => toggle_water(&args, program_state)?, + "fan" => toggle_fan(program_state)?, + "light" => toggle_light(program_state)?, + "ana" => analogue_command(&args, program_state)?, + "exit" => return Ok(true), + _ => return Err(format!("Main command '{}' invalid", main_command).into()), + } + + Ok(false) +} + +fn analogue_command(args: &[&str], program_state: &mut ProgramState) -> GenericResult<()> { + let pin = args.get(1).ok_or("No pin given")?; + let pin: u8 = pin.parse()?; + + let adc_target = rppal::i2c::I2c::new()?; + let mut adc_target = + Ads1x1x::new_ads1115(adc_target, ads1x1x::SlaveAddr::Alternative(false, false)); + let channel: ChannelSelection = match pin { + 0 => ChannelSelection::SingleA0, + 1 => ChannelSelection::SingleA1, + 2 => ChannelSelection::SingleA2, + 3 => ChannelSelection::SingleA3, + _ => ChannelSelection::SingleA0, + }; + loop { + let value = block!(adc_target.read(channel)).map_err(|e| format!("{:?}", e))?; + let value = value as f32; + let voltage = value / i16::MAX as f32 * 2.048; + let resistance = (3.3 / voltage - 1.) * 9_700.; + println!("Value: {}", value); + println!("resistance: {}", resistance); + let temp = 1. / ((1. / 298.15) + (1. / 3950. * f32::ln(resistance / 10_000.))) - 273.15; + println!("Temp: {}", temp); + //println!("Value of pin {} is: {}", pin, value); + thread::sleep(Duration::from_millis(2000)); + } + Ok(()) +} + +fn toggle_water(args: &[&str], program_state: &mut ProgramState) -> GenericResult<()> { + if let Some(duration) = args.get(1) { + let duration: u64 = duration.parse()?; + println!("Turning on water for {} milliseconds", duration); + program_state.water_pin.set_low(); + thread::sleep(Duration::from_millis(duration)); + program_state.water_pin.set_high(); + } else { + program_state.water_pin.toggle(); + println!("Toggling water output"); + } + Ok(()) +} + +fn toggle_light(program_state: &mut ProgramState) -> GenericResult<()> { + program_state.light_pin.toggle(); + println!("Toggling light output"); + Ok(()) +} +fn toggle_fan(program_state: &mut ProgramState) -> GenericResult<()> { + program_state.fan_pin.toggle(); + println!("Toggling fan output"); Ok(()) }