Skip to content

Commit 70629b4

Browse files
committed
feat: add NC/NO pulse counting options
1 parent 6847744 commit 70629b4

File tree

2 files changed

+53
-21
lines changed

2 files changed

+53
-21
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
This project uses a Raspberry Pi Pico to identify and store various information
44
about a system/fixture, settable and retrievable over UART or USB. Additionally,
55
writing can be disabled by jumping GPIO pins 14 and 15 together (pins 19 and 20
6-
on the board), and GPIO 13 (pin 17 on the board) can be switched to GND and used
7-
as a pulse counter, such as for a fixture lid switch. This pin is active low and
8-
counts any low pulse longer than a minimum time period (configurable by with a
9-
CMake variable).
6+
on the board), and either GPIO 12 or 13 (pins 16 and 17 on the board) can be
7+
used as a pulse counter, such as for a fixture lid switch. Both of these pins
8+
are active low and affect the same count. However, GPIO 12 is for a normally
9+
open switch and GPIO 13 is for a normally closed switch. These pins count any
10+
pulse longer than a minimum time period (configurable with a CMake variable).
1011

1112
This project makes use of a Pi Pico and a MIKROE EEPROM 3 Click. The I2C lines
1213
for the EEPROM should be connected to GPIOs 16 (SDA) and 17 (SCL) (pins 21 and

src/main.cpp

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
/*
2727
* GPIO pins.
2828
*/
29-
#define PIN_SWITCH (13)
29+
#define PIN_SWITCH_NO (12)
30+
#define PIN_SWITCH_NC (13)
3031
#define PIN_WRLOCK_OUT (14)
3132
#define PIN_WRLOCK_IN (15)
3233
#define PIN_SDA (16)
@@ -286,12 +287,17 @@ int main(void) {
286287
// Make the I2C pins available to picotool.
287288
bi_decl(bi_2pins_with_func(PIN_SDA, PIN_SCL, GPIO_FUNC_I2C));
288289

289-
::gpio_init(PIN_SWITCH);
290-
::gpio_set_dir(PIN_SWITCH, GPIO_IN);
291-
::gpio_pull_up(PIN_SWITCH);
290+
::gpio_init(PIN_SWITCH_NO);
291+
::gpio_set_dir(PIN_SWITCH_NO, GPIO_IN);
292+
::gpio_pull_up(PIN_SWITCH_NO);
293+
::gpio_init(PIN_SWITCH_NC);
294+
::gpio_set_dir(PIN_SWITCH_NC, GPIO_IN);
295+
::gpio_pull_up(PIN_SWITCH_NC);
292296

293-
// Make the lid switch pin available to picotool.
294-
bi_decl(bi_1pin_with_name(PIN_SWITCH, "Lid switch (active low)"));
297+
// Make the lid switch pins available to picotool.
298+
bi_decl(bi_2pins_with_names(
299+
PIN_SWITCH_NO, "Lid switch (active low, normally open)",
300+
PIN_SWITCH_NC, "Lid switch (active low, normally closed)"));
295301

296302
// Load device info and make sure it's valid.
297303
LoadDeviceInfo();
@@ -305,32 +311,57 @@ int main(void) {
305311

306312
last_pulsecount = pulsecount;
307313

308-
static volatile ::absolute_time_t last_edge_time = ::nil_time;
309-
static volatile bool switch_state = ::gpio_get(PIN_SWITCH);
314+
static volatile ::absolute_time_t last_edge_time_nc = ::nil_time;
315+
static volatile ::absolute_time_t last_edge_time_no = ::nil_time;
316+
static volatile bool switch_state_nc = ::gpio_get(PIN_SWITCH_NC);
317+
static volatile bool switch_state_no = ::gpio_get(PIN_SWITCH_NO);
318+
// Note: the callback set for the NO pin here also applies to the NC pin, as
319+
// we are using the "easy" IRQ functionality and not actual raw IRQs.
320+
::gpio_set_irq_enabled(PIN_SWITCH_NC, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE,
321+
true);
310322
::gpio_set_irq_enabled_with_callback(
311-
PIN_SWITCH, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true,
312-
[](::uint, std::uint32_t) {
323+
PIN_SWITCH_NO, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true,
324+
[](::uint pin, std::uint32_t) {
313325
const auto now = ::get_absolute_time();
314326

327+
volatile ::absolute_time_t* p_last_edge_time;
328+
volatile bool* p_switch_state;
329+
bool pulse_count_state;
330+
switch (pin) {
331+
case PIN_SWITCH_NO:
332+
p_last_edge_time = &last_edge_time_no;
333+
p_switch_state = &switch_state_no;
334+
pulse_count_state = true;
335+
break;
336+
case PIN_SWITCH_NC:
337+
p_last_edge_time = &last_edge_time_nc;
338+
p_switch_state = &switch_state_nc;
339+
pulse_count_state = false;
340+
break;
341+
default:
342+
return; // ???
343+
}
344+
315345
// This is the first edge seen.
316-
if (::is_nil_time(last_edge_time)) [[unlikely]] {
317-
last_edge_time = now;
318-
switch_state = !switch_state;
346+
if (::is_nil_time(*p_last_edge_time)) [[unlikely]] {
347+
*p_last_edge_time = now;
348+
*p_switch_state = !*p_switch_state;
319349
return;
320350
}
321351

322-
const auto delta_t = ::absolute_time_diff_us(last_edge_time, now);
352+
const auto delta_t = ::absolute_time_diff_us(*p_last_edge_time, now);
323353
if (delta_t < SWITCH_DEBOUNCE_TIME_US) {
324354
return;
325355
}
326356

327-
switch_state = !switch_state;
357+
*p_switch_state = !*p_switch_state;
328358

329-
if (switch_state && delta_t >= MIN_PULSE_WIDTH_US) {
359+
if (*p_switch_state == pulse_count_state &&
360+
delta_t >= MIN_PULSE_WIDTH_US) {
330361
pulsecount = pulsecount + 1;
331362
}
332363

333-
last_edge_time = now;
364+
*p_last_edge_time = now;
334365
});
335366

336367
char rdbuf[512] = {0};

0 commit comments

Comments
 (0)