How does the espressif SDK handle inputs?
This article is part of a series.
- Part 1: Can I program a an ESP32C6 with the esp-idf?
- Part 2: Can I program an ESP32C6 with the Swift example code?
- Part 3: This Article
- Part 4: How does the espressif SDK handle wifi?
- Part 5: Can I combine an LED and a button on the ESP32C6 with Swift?
- Part 6: Can I add Wifi to the ESP32C6 project with Swift?
- Part 7: Can I make a Swift-wrapped HTTP GET request from the ESP32C6?
So even though my target is writing as much as possible in Swift, my process will be to make things work in C first.
The next simple step is to check how to add a digital input pin.
Here are the docs I used:
- https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32c6/api-reference/peripherals/gpio.html
- https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf#iomuxgpio (7.4.1)
Here are the examples I mainly looked at (not to be confused with the sleep examples in OpenThread directory). Most of these inputs were interrupt enabled, which I will likely use later but did not in this example.
- https://github.com/espressif/esp-idf/tree/v5.5.1/examples/peripherals/gpio/generic_gpio
- https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/light_sleep
- https://github.com/espressif/esp-idf/tree/v5.5.1/examples/system/deep_sleep
This was the resulting project:
Peculiarities of Using the Boot Button
Adding a basic input button has pretty much the same steps no matter the chip.
- the micro has to know the pin will be an input
- the micro has to know if internal hardware (pullups, pull downs) are being used
Given chips and given pins on those chips might have some specialty behaviors, but those are the two biggies.
On the ESP32-C6 GPIO 9 is one of the so-called “strapping” pins, pins that are associated with telling the micro what boot mode to be in.
From the technical reference manual (9.2.1) the default configuration of GPIO9 will be to have it’s internal pull up enabled.
By default, GPIO9 is connected to the chip’s internal pull-up resistor. If GPIO9 is not connected or is connected to an external high-impedance circuit, the internal weak pull-up determines the default input level of this strapping pin (see Table 9.2-1).
The manual continues in section 9.2.2:
The values of GPIO8 and GPIO9 at reset determine the boot mode after the reset is released. Table 9.2-2 shows the strapping pin values of GPIO8 and GPIO9, and the associated boot modes. (x: this value is ignored.)
Boot Mode | GPIO9 | GPIO8 |
---|---|---|
SPI Boot | 1 | x |
Download Boot | 0 | 1 |
We can see on the Xiao’s schematic (labeled net BOOT)that Seeed has attached the appropriate active low switch so that GPIO9 stays high by default.
This all means that when using pin 9 failing to set the internal pull up resistor won’t be a big deal because it will be set for us. It also means that the boot switch must be active low if we don’t want to change the expected default boot behaviors.
The ESP32-C6 SDK offers a handy command gpio_dump_io_configuration
to print out the current pin, as discussed in the API reference.
It looks like:
================IO DUMP Start================
IO[9] -
Pullup: 1, Pulldown: 0, DriveCap: 2
InputEn: 1, OutputEn: 0, OpenDrain: 0
FuncSel: 0 (IOMUX)
SleepSelEn: 1
IO[15] -
Pullup: 1, Pulldown: 0, DriveCap: 2
InputEn: 0, OutputEn: 1, OpenDrain: 0
FuncSel: 1 (GPIO)
GPIO Matrix SigOut ID: 128 (simple GPIO output)
SleepSelEn: 1
=================IO DUMP End=================
Example Code
// Needed for logging to serial monitor
// with TAG prefix
#include <stdio.h>
#include "esp_log.h"
// Needed for portTICK_PERIOD_MS
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// Needed for io pins
#include "driver/gpio.h"
// Blinking related defines
#define BLINK_GPIO 15
#define BLINK_PERIOD_SLOW 2000
#define BLINK_PERIOD_FAST 500
// Button related defines
#define BOOT_BUTTON_NUM 9
#define MY_BUTTON_NUM BOOT_BUTTON_NUM
// active low
#define MY_BUTTON_PRESSED_STATE 0
// logging prefix
static const char *TAG = "simple_button";
// current state of the LED
static uint8_t s_led_state = 0;
//current blink period
static uint32_t current_blink_period = BLINK_PERIOD_SLOW;
//----------- LED
static void configure_led(void)
{
ESP_LOGI(TAG, "Example configured to blink GPIO LED!");
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
}
static void blink_led(void)
{
/* Set the GPIO level according to the state (LOW or HIGH)*/
gpio_set_level(BLINK_GPIO, s_led_state);
}
//----------- Button
static void configure_button(void)
{
gpio_set_direction(MY_BUTTON_NUM, GPIO_MODE_INPUT);
//??? No need to set internal pulls?
}
// will return 1 when the button read matches the value expected for a
// pressed button.
static uint8_t read_button(){
return (gpio_get_level(MY_BUTTON_NUM) == MY_BUTTON_PRESSED_STATE);
}
//----------- Configure Info
static void reveal_configuration(void) {
//shows all
//gpio_dump_io_configuration(stdout, SOC_GPIO_VALID_GPIO_MASK);
gpio_dump_io_configuration(stdout, (1ULL << BLINK_GPIO) | (1ULL << BOOT_BUTTON_NUM));
}
void app_main(void)
{
// Configure the peripherals
configure_led();
configure_button();
//print out the information
reveal_configuration();
while (1) {
// pin HIGH is __LED OFF__ for the XIAO built in LED.
ESP_LOGI(TAG, "Turning the LED %s!", s_led_state == true ? "OFF":"ON");
blink_led();
/* Toggle the LED state */
s_led_state = !s_led_state;
// if button is true, blink fast, else blink slow
if (read_button() == 1) {
current_blink_period = BLINK_PERIOD_FAST;
} else {
current_blink_period = BLINK_PERIOD_SLOW;
}
vTaskDelay(current_blink_period / portTICK_PERIOD_MS);
}
}
Summary
That’s enough for one round. Next step is to confirm I can make the WiFi work with just the SDK as well.
This article is part of a series.
- Part 1: Can I program a an ESP32C6 with the esp-idf?
- Part 2: Can I program an ESP32C6 with the Swift example code?
- Part 3: This Article
- Part 4: How does the espressif SDK handle wifi?
- Part 5: Can I combine an LED and a button on the ESP32C6 with Swift?
- Part 6: Can I add Wifi to the ESP32C6 project with Swift?
- Part 7: Can I make a Swift-wrapped HTTP GET request from the ESP32C6?