Comments (7)
I tried using the actual driver type, switching from linux to no std, etc. I have
type Adc = Ads1x1x<I2cInterface<BlockingI2c<I2C2, impl Pins<I2C2>>>, Ads1015, Resolution16Bit, ads1x1x::mode::OneShot>;
but then I get
`impl Trait` in type aliases is unstable
and it looks downhill from there. I guess I have to spell out the whole concrete type for every hal. I have a reasonable work around just leaving that one read in the main loop ( I just have to disambiguate), so I think I will leave it like that until there is an easy way to make it clean.
from ads1x1x-rs.
If you split read_adc()
into two functions so that you can change the FSR outside of it, you could have two functions that simply take the ADC as an embedded_hal::adc::OneShot
trait.
Would that be a solution for you?
from ads1x1x-rs.
Yes, this would work. But now I'm stuck trying to figure out the type arguments
error[E0107]: wrong number of type arguments: expected 3, found 0
--> examples/zz.rs:64:27
|
64 | fn read_adc_a(adc_a: impl embedded_hal::adc::OneShot) -> (i16, i16, i16) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 3 type arguments
(I expect there should be an easy way to find type arguments in documentation or compiler error messages, but I have not figure it out.)
from ads1x1x-rs.
Ah, that solution I proposed cannot work because the OneShot
trait is channel-specific and you want to pass the whole ADC and measure several channels inside the function.
You can use your function as initially proposed if you define the concrete types of the ADC.
An example of doing this is in this example.
You will only need to replace I2cdev
with something like BlockingI2c<I2C2, ...>
although putting the pin types there will bloat the type up a bit.
I have a look at adding a trait to simplify this.
from ads1x1x-rs.
I have added the DynamicOneShot
trait to ease the usage in functions in release 0.2.2
. See this example.
Closing.
from ads1x1x-rs.
Thanks for adding this trait
. It works well except when I try to use the method .set_full_scale_range
in the read
function. (I do this because I am measuring a voltage across a shunt resistor and also to ground.) I'm not sure if I just don't have the proper syntax figured out, I am a newbie still, or if there is a problem de-referencing the method. I have tried various syntax without luck:
113 | adc_a.set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
| ^^^^^^^^^^^^^^^^^^^^ method not found in `&mut A`
113 | *adc_a.set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
| ^^^^^^^^^^^^^^^^^^^^ method not found in `&mut A`
113 | (*adc_a).set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
| ^^^^^^^^^^^^^^^^^^^^ method not found in `A`
A stripped down version of the code follows.
Click to expand
// setup for bluepill stm32f1xx_hal
#![deny(unsafe_code)]
#![no_std]
#![no_main]
#[cfg(debug_assertions)]
use panic_semihosting as _;
#[cfg(not(debug_assertions))]
use panic_halt as _;
use cortex_m_rt::entry;
use ads1x1x::{Ads1x1x, ChannelSelection, DynamicOneShot, FullScaleRange, SlaveAddr};
use core::fmt::Write;
use embedded_graphics::{
mono_font::{ascii::FONT_8X13, MonoTextStyle, MonoTextStyleBuilder}, //FONT_6X10 FONT_8X13
pixelcolor::BinaryColor,
prelude::*,
text::{Baseline, Text},
};
use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};
use nb::block;
pub trait LED {
fn on(&mut self) -> ();
fn off(&mut self) -> ();
// default methods
fn blink(&mut self, time: u16, delay: &mut Delay) -> () {
self.on();
delay.delay_ms(time);
self.off()
}
}
use stm32f1xx_hal::{
delay::Delay,
device::I2C2,
gpio::{gpioc::PC13, Output, PushPull},
i2c::{BlockingI2c, DutyCycle, Mode, Pins},
pac::{CorePeripherals, Peripherals},
prelude::*,
};
fn setup() -> (BlockingI2c<I2C2, impl Pins<I2C2>>, impl LED, Delay) {
let cp = CorePeripherals::take().unwrap();
let p = Peripherals::take().unwrap();
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut p.FLASH.constrain().acr);
let mut gpiob = p.GPIOB.split(); // for i2c scl and sda
let i2c = BlockingI2c::i2c2(
p.I2C2,
(
gpiob.pb10.into_alternate_open_drain(&mut gpiob.crh), // scl on PB10
gpiob.pb11.into_alternate_open_drain(&mut gpiob.crh), // sda on PB11
),
Mode::Fast {
frequency: 100_000.hz(),
duty_cycle: DutyCycle::Ratio2to1,
},
clocks,
1000,
10,
1000,
1000,
);
let delay = Delay::new(cp.SYST, clocks);
// led
let mut gpioc = p.GPIOC.split();
let led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); // led on pc13
impl LED for PC13<Output<PushPull>> {
fn on(&mut self) -> () {
self.set_low()
}
fn off(&mut self) -> () {
self.set_high()
}
}
(i2c, led, delay)
}
pub fn read_all<E, A: DynamicOneShot<Error = E>>(adc_a: &mut A, adc_b: &mut A
) -> (i16, i16, i16, i16, [i16; 3]) {
let scale_cur = 10; // calibrated to get mA/mV depends on FullScaleRange above and values of shunt resistors
let scale_a = 2; // calibrated to get mV depends on FullScaleRange
let scale_b = 2; // calibrated to get mV depends on FullScaleRange
let scale_temp = 5; //divides
let offset_temp = 50;
let bat_ma = block!(adc_a.read(ChannelSelection::DifferentialA1A3)).unwrap_or(8091) / scale_cur;
let load_ma = block!(adc_a.read(ChannelSelection::DifferentialA2A3)).unwrap_or(8091) / scale_cur;
// toggle FullScaleRange to measure battery voltage, not just diff across shunt resistor
// set FullScaleRange to measure expected max voltage.
// This is very small for diff across low value shunt resistors
// but up to 5v for single pin with usb power.
// +- 6.144v , 4.096v, 2.048v, 1.024v, 0.512v, 0.256v
adc_a.set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
let bat_mv = block!(adc_a.read(ChannelSelection::SingleA0)).unwrap_or(8091) * scale_a;
adc_a.set_full_scale_range(FullScaleRange::Within0_256V).unwrap();
// second adc
let values_b = [
block!(adc_b.read(ChannelSelection::SingleA0)).unwrap_or(8091) * scale_b,
block!(adc_b.read(ChannelSelection::SingleA1)).unwrap_or(8091) * scale_b,
block!(adc_b.read(ChannelSelection::SingleA2)).unwrap_or(8091) * scale_b,
];
let temp_c = block!(adc_b.read(ChannelSelection::SingleA3)).unwrap_or(8091) / scale_temp
- offset_temp;
(bat_mv, bat_ma, load_ma, temp_c, values_b )
}
fn display<S>(
bat_mv: i16,
bat_ma: i16,
load_ma: i16,
temp_c: i16,
values_b: [i16; 3],
text_style: MonoTextStyle<BinaryColor>,
disp: &mut Ssd1306<impl WriteOnlyDataCommand, S, BufferedGraphicsMode<S>>,
) -> ()
where
S: DisplaySize,
{
let mut lines: [heapless::String<32>; 4] = [
heapless::String::new(),
heapless::String::new(),
heapless::String::new(),
heapless::String::new(),
];
// Many SSD1306 modules have a yellow strip at the top of the display, so first line may be yellow.
// it is now possible to use \n in place of separate writes, with one line rather than vector.
write!(lines[0], "bat:{:4}mV{:4}mA", bat_mv, bat_ma).unwrap();
write!(lines[1], "load: {:5}mA", load_ma).unwrap();
write!(
lines[2],
"B:{:4} {:4} {:4}",
values_b[0], values_b[1], values_b[2]
)
.unwrap();
write!(lines[3], "temperature{:3} C", temp_c).unwrap();
disp.clear();
for i in 0..lines.len() {
// start from 0 requires that the top is used for font baseline
Text::with_baseline(
&lines[i],
Point::new(0, i as i32 * 16),
text_style,
Baseline::Top,
)
.draw(&mut *disp)
.unwrap();
}
disp.flush().unwrap();
()
}
#[entry]
fn main() -> ! {
let (i2c, mut led, mut delay) = setup();
let manager = shared_bus::BusManager::<cortex_m::interrupt::Mutex<_>, _>::new(i2c);
let interface = I2CDisplayInterface::new(manager.acquire());
let mut disp = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
disp.init().unwrap();
let text_style = MonoTextStyleBuilder::new()
.font(&FONT_8X13) //.&FONT_6X10 &FONT_8X13
.text_color(BinaryColor::On)
.build();
Text::with_baseline("Display initialized ...", Point::zero(), text_style, Baseline::Top)
.draw(&mut disp)
.unwrap();
let mut adc_a = Ads1x1x::new_ads1015(manager.acquire(), SlaveAddr::Alternative(false, false)); //addr = GND
let mut adc_b = Ads1x1x::new_ads1015(manager.acquire(), SlaveAddr::Alternative(false, true)); //addr = V
adc_a.set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
adc_b.set_full_scale_range(FullScaleRange::Within4_096V).unwrap();
loop {
// Blink LED to check that everything is actually running.
led.blink(10_u16, &mut delay);
let (bat_mv, bat_ma, load_ma, temp_c, values_b ) = read_all(&mut adc_a, &mut adc_b);
display(bat_mv, bat_ma, load_ma, temp_c, values_b, text_style, &mut disp);
delay.delay_ms(2000_u16); // sleep for 2s
}
}
from ads1x1x-rs.
Ah, I forgot about that. Could you just use the actual driver type then, instead of this trait?
You just need to use the concrete type (Depending on your IDE, it might help you there) like here
Then you can use it easily in a function like here
I would start with adc_a
only.
from ads1x1x-rs.
Related Issues (13)
- Docs and crates invalid link? HOT 2
- Example across function / struct boundary HOT 1
- Setting the address HOT 2
- ADS1115 read return always 32767 HOT 3
- toggling FullScaleRange? HOT 2
- Example for STM32F4 HOT 1
- ADS1119 support? HOT 5
- How to improve reading speed. HOT 1
- Interest in supporting `async`? HOT 4
- `Ads1015` and `Resolution12Bit` need to be public HOT 1
- Release to crates.io to allow embedded-hal 1.0 compat HOT 1
- The `use_alert_rdy_pin_as_ready` does not enable pulse in continuous-conversion mode as documented HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ads1x1x-rs.