commit bdb32de10d5757873f82e0c2ae567677ea3a4ad7 Author: Zykino Date: Wed Mar 11 22:35:28 2020 +0100 Initial commit, MVP ready/hardcoded diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d1f4d2a --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,30 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" + +[[package]] +name = "rppal" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "137dbba1fb867daa27cda4c3cd6a11bca5bb5a1551f034cf9319b994846ddbe1" +dependencies = [ + "lazy_static", + "libc", +] + +[[package]] +name = "tempi" +version = "0.1.0" +dependencies = [ + "rppal", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b9e6373 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tempi" +version = "0.1.0" +authors = ["Zykino"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rppal = "0.11.3" + diff --git a/src/fan/hysteresis.rs b/src/fan/hysteresis.rs new file mode 100644 index 0000000..c99b3ba --- /dev/null +++ b/src/fan/hysteresis.rs @@ -0,0 +1,45 @@ +use crate::fan::Fan; +use crate::temperatures::Temperatures; + +use rppal::gpio::{Gpio, OutputPin}; + +pub struct Hysteresis { + pub max_temperature: f64, + pub hysteresis: f64, + pin: OutputPin, +} + +impl Hysteresis { + pub fn new(max_temperature: f64, hysteresis: f64, bcm_pin: u8) -> Hysteresis { + let gpio = Gpio::new().unwrap(); + let mut pin = gpio.get(bcm_pin).unwrap().into_output(); + + pin.set_low(); + + Hysteresis { + max_temperature, + hysteresis, + pin, + } + } +} + +impl Fan for Hysteresis { + fn update_temperature(&mut self, temperatures: &Temperatures) { + if temperatures.cpu > self.max_temperature { + self.pin.set_high(); + } else { + if temperatures.cpu < self.max_temperature - self.hysteresis { + self.pin.set_low(); + } + } + } + + fn percentage(&self) -> f64 { + if self.pin.is_set_high() { + 1_f64 + } else { + 0_f64 + } + } +} diff --git a/src/fan/mod.rs b/src/fan/mod.rs new file mode 100644 index 0000000..a4a7f82 --- /dev/null +++ b/src/fan/mod.rs @@ -0,0 +1,9 @@ +pub mod hysteresis; +pub mod pwm; + +use crate::temperatures::Temperatures; + +pub trait Fan { + fn update_temperature(&mut self, _: &Temperatures); + fn percentage(&self) -> f64; +} diff --git a/src/fan/pwm.rs b/src/fan/pwm.rs new file mode 100644 index 0000000..0d47cde --- /dev/null +++ b/src/fan/pwm.rs @@ -0,0 +1,46 @@ +use crate::fan::Fan; +use crate::temperatures::Temperatures; + +use rppal::pwm::{Channel, Polarity, Pwm as Pwm_rpi}; + +pub struct Pwm { + pub max_temperature: f64, + pub min_temperature: f64, + pwm: Pwm_rpi, +} + +impl Pwm { + pub fn new(max_temperature: f64, min_temperature: f64, bcm_pin: Channel) -> Pwm { + let pwm = + Pwm_rpi::with_frequency(bcm_pin, 0.1_f64, 0_f64, Polarity::Normal, false).unwrap(); + + Pwm { + max_temperature, + min_temperature, + pwm, + } + } +} + +impl Fan for Pwm { + fn update_temperature(&mut self, temperatures: &Temperatures) { + let percentage = (temperatures.cpu - self.min_temperature) + / (self.max_temperature - self.min_temperature); + let percentage = if percentage > 1_f64 { + 1_f64 + } else { + percentage + }; + + if temperatures.cpu > self.min_temperature { + self.pwm.enable().unwrap(); + self.pwm.set_duty_cycle(percentage).unwrap(); + } else { + self.pwm.disable().unwrap(); + } + } + + fn percentage(&self) -> f64 { + self.pwm.duty_cycle().unwrap() + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ccb6c1e --- /dev/null +++ b/src/main.rs @@ -0,0 +1,32 @@ +mod fan; +mod temperatures; + +use fan::hysteresis::Hysteresis; +use fan::pwm::Pwm; +use fan::Fan; + +use rppal::pwm::Channel; +use std::thread; +use std::time::Duration; + +fn main() { + let mut temps = temperatures::Temperatures::default(); + + let mut fan: Box = if true { + Box::new(Hysteresis::new(52.0, 5.0, 18)) + } else { + Box::new(Pwm::new(52.0, 42.0, Channel::Pwm0)) + }; + + loop { + temps.update(); + fan.update_temperature(&temps); + println!( + "CPU: {:.1}°C, fan is at {:.1}%", + temps.cpu, + fan.percentage() * 100_f64 + ); + + thread::sleep(Duration::from_secs(5)); + } +} diff --git a/src/temperatures.rs b/src/temperatures.rs new file mode 100644 index 0000000..8a7cc12 --- /dev/null +++ b/src/temperatures.rs @@ -0,0 +1,28 @@ +use std::fs::File; +use std::io::prelude::*; + +pub struct Temperatures { + pub cpu: f64, +} + +impl Default for Temperatures { + fn default() -> Self { + Temperatures { + cpu: get_cpu_temp(), + } + } +} + +impl Temperatures { + pub fn update(&mut self) { + self.cpu = get_cpu_temp(); + } +} + +fn get_cpu_temp() -> f64 { + let mut f = File::open("/sys/class/thermal/thermal_zone0/temp").unwrap(); + let mut buffer = String::new(); + f.read_to_string(&mut buffer).unwrap(); + + buffer.trim().parse::().unwrap() / 1_000_f64 +}