From 8ad2e2069f2cc4e3359f68c581dc81eb723a8295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Thu, 26 Dec 2024 12:16:04 -0300 Subject: [PATCH 1/6] Cargo: Update dependencies to use latest embedded-hal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- Cargo.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0fc60a8c2..2578fa715 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,17 +11,17 @@ keywords = ["BlueRobotics", "embedded", "navigator", "robotics", "ROV"] readme = "README.md" [dependencies] -ads1x1x = "0.2.2" -ak09915_rs= "0.2.0" +ads1x1x = { git = "https://github.com/eldruin/ads1x1x-rs" } +ak09915_rs = { git = "https://github.com/bluerobotics/AK09915-rs" } approx = "0.5.1" bmp280 = "0.4.0" -dummy-pin = "0.1.1" -embedded-hal = "0.2.7" -icm20689 = "0.1.1" -linux-embedded-hal = "0.3.2" +dummy-pin = "1.0.0" +embedded-hal = "1.0.0" +icm20689 = { git = "https://github.com/tstellanova/icm20689" } +linux-embedded-hal = "0.4.0" log = "0.4.19" nb = "1.1.0" -pwm-pca9685 = "0.3.1" +pwm-pca9685 = "1.0.0" sk6812_rpi = "0.1" [dev-dependencies] From 95e1f84a5b2fbc6760a4695c008eca9685fddf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Thu, 26 Dec 2024 12:17:22 -0300 Subject: [PATCH 2/6] ads1115: Update to use latest embedded-hal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- src/ads1115.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/ads1115.rs b/src/ads1115.rs index 909b037c0..ebc06883d 100644 --- a/src/ads1115.rs +++ b/src/ads1115.rs @@ -2,15 +2,14 @@ use std::error::Error; use ads1x1x::{ ic::{Ads1115, Resolution16Bit}, - interface::I2cInterface, - Ads1x1x, DynamicOneShot, SlaveAddr, + Ads1x1x, TargetAddr, }; use linux_embedded_hal::I2cdev; use crate::peripherals::{AdcSensor, AnyHardware, PeripheralClass, PeripheralInfo, Peripherals}; pub struct Ads1115Device { - adc: Ads1x1x, Ads1115, Resolution16Bit, ads1x1x::mode::OneShot>, + adc: Ads1x1x, info: PeripheralInfo, } @@ -32,7 +31,7 @@ impl AnyHardware for Ads1115Device { pub struct Ads1115DeviceBuilder { i2c_bus: String, - address: SlaveAddr, + address: TargetAddr, info: PeripheralInfo, } @@ -40,7 +39,7 @@ impl Ads1115DeviceBuilder { pub fn new() -> Self { Ads1115DeviceBuilder { i2c_bus: "/dev/i2c-1".into(), - address: SlaveAddr::default(), + address: TargetAddr::default(), info: PeripheralInfo { peripheral: Peripherals::Ads1115, class: vec![PeripheralClass::Adc], @@ -63,7 +62,7 @@ impl Ads1115DeviceBuilder { /// # Arguments /// /// * `address` - The I²C address (e.g., 0x48). - pub fn with_address(mut self, address: SlaveAddr) -> Self { + pub fn with_address(mut self, address: TargetAddr) -> Self { self.address = address; self } @@ -77,7 +76,6 @@ impl Ads1115DeviceBuilder { let i2c = I2cdev::new(self.i2c_bus)?; let mut adc = Ads1x1x::new_ads1115(i2c, self.address); - adc.reset_internal_driver_state(); adc.set_full_scale_range(ads1x1x::FullScaleRange::Within4_096V) .unwrap(); adc.set_data_rate(ads1x1x::DataRate16Bit::Sps860).unwrap(); @@ -91,17 +89,17 @@ impl Ads1115DeviceBuilder { impl AdcSensor for Ads1115Device { fn read_channel(&mut self, channel: usize) -> Result> { - let channel_selection = match channel { - 0 => ads1x1x::ChannelSelection::SingleA0, - 1 => ads1x1x::ChannelSelection::SingleA1, - 2 => ads1x1x::ChannelSelection::SingleA2, - 3 => ads1x1x::ChannelSelection::SingleA3, - _ => return Err("Invalid ADC channel".into()), - }; - // Keep trying to read until the conversion is complete loop { - match self.adc.read(channel_selection) { + let channel_value = match channel { + 0 => self.adc.read(ads1x1x::channel::SingleA0), + 1 => self.adc.read(ads1x1x::channel::SingleA1), + 2 => self.adc.read(ads1x1x::channel::SingleA2), + 3 => self.adc.read(ads1x1x::channel::SingleA3), + _ => return Err("Invalid ADC channel".into()), + }; + + match channel_value { Ok(raw_value) => { // TODO: Hold configuration over having it hardcoded let gain = ads1x1x::FullScaleRange::Within4_096V; From 484fd157c35e167c18e4a8c003c920037cdb9378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Thu, 26 Dec 2024 12:17:53 -0300 Subject: [PATCH 3/6] bmp390: Update to use latest embedded-hal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- src/bmp390.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bmp390.rs b/src/bmp390.rs index 2dca9eec5..27c3b647a 100644 --- a/src/bmp390.rs +++ b/src/bmp390.rs @@ -1,7 +1,7 @@ use std::error::Error; use std::path::PathBuf; -use embedded_hal::blocking::i2c::{Write, WriteRead}; +use embedded_hal::i2c::I2c; use linux_embedded_hal::I2cdev; use crate::peripherals::{ From c4b3fa000192c11d4a7021530dd2db8fda193f59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Thu, 26 Dec 2024 12:18:06 -0300 Subject: [PATCH 4/6] icm20689: Update to use latest embedded-hal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- src/icm20689.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/icm20689.rs b/src/icm20689.rs index 396f08327..696f0e5ab 100644 --- a/src/icm20689.rs +++ b/src/icm20689.rs @@ -2,15 +2,17 @@ use std::error::Error; use dummy_pin::DummyPin; use icm20689::{self, Builder as ImuBuilder, SpiInterface, ICM20689}; -use linux_embedded_hal::spidev::{SpiModeFlags, SpidevOptions}; -use linux_embedded_hal::{Delay, Spidev}; +use linux_embedded_hal::{ + spidev::{SpiModeFlags, SpidevOptions}, + Delay, SpidevDevice, +}; use crate::peripherals::{ AccelerometerSensor, AnyHardware, GyroscopeSensor, PeripheralClass, PeripheralInfo, Peripherals, }; pub struct Icm20689Device { - imu: ICM20689>, + imu: ICM20689>, info: PeripheralInfo, } @@ -66,7 +68,7 @@ impl Icm20689Builder { } pub fn build(self) -> Result> { - let mut spi = Spidev::open(self.spi_device)?; + let mut spi = SpidevDevice::open(self.spi_device)?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(10_000_000) From f992dcf93c736bb7b398ee86e4cddabe4af7d4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Fri, 27 Dec 2024 11:48:03 -0300 Subject: [PATCH 5/6] navigator2 wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- Cargo.toml | 5 ++ src/bmp180.rs | 144 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 ++ src/mpu6050.rs | 133 +++++++++++++++++++++++++++++++++++++++++ src/peripherals.rs | 2 + 5 files changed, 288 insertions(+) create mode 100644 src/bmp180.rs create mode 100644 src/mpu6050.rs diff --git a/Cargo.toml b/Cargo.toml index 2578fa715..1b0736cfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,12 +14,17 @@ readme = "README.md" ads1x1x = { git = "https://github.com/eldruin/ads1x1x-rs" } ak09915_rs = { git = "https://github.com/bluerobotics/AK09915-rs" } approx = "0.5.1" +bmp180-driver = "0.1.1" +bmp180-embedded-hal = { version = "0.1.0", features = ["blocking"] } bmp280 = "0.4.0" dummy-pin = "1.0.0" embedded-hal = "1.0.0" +ftdi = "0.1.3" +ftdi-embedded-hal = "0.22.1" icm20689 = { git = "https://github.com/tstellanova/icm20689" } linux-embedded-hal = "0.4.0" log = "0.4.19" +mpu6050 = { git = "https://github.com/patrickelectric/mpu6050", rev = "0fe2526" } nb = "1.1.0" pwm-pca9685 = "1.0.0" sk6812_rpi = "0.1" diff --git a/src/bmp180.rs b/src/bmp180.rs new file mode 100644 index 000000000..6ef87bb63 --- /dev/null +++ b/src/bmp180.rs @@ -0,0 +1,144 @@ +use std::error::Error; + +//use bmp180_embedded_hal::blocking::{UninitBMP180, BMP180} +use bmp180_driver::{Common, InitializedBMP180, Resolution, BMP180}; +use linux_embedded_hal::{Delay, I2cdev}; + +use crate::peripherals::{ + AnyHardware, BarometerSensor, PeripheralClass, PeripheralInfo, Peripherals, TemperatureSensor, +}; + +pub struct Bmp180Device { + bmp180: InitializedBMP180, + info: PeripheralInfo, +} + +impl Bmp180Device { + pub fn builder() -> BarometerBuilder { + BarometerBuilder::new() + } + + pub fn get_peripheral_info(&self) -> &PeripheralInfo { + &self.info + } +} + +impl AnyHardware for Bmp180Device { + fn as_temperature_sensor(&mut self) -> Option<&mut dyn TemperatureSensor> { + Some(self) + } + + fn as_barometer_sensor(&mut self) -> Option<&mut dyn BarometerSensor> { + Some(self) + } +} + +pub struct BarometerBuilder { + i2c_bus: Result>, + address: u8, + info: PeripheralInfo, +} + +impl BarometerBuilder { + pub fn new() -> Self { + BarometerBuilder { + i2c_bus: I2cdev::new("/dev/i2c-1").map_err(|e| Box::new(e) as Box), + address: 0x76, + info: PeripheralInfo { + peripheral: Peripherals::Bmp180, + class: vec![PeripheralClass::Pressure, PeripheralClass::Temperature], + }, + } + } + + /// Sets the I²C bus to be used. + /// + /// # Arguments + /// + /// * `bus` - The I²C bus (e.g., "/dev/i2c-1"). + pub fn with_i2c_bus(mut self, bus: &str) -> Self { + self.i2c_bus = I2cdev::new(bus).map_err(|e| Box::new(e) as Box); + self + } + + pub fn with_i2c(mut self, i2c: Result>) -> Self { + self.i2c_bus = i2c; + self + } + + /// Sets the I²C address + /// + /// # Arguments + /// + /// * `address` - The I²C address (e.g., 0x76). + pub fn with_address(mut self, address: u8) -> Self { + self.address = address; + self + } + + pub fn with_peripheral_info(mut self, info: PeripheralInfo) -> Self { + self.info = info; + self + } + + pub fn build(self) -> Result> { + let i2c = self.i2c_bus?; + let delay = Delay {}; + + let mut bmp180 = BMP180::new(i2c, delay); + bmp180.check_connection()?; + let bmp180 = bmp180.initialize()?; + + Ok(Bmp180Device { + bmp180, + info: self.info, + }) + } +} + +impl TemperatureSensor for Bmp180Device { + fn read_temperature(&mut self) -> Result> { + let temperature = self.bmp180.temperature()?; + Ok(temperature / 10.0) + } +} + +impl BarometerSensor for Bmp180Device { + fn read_pressure(&mut self) -> Result> { + let pressure = self.bmp180.pressure(Resolution::Standard)? as f32; + Ok(pressure) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use ftdi_embedded_hal as hal; + + #[test] + fn ftdi() { + let device = ftdi::find_by_vid_pid(0x0403, 0x6011) + .interface(ftdi::Interface::A) + .open() + .unwrap(); + + let hal = hal::FtHal::init_default(device).unwrap(); + let mut i2c = hal + .i2c() + .map_err(|e| Box::new(e) as Box) + .unwrap(); + + let mut bmp180 = BMP180::new(i2c, Delay {}); + bmp180.check_connection().unwrap(); + let mut bmp180 = bmp180.initialize().unwrap(); + + loop { + let temperature = bmp180.temperature().unwrap(); + let pressure = bmp180.pressure(Resolution::Standard).unwrap() as f32; + println!( + "Temperature: {:.2}°C, Pressure: {:.2}hPa", + temperature, pressure + ); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8bfa6aa31..7455752eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,11 +6,13 @@ use std::fmt; mod ads1115; mod ak09915; +mod bmp180; mod bmp280; mod bmp390; mod icm20689; mod leak; mod led; +mod mpu6050; mod pca9685; mod peripherals; mod rgb; @@ -21,9 +23,11 @@ use crate::bmp280::Bmp280Device; use crate::icm20689::Icm20689Device; use ads1115::Ads1115Device; use ak09915::Ak09915Device; +use bmp180::Bmp180Device; use bmp390::Bmp390Device; use leak::LeakDetector; use led::LedController; +use mpu6050::Mpu6050Device; use pca9685::Pca9685Device; use rgb::RgbController; diff --git a/src/mpu6050.rs b/src/mpu6050.rs new file mode 100644 index 000000000..147eb4698 --- /dev/null +++ b/src/mpu6050.rs @@ -0,0 +1,133 @@ +use crate::peripherals::{ + AccelerometerSensor, AnyHardware, GyroscopeSensor, PeripheralClass, PeripheralInfo, + Peripherals, TemperatureSensor, +}; +use embedded_hal::i2c::I2c; +use linux_embedded_hal::{Delay, I2cdev}; +use mpu6050::{Mpu6050, Mpu6050Error}; +use std::error::Error; + +pub struct Mpu6050Device { + mpu: Mpu6050, + info: PeripheralInfo, +} + +impl Mpu6050Device { + pub fn builder() -> Mpu6050Builder { + Mpu6050Builder::new() + } + + pub fn get_peripheral_info(&self) -> &PeripheralInfo { + &self.info + } +} + +impl AnyHardware for Mpu6050Device { + fn as_gyroscope_sensor(&mut self) -> Option<&mut dyn GyroscopeSensor> { + Some(self) + } + + fn as_accelerometer_sensor(&mut self) -> Option<&mut dyn AccelerometerSensor> { + Some(self) + } + + fn as_temperature_sensor(&mut self) -> Option<&mut dyn TemperatureSensor> { + Some(self) + } +} + +pub struct Mpu6050Builder { + i2c_device: String, + info: PeripheralInfo, +} + +impl Mpu6050Builder { + pub fn new() -> Self { + Mpu6050Builder { + i2c_device: "/dev/i2c-1".to_string(), + info: PeripheralInfo { + peripheral: Peripherals::Mpu6050, + class: vec![PeripheralClass::Accelerometer, PeripheralClass::Gyroscope], + }, + } + } + + pub fn with_i2c_device(mut self, device: &str) -> Self { + self.i2c_device = device.to_string(); + self + } + + pub fn with_peripheral_info(mut self, info: PeripheralInfo) -> Self { + self.info = info; + self + } + + pub fn build(self) -> Result> { + let i2c = I2cdev::new(&self.i2c_device)?; + let mut mpu = Mpu6050::new(i2c); + mpu.init(&mut Delay).unwrap(); + Ok(Mpu6050Device { + mpu, + info: self.info, + }) + } +} + +impl GyroscopeSensor for Mpu6050Device { + fn read_angular_velocity(&mut self) -> Result<(f32, f32, f32), Box> { + let gyro = self.mpu.get_gyro().unwrap(); + Ok((gyro.x, gyro.y, gyro.z)) + } +} + +impl AccelerometerSensor for Mpu6050Device { + fn read_acceleration(&mut self) -> Result<(f32, f32, f32), Box> { + let acc = self.mpu.get_acc().unwrap(); + Ok((acc.x, acc.y, acc.z)) + } +} + +impl TemperatureSensor for Mpu6050Device { + fn read_temperature(&mut self) -> Result> { + let temp = self.mpu.get_temp().unwrap(); + Ok(temp) + } +} + +#[cfg(test)] +mod tests { + use ftdi_embedded_hal as hal; + use linux_embedded_hal::Delay; + use mpu6050::Mpu6050; + use std::error::Error; + + #[test] + fn ftdi() -> Result<(), Box> { + let device = ftdi::find_by_vid_pid(0x0403, 0x6011) + .interface(ftdi::Interface::A) + .open()?; + + let hal = hal::FtHal::init_default(device)?; + let i2c = hal.i2c().map_err(|e| Box::new(e) as Box)?; + + let mut mpu = Mpu6050::new(i2c); + mpu.init(&mut Delay).unwrap(); + + // Necessary for GY87 board + // i2c detect will work after this + mpu.set_master_interrupt_enabled(false).unwrap(); + mpu.set_bypass_enabled(true).unwrap(); + mpu.set_sleep_enabled(false).unwrap(); + + loop { + let gyro = mpu.get_gyro().unwrap(); + let acc = mpu.get_acc().unwrap(); + println!( + "Gyro: x={:.2} y={:.2} z={:.2}, Acc: x={:.2} y={:.2} z={:.2}", + gyro.x, gyro.y, gyro.z, acc.x, acc.y, acc.z + ); + } + + Ok(()) + } +} diff --git a/src/peripherals.rs b/src/peripherals.rs index f39d8fbc8..8234a5b61 100644 --- a/src/peripherals.rs +++ b/src/peripherals.rs @@ -3,11 +3,13 @@ use std::error::Error; pub enum Peripherals { Ads1115, // ADC Ak09915, // 3-axis magnetometer + Bmp180, // Pressure and Temperature Bmp280, // Pressure and Temperature Bmp390, // Pressure and Temperature Gpio, Icm20689, // Accelerometer and Gyroscope Leak, + Mpu6050, // Accelerometer, Gyroscope and Temperature Pca9685, // PWM controller Sk6812, // Neopixel RGB LED } From 70e251196162353bcbc7c6d3d4406e3aaaca46f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Fri, 27 Dec 2024 13:17:57 -0300 Subject: [PATCH 6/6] wip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- Cargo.toml | 1 + src/lib.rs | 2 ++ src/peripherals.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 1b0736cfa..e27305f22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ linux-embedded-hal = "0.4.0" log = "0.4.19" mpu6050 = { git = "https://github.com/patrickelectric/mpu6050", rev = "0fe2526" } nb = "1.1.0" +qmc5883l = { git = "https://github.com/patrickelectric/qmc5883l", ref = "62b8a64" } pwm-pca9685 = "1.0.0" sk6812_rpi = "0.1" diff --git a/src/lib.rs b/src/lib.rs index 7455752eb..8b2158c8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ mod led; mod mpu6050; mod pca9685; mod peripherals; +mod qmc5883l; mod rgb; use peripherals::*; @@ -29,6 +30,7 @@ use leak::LeakDetector; use led::LedController; use mpu6050::Mpu6050Device; use pca9685::Pca9685Device; +use qmc5883l::Qmc5883lDevice; use rgb::RgbController; // add docs ( difference btwen boards) diff --git a/src/peripherals.rs b/src/peripherals.rs index 8234a5b61..7478e5d19 100644 --- a/src/peripherals.rs +++ b/src/peripherals.rs @@ -9,8 +9,10 @@ pub enum Peripherals { Gpio, Icm20689, // Accelerometer and Gyroscope Leak, + Mmc5983, // 3-axis magnetometer and Temperature Mpu6050, // Accelerometer, Gyroscope and Temperature Pca9685, // PWM controller + Qmc5883l, // 3-axis magnetometer Sk6812, // Neopixel RGB LED }