embassy_rp_gl5528/lib.rs
1// Copyright (C) 2026 Jorge Andre Castro
2// GPL-2.0-or-later
3//! # embassy-rp-gl5528
4//!
5//! Driver async `no_std` minimaliste pour la photorésistance **GL5528** (LDR)
6//! sur microcontrôleur RP2040 et RP235x, basé sur le framework [Embassy](https://embassy.dev).
7//!
8//! ## Description du composant
9//!
10//! La GL5528 est une photorésistance (LDR — *Light Dependent Resistor*) dont la
11//! résistance varie entre ~1 kΩ (forte lumière) et ~10 MΩ (obscurité totale).
12//! Elle est typiquement utilisée dans un diviseur de tension avec une résistance
13//! fixe (10 kΩ recommandée) pour convertir la variation de résistance en tension
14//! lisible par un ADC.
15//!
16//! ## Schéma de câblage
17//!
18//! ```text
19//! 3.3V
20//! │
21//! [GL5528]
22//! │
23//! ├──── GP26 (ADC0)
24//! │
25//! [R 10kΩ]
26//! │
27//! GND
28//! ```
29//!
30//! La tension sur la broche ADC augmente avec la luminosité (la GL5528 devient
31//! moins résistante, le point milieu monte vers 3,3 V).
32//!
33//! ## Exemple d'utilisation
34//!
35//! ```rust,no_run
36//! #![no_std]
37//! #![no_main]
38//!
39//! use embassy_executor::Spawner;
40//! use embassy_rp::adc::{Adc, Channel, Config as AdcConfig};
41//! use embassy_rp::bind_interrupts;
42//! use embassy_rp::peripherals::ADC;
43//! use embassy_rp::adc::InterruptHandler;
44//! use embassy_rp_gl5528::Gl5528;
45//!
46//! bind_interrupts!(struct Irqs {
47//! ADC_IRQ_FIFO => InterruptHandler;
48//! });
49//!
50//! #[embassy_executor::main]
51//! async fn main(_spawner: Spawner) {
52//! let p = embassy_rp::init(Default::default());
53//!
54//! let adc = Adc::new(p.ADC, Irqs, AdcConfig::default());
55//! let channel = Channel::new_pin(p.PIN_26, embassy_rp::gpio::Pull::None);
56//!
57//! let mut sensor = Gl5528::new(adc, channel);
58//!
59//! loop {
60//! let raw = sensor.read_raw().await;
61//! // Valeur entre 0 (obscurité) et 4095 (pleine lumière sur 12 bits)
62//! let _ = raw;
63//! }
64//! }
65//! ```
66//!
67//! ## Calcul de luminosité
68//!
69//! La valeur brute ADC peut être convertie en tension (ex: 12 bits sur RP2040, 14 bits sur RP235x) ::
70//!
71//! ```text
72//! V = raw × 3.3 / MAX (4095 ou 16383)
73//! ```
74//!
75//! La résistance de la LDR s'en déduit (diviseur de tension, R_pull = 10 kΩ) :
76//!
77//! ```text
78//! R_ldr = R_pull × V / (3.3 - V)
79//! ```
80//!
81//! ## Caractéristiques
82//!
83//! | Paramètre | Valeur |
84//! |------------------------|-------------------------------------- |
85//! | Tension d'alimentation | 3,3 V (RP2040 / RP235x) |
86//! | Résolution ADC | 12 bits (0–4095) et 14 bits sur RP235x|
87//! | Résistance lumière | ~1 kΩ @ 10 lux |
88//! | Résistance obscurité | ~1 MΩ minimum |
89//! | Résistance de tirage | 10 kΩ recommandée |
90//!
91//! ## `no_std`
92//!
93//! Cette crate ne dépend pas de la bibliothèque standard et est conçue pour
94//! tourner sur des microcontrôleurs bare-metal avec le runtime Embassy.
95
96#![no_std]
97#![forbid(unsafe_code)]
98
99use embassy_rp::adc::{Adc, Async, Channel};
100
101/// Driver pour la photorésistance GL5528 via l'ADC du RP2040.
102///
103/// Ce driver encapsule un canal ADC Embassy et fournit une lecture asynchrone
104/// de la valeur brute du capteur.
105///
106/// # Exemple
107///
108/// ```rust,no_run
109/// # use embassy_rp::adc::{Adc, Channel};
110/// # use embassy_rp_gl5528::Gl5528;
111/// // Création du driver (adc et channel obtenus depuis les périphériques Embassy)
112/// // let mut sensor = Gl5528::new(adc, channel);
113/// // let raw: u16 = sensor.read_raw().await;
114/// ```
115pub struct Gl5528<'d> {
116 adc: Adc<'d, Async>,
117 channel: Channel<'d>,
118}
119
120impl<'d> Gl5528<'d> {
121 /// Crée une nouvelle instance du driver GL5528.
122 ///
123 /// # Arguments
124 ///
125 /// * `adc` — Périphérique ADC Embassy en mode asynchrone.
126 /// * `channel` — Canal ADC connecté à la broche de lecture de la GL5528.
127 ///
128 /// # Exemple
129 ///
130 /// ```rust,no_run
131 /// # use embassy_rp::adc::{Adc, Channel, Config as AdcConfig};
132 /// # use embassy_rp_gl5528::Gl5528;
133 /// // let adc = Adc::new(p.ADC, Irqs, AdcConfig::default());
134 /// // let channel = Channel::new_pin(p.PIN_26, embassy_rp::gpio::Pull::None);
135 /// // let sensor = Gl5528::new(adc, channel);
136 /// ```
137 #[inline]
138 pub fn new(adc: Adc<'d, Async>, channel: Channel<'d>) -> Self {
139 Self { adc, channel }
140 }
141
142 /// Lit la valeur brute du convertisseur ADC.
143 ///
144 /// Retourne la valeur brute lue (ex: `0..=4095` sur RP2040 ou `0..=16383` sur RP235x).
145 /// Une valeur élevée correspond à une forte luminosité.
146 ///
147 /// En cas d'erreur ADC, la valeur `0` est retournée.
148 ///
149 /// # Retour
150 ///
151 ///* u16 — Valeur ADC brute (le maximum dépend de la puce : 4095 ou 16383).
152 ///
153 /// # Exemple
154 ///
155 /// ```rust,no_run
156 /// # use embassy_rp_gl5528::Gl5528;
157 /// # async fn example(mut sensor: Gl5528<'_>) {
158 /// let raw: u16 = sensor.read_raw().await;
159 ///
160 /// // Conversion en tension (V)
161 /// let voltage = raw as f32 * 3.3 / 4095.0; // Utiliser 16383.0 sur RP235x
162 ///
163 /// // Conversion en résistance LDR (kΩ), avec R_pull = 10 kΩ
164 /// if voltage < 3.3 {
165 /// // Si LDR est au 3.3V et R_pull (10k) au GND :
166 /// let r_ldr = 10.0 * (3.3 - voltage) / voltage;
167 /// let _ = r_ldr;
168 /// }
169 /// # }
170 /// ```
171
172 #[inline]
173 pub async fn read_raw(&mut self) -> u16 {
174 self.adc.read(&mut self.channel).await.unwrap_or(0)
175 }
176}