vexide_devices/adi/light_sensor.rs
1//! ADI Light Sensor
2//!
3//! The Light Sensor measures the intensity of visible light with a photoresistor.
4//!
5//! # Hardware Overview
6//!
7//! Using a Cadmium Sulfoselenide photoconductive photocell (CdS), the light sensor
8//! is able to adjust its resistance based on the amount of visible light shining on it.
9//!
10//! The light sensor only measures light in the visible spectrum. It cannot detect
11//! infrared or ultraviolet sources.
12//!
13//! # Effective Range
14//!
15//! Effective range is dependent on both the intensity of the source and the surrounding
16//! environment. Darker ambient surroundings with a brighter source will result in a
17//! greater effective range.
18//!
19//! That being said, the sensor generally has a usable range of up to 6 feet, meaning it
20//! can distinguish a light source from the surrounding ambient light at up to six feet
21//! away. Measurements farther than this might cause the sensor to return inconclusive
22//! results or blend into the ambient light.
23
24use vex_sdk::vexDeviceAdiValueGet;
25
26use super::{analog, AdiDevice, AdiDeviceType, AdiPort, PortError};
27
28/// Light Sensor
29#[derive(Debug, Eq, PartialEq)]
30pub struct AdiLightSensor {
31 port: AdiPort,
32}
33
34impl AdiLightSensor {
35 /// Create a light sensor on the given [`AdiPort`].
36 ///
37 /// # Examples
38 ///
39 /// ```
40 /// use vexide::prelude::*;
41 ///
42 /// #[vexide::main]
43 /// async fn main(peripherals: Peripherals) {
44 /// // Create a new light sensor on port 1
45 /// let sensor = AdiLightSensor::new(peripherals.port_1);
46 ///
47 /// // Get the brightness value
48 /// println!("Brightness value: {:?}", sensor.brightness());
49 /// }
50 /// ```
51 #[must_use]
52 pub fn new(port: AdiPort) -> Self {
53 port.configure(AdiDeviceType::LightSensor);
54
55 Self { port }
56 }
57
58 /// Returns the brightness factor measured by the sensor. Higher numbers mean
59 /// a brighter light source.
60 ///
61 /// This is returned as a value in the interval [0.0, 1.0].
62 ///
63 /// # Errors
64 ///
65 /// - A [`PortError::Disconnected`] error is returned if an ADI expander device was required but not connected.
66 /// - A [`PortError::IncorrectDevice`] error is returned if an ADI expander device was required but
67 /// something else was connected.
68 ///
69 /// # Examples
70 ///
71 /// ```
72 /// use vexide::prelude::*;
73 ///
74 /// #[vexide::main]
75 /// async fn main(peripherals: Peripherals) {
76 /// // Create a new light sensor on port 1
77 /// let sensor = AdiLightSensor::new(peripherals.port_1);
78 ///
79 /// // Get the brightness value
80 /// println!("Brightness value: {:?}", sensor.brightness());
81 /// }
82 /// ```
83 pub fn brightness(&self) -> Result<f64, PortError> {
84 Ok(f64::from(analog::ADC_MAX_VALUE - self.raw_brightness()?)
85 / f64::from(analog::ADC_MAX_VALUE))
86 }
87
88 /// Returns the 12-bit brightness reading of the sensor.
89 ///
90 /// This is a raw 12-bit value in the interval [0, 4095] representing the voltage level from
91 /// 0-5V measured by the V5 Brain's ADC.
92 ///
93 /// A low number (less voltage) represents a **brighter** light source.
94 ///
95 /// # Errors
96 ///
97 /// - A [`PortError::Disconnected`] error is returned if an ADI expander device was required but not connected.
98 /// - A [`PortError::IncorrectDevice`] error is returned if an ADI expander device was required but
99 /// something else was connected.
100 ///
101 /// # Examples
102 ///
103 /// ```
104 /// use vexide::prelude::*;
105 ///
106 /// #[vexide::main]
107 /// async fn main(peripherals: Peripherals) {
108 /// // Create a new light sensor on port 1
109 /// let sensor = AdiLightSensor::new(peripherals.port_1);
110 ///
111 /// // Get the brightness value
112 /// println!("Raw 12-bit brightness value: {:?}", sensor.raw_brightness());
113 /// }
114 /// ```
115 pub fn raw_brightness(&self) -> Result<u16, PortError> {
116 self.port.validate_expander()?;
117
118 Ok(unsafe { vexDeviceAdiValueGet(self.port.device_handle(), self.port.index()) } as u16)
119 }
120}
121
122impl AdiDevice<1> for AdiLightSensor {
123 fn port_numbers(&self) -> [u8; 1] {
124 [self.port.number()]
125 }
126
127 fn expander_port_number(&self) -> Option<u8> {
128 self.port.expander_number()
129 }
130
131 fn device_type(&self) -> AdiDeviceType {
132 AdiDeviceType::LightSensor
133 }
134}