aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32f3/src
diff options
context:
space:
mode:
authormichel <[email protected]>2024-08-07 21:58:49 +0200
committermichel <[email protected]>2024-11-29 17:58:33 +0100
commit721c6820d4a6e3bbf2546997205a32975e6bad8b (patch)
treef725e1f66b0b7f40a3b663f355c2b1d5d389af06 /examples/stm32f3/src
parent1a1d5c4689a8b6c57ebb74e99fdea8df39adb037 (diff)
STM32-TSC: enable discriminating between pins within same TSC group and improve TSC library in general
Diffstat (limited to 'examples/stm32f3/src')
-rw-r--r--examples/stm32f3/src/bin/blocking-tsc.rs98
-rw-r--r--examples/stm32f3/src/bin/tsc_blocking.rs138
2 files changed, 138 insertions, 98 deletions
diff --git a/examples/stm32f3/src/bin/blocking-tsc.rs b/examples/stm32f3/src/bin/blocking-tsc.rs
deleted file mode 100644
index 5c8dac94f..000000000
--- a/examples/stm32f3/src/bin/blocking-tsc.rs
+++ /dev/null
@@ -1,98 +0,0 @@
1// Example of polling TSC (Touch Sensing Controller) that lights an LED when touch is detected.
2//
3// Suggested physical setup on STM32F303ZE Nucleo board:
4// - Connect a 1000pF capacitor between pin A0 and GND. This is your sampling capacitor.
5// - Connect one end of a 1K resistor to pin A1 and leave the other end loose.
6// The loose end will act as touch sensor which will register your touch.
7//
8// Troubleshooting the setup:
9// - If no touch seems to be registered, then try to disconnect the sampling capacitor from GND momentarily,
10// now the led should light up. Next try using a different value for the sampling capacitor.
11// Also experiment with increasing the values for `ct_pulse_high_length`, `ct_pulse_low_length`, `pulse_generator_prescaler`, `max_count_value` and `discharge_delay`.
12//
13// All configuration values and sampling capacitor value have been determined experimentally.
14// Suitable configuration and discharge delay values are highly dependent on the value of the sample capacitor. For example, a shorter discharge delay can be used with smaller capacitor values.
15//
16#![no_std]
17#![no_main]
18
19use defmt::*;
20use embassy_stm32::gpio::{Level, Output, Speed};
21use embassy_stm32::tsc::{self, *};
22use embassy_time::Timer;
23use {defmt_rtt as _, panic_probe as _};
24
25/// This example is written for the nucleo-stm32f303ze, with a stm32f303ze chip.
26///
27/// Make sure you check/update the following (whether you use the F303ZE or another board):
28///
29/// * [ ] Update .cargo/config.toml with the correct `probe-rs run --chip STM32F303ZETx`chip name.
30/// * [ ] Update Cargo.toml to have the correct `embassy-stm32` feature, for F303ZE it should be `stm32f303ze`.
31/// * [ ] If your board has a special clock or power configuration, make sure that it is
32/// set up appropriately.
33/// * [ ] If your board has different pin mapping, update any pin numbers or peripherals
34/// to match your schematic
35///
36/// If you are unsure, please drop by the Embassy Matrix chat for support, and let us know:
37///
38/// * Which example you are trying to run
39/// * Which chip and board you are using
40///
41/// Embassy Chat: https://matrix.to/#/#embassy-rs:matrix.org
42#[embassy_executor::main]
43async fn main(_spawner: embassy_executor::Spawner) {
44 let device_config = embassy_stm32::Config::default();
45 let context = embassy_stm32::init(device_config);
46
47 let tsc_conf = Config {
48 ct_pulse_high_length: ChargeTransferPulseCycle::_8,
49 ct_pulse_low_length: ChargeTransferPulseCycle::_8,
50 spread_spectrum: false,
51 spread_spectrum_deviation: SSDeviation::new(2).unwrap(),
52 spread_spectrum_prescaler: false,
53 pulse_generator_prescaler: PGPrescalerDivider::_32,
54 max_count_value: MaxCount::_255,
55 io_default_mode: false,
56 synchro_pin_polarity: false,
57 acquisition_mode: false,
58 max_count_interrupt: false,
59 channel_ios: TscIOPin::Group1Io1.into(),
60 shield_ios: 0, // no shield
61 sampling_ios: TscIOPin::Group1Io2.into(),
62 };
63
64 let mut g1: PinGroup<embassy_stm32::peripherals::TSC, G1> = PinGroup::new();
65 g1.set_io1(context.PA0, PinType::Sample);
66 g1.set_io2(context.PA1, PinType::Channel);
67
68 let mut touch_controller = tsc::Tsc::new_blocking(context.TSC, Some(g1), None, None, None, None, None, tsc_conf);
69
70 // LED2 on the STM32F303ZE nucleo-board
71 let mut led = Output::new(context.PB7, Level::High, Speed::Low);
72
73 // smaller sample capacitor discharge faster and can be used with shorter delay.
74 let discharge_delay = 5; // ms
75
76 // the interval at which the loop polls for new touch sensor values
77 let polling_interval = 100; // ms
78
79 info!("polling for touch");
80 loop {
81 touch_controller.start();
82 touch_controller.poll_for_acquisition();
83 touch_controller.discharge_io(true);
84 Timer::after_millis(discharge_delay).await;
85
86 let grp1_status = touch_controller.group_get_status(Group::One);
87 match grp1_status {
88 GroupStatus::Complete => {
89 let group_one_val = touch_controller.group_get_value(Group::One);
90 info!("{}", group_one_val);
91 led.set_high();
92 }
93 GroupStatus::Ongoing => led.set_low(),
94 }
95
96 Timer::after_millis(polling_interval).await;
97 }
98}
diff --git a/examples/stm32f3/src/bin/tsc_blocking.rs b/examples/stm32f3/src/bin/tsc_blocking.rs
new file mode 100644
index 000000000..fa7f718e6
--- /dev/null
+++ b/examples/stm32f3/src/bin/tsc_blocking.rs
@@ -0,0 +1,138 @@
1// Example of blocking TSC (Touch Sensing Controller) that lights an LED when touch is detected.
2//
3// This example demonstrates:
4// 1. Configuring a single TSC channel pin
5// 2. Using the blocking TSC interface with polling
6// 3. Waiting for acquisition completion using `poll_for_acquisition`
7// 4. Reading touch values and controlling an LED based on the results
8//
9// Suggested physical setup on STM32F303ZE Nucleo board:
10// - Connect a 1000pF capacitor between pin PA10 and GND. This is your sampling capacitor.
11// - Connect one end of a 1K resistor to pin PA9 and leave the other end loose.
12// The loose end will act as the touch sensor which will register your touch.
13//
14// The example uses two pins from Group 4 of the TSC:
15// - PA10 as the sampling capacitor, TSC group 4 IO2 (D68 on the STM32F303ZE nucleo-board)
16// - PA9 as the channel pin, TSC group 4 IO1 (D69 on the STM32F303ZE nucleo-board)
17//
18// The program continuously reads the touch sensor value:
19// - It starts acquisition, waits for completion using `poll_for_acquisition`, and reads the value.
20// - The LED is turned on when touch is detected (sensor value < 40).
21// - Touch values are logged to the console.
22//
23// Troubleshooting:
24// - If touch is not detected, try adjusting the SENSOR_THRESHOLD value.
25// - Experiment with different values for ct_pulse_high_length, ct_pulse_low_length,
26// pulse_generator_prescaler, max_count_value, and discharge_delay to optimize sensitivity.
27//
28// Note: Configuration values and sampling capacitor value have been determined experimentally.
29// Optimal values may vary based on your specific hardware setup.
30// Pins have been chosen for their convenient locations on the STM32F303ZE board. Refer to the
31// official relevant STM32 datasheets and user nucleo-board user manuals to find suitable
32// alternative pins.
33
34#![no_std]
35#![no_main]
36
37use defmt::*;
38use embassy_stm32::gpio::{Level, Output, Speed};
39use embassy_stm32::tsc::{self, *};
40use embassy_stm32::{mode, peripherals};
41use embassy_time::Timer;
42use {defmt_rtt as _, panic_probe as _};
43
44const SENSOR_THRESHOLD: u16 = 25; // Adjust this value based on your setup
45
46#[embassy_executor::main]
47async fn main(_spawner: embassy_executor::Spawner) {
48 let device_config = embassy_stm32::Config::default();
49 let context = embassy_stm32::init(device_config);
50
51 let tsc_conf = Config {
52 ct_pulse_high_length: ChargeTransferPulseCycle::_4,
53 ct_pulse_low_length: ChargeTransferPulseCycle::_4,
54 spread_spectrum: false,
55 spread_spectrum_deviation: SSDeviation::new(2).unwrap(),
56 spread_spectrum_prescaler: false,
57 pulse_generator_prescaler: PGPrescalerDivider::_16,
58 max_count_value: MaxCount::_255,
59 io_default_mode: false,
60 synchro_pin_polarity: false,
61 acquisition_mode: false,
62 max_count_interrupt: false,
63 };
64
65 let mut g: PinGroupWithRoles<peripherals::TSC, G4> = PinGroupWithRoles::default();
66 // D68 on the STM32F303ZE nucleo-board
67 g.set_io2::<tsc_pin_roles::Sample>(context.PA10);
68 // D69 on the STM32F303ZE nucleo-board
69 let tsc_sensor = g.set_io1::<tsc_pin_roles::Channel>(context.PA9);
70
71 let pin_groups: PinGroups<peripherals::TSC> = PinGroups {
72 g4: Some(g.pin_group),
73 ..Default::default()
74 };
75
76 let mut touch_controller = tsc::Tsc::new_blocking(context.TSC, pin_groups, tsc_conf).unwrap();
77
78 // Check if TSC is ready
79 if touch_controller.get_state() != State::Ready {
80 crate::panic!("TSC not ready!");
81 }
82 info!("TSC initialized successfully");
83
84 // LED2 on the STM32F303ZE nucleo-board
85 let mut led = Output::new(context.PB7, Level::High, Speed::Low);
86
87 // smaller sample capacitor discharge faster and can be used with shorter delay.
88 let discharge_delay = 5; // ms
89
90 // the interval at which the loop polls for new touch sensor values
91 let polling_interval = 100; // ms
92
93 info!("polling for touch");
94 loop {
95 touch_controller.set_active_channels_mask(tsc_sensor.pin.into());
96 touch_controller.start();
97 touch_controller.poll_for_acquisition();
98 touch_controller.discharge_io(true);
99 Timer::after_millis(discharge_delay).await;
100
101 match read_touch_value(&mut touch_controller, tsc_sensor.pin).await {
102 Some(v) => {
103 info!("sensor value {}", v);
104 if v < SENSOR_THRESHOLD {
105 led.set_high();
106 } else {
107 led.set_low();
108 }
109 }
110 None => led.set_low(),
111 }
112
113 Timer::after_millis(polling_interval).await;
114 }
115}
116
117const MAX_GROUP_STATUS_READ_ATTEMPTS: usize = 10;
118
119// attempt to read group status and delay when still ongoing
120async fn read_touch_value(
121 touch_controller: &mut tsc::Tsc<'_, peripherals::TSC, mode::Blocking>,
122 sensor_pin: TscIOPin,
123) -> Option<u16> {
124 for _ in 0..MAX_GROUP_STATUS_READ_ATTEMPTS {
125 match touch_controller.group_get_status(sensor_pin.group()) {
126 GroupStatus::Complete => {
127 return Some(touch_controller.group_get_value(sensor_pin.group()));
128 }
129 GroupStatus::Ongoing => {
130 // if you end up here a lot, then you prob need to increase discharge_delay
131 // or consider changing the code to adjust the discharge_delay dynamically
132 info!("Acquisition still ongoing");
133 Timer::after_millis(1).await;
134 }
135 }
136 }
137 None
138}