/
opt3001-als-display-bp.rs
117 lines (103 loc) · 3.23 KB
/
opt3001-als-display-bp.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//! Continuously measure the ambient light sensor data with an OPT3001
//! and print it to an SSD1306 OLED display in lux.
//!
//! Introductory blog post with some pictures here:
//! https://blog.eldruin.com/opt300x-ambient-light-sensor-driver-in-rust/
//!
//! This example is runs on the STM32F103 "Bluepill" board using I2C1.
//!
//! ```
//! BP <-> OPT3001 <-> Display
//! GND <-> GND <-> GND
//! 3.3V <-> VCC <-> VDD
//! PB8 <-> SCL <-> SCL
//! PB9 <-> SDA <-> SDA
//! ```
//!
//! Run with:
//! `cargo embed --example opt3001-als-display-bp --release`
#![deny(unsafe_code)]
#![no_std]
#![no_main]
use core::fmt::Write;
use cortex_m_rt::entry;
use embedded_graphics::{
fonts::{Font6x8, Text},
pixelcolor::BinaryColor,
prelude::*,
style::TextStyleBuilder,
};
use nb::block;
use opt300x::{Measurement, Opt300x, SlaveAddr, Status};
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use ssd1306::{prelude::*, Builder, I2CDIBuilder};
use stm32f1xx_hal::{
delay::Delay,
i2c::{BlockingI2c, DutyCycle, Mode},
pac,
prelude::*,
};
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("OPT3001 example");
let cp = cortex_m::Peripherals::take().unwrap();
let dp = pac::Peripherals::take().unwrap();
let mut flash = dp.FLASH.constrain();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut afio = dp.AFIO.constrain();
let mut gpiob = dp.GPIOB.split();
let scl = gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh);
let sda = gpiob.pb9.into_alternate_open_drain(&mut gpiob.crh);
let i2c = BlockingI2c::i2c1(
dp.I2C1,
(scl, sda),
&mut afio.mapr,
Mode::Fast {
frequency: 100_000.hz(),
duty_cycle: DutyCycle::Ratio2to1,
},
clocks,
1000,
10,
1000,
1000,
);
let mut gpioc = dp.GPIOC.split();
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
let mut delay = Delay::new(cp.SYST, clocks);
let manager = shared_bus::BusManagerSimple::new(i2c);
let interface = I2CDIBuilder::new().init(manager.acquire_i2c());
let mut disp: GraphicsMode<_> = Builder::new().connect(interface).into();
disp.init().unwrap();
disp.flush().unwrap();
let text_style = TextStyleBuilder::new(Font6x8)
.text_color(BinaryColor::On)
.build();
let mut sensor =
Opt300x::new_opt3001(manager.acquire_i2c(), SlaveAddr::Alternative(false, false));
let mut buffer: heapless::String<64> = heapless::String::new();
loop {
// Blink LED 0 to check that everything is actually running.
// If the LED 0 is off, something went wrong.
led.set_high();
delay.delay_ms(50_u16);
led.set_low();
delay.delay_ms(50_u16);
let def = Measurement {
result: 999.9,
status: Status::default(),
};
let m = block!(sensor.read_lux()).unwrap_or(def);
buffer.clear();
write!(buffer, "lux: {:.2}", m.result).unwrap();
disp.clear();
Text::new(&buffer, Point::zero())
.into_styled(text_style)
.draw(&mut disp)
.unwrap();
disp.flush().unwrap();
}
}