Can I make the button more pressable?
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: How does the espressif SDK handle inputs?
- 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?
- Part 8: Can I make my ESP32C6 HTTP client use HTTPTypes?
- Part 9: Can I Swiftify that ESP32C6 HTTPClient more?
- Part 10: This Article
So this project needs it’s button situation improved. The little boot button that I’m pressing with a bamboo skewer isn’t going to cut it.
Also I want to make the HTTP call “onPress”, not a repeat timer nor “while pressed”. I need to add that feature to MomentaryInput
.
For state of the code at the end of these notes see:
New Parts
So I bought some parts from Adafruit. I generally buy 2 of each thing because accidents happen.
Desired Button:
- Kailh Mechanical Key Switch - Clicky Blue
- Adafruit NeoKey BFF for Mechanical Key Add-On for QT Py and Xiao
Fallback Button (only 1x because its a fall back anyway):
If decide to take on battery power:
- Adafruit LiIon or LiPoly Charger BFF Add-On for QT Py
- Lithium Ion Polymer Battery with Short Cable - 3.7V 420mAh
Short USB C cable:
3 sets of headers went in to assembling the prototype, each a different type.
- the low profile pin headers that came with the button BFF
- deep socket headers
- lower profile socket headers
These all need to be cut down to a length of 7, so if bulk sourcing getting them precut is easier.
Not gonna lie, my husband todbot zipped these on for me since he’s in the middle of a soldering palooza. (Adafruit tutorial on soldering headers and my old play list on soldering in general) I traded firmware-loading duties later in the week. Hero shot for my hero!
To test the new hardware, move the button pin:
//new button on pin 2 instead of on the boot pin (9)
guard var button = MomentaryInput(2) else {
fatalError("Difficulty setting up button.")
}
return it to a simple switch
if button.isActive {
led.turnOn()
} else {
led.turnOff()
}
delay(50);
Why the delay? because without it the esp-if monitor gets a little overwhelmed.
Please enable CONFIG_ESP_SYSTEM_USE_FRAME_POINTER option to have a full backtrace.
E (24238) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (24238) task_wdt: - IDLE (CPU 0)
E (24238) task_wdt: Tasks currently running:
E (24238) task_wdt: CPU 0: main
E (24238) task_wdt: Print CPU 0 (current core) registers
Core 0 register dump:
MEPC : 0x4200b03a RA : 0x4200b03a SP : 0x40811000 GP : 0x4080bfa4
--- 0x4200b03a: $e10__idf_main0B0yyF at ??:?
--- 0x4200b03a: $e10__idf_main0B0yyF at ??:?
TP : 0x40811060 T0 : 0x4200b088 T1 : 0x20000000 T2 : 0xffffffff
--- 0x4200b088: $es5print_10terminatorys12StaticStringV_ADtF at ??:?
S0/FP : 0x0000000f S1 : 0x00000001 A0 : 0x00000000 A1 : 0x00000001
A2 : 0x00000000 A3 : 0x00000004 A4 : 0x00008000 A5 : 0x60091000
A6 : 0x00000001 A7 : 0x0000000a S2 : 0x42020550 S3 : 0x00000000
S4 : 0x00000000 S5 : 0x00000000 S6 : 0x00000000 S7 : 0x00000000
S8 : 0x00000000 S9 : 0x00000000 S10 : 0x00000000 S11 : 0x00000000
T3 : 0x00000000 T4 : 0x00000000 T5 : 0x00000000 T6 : 0x00000000
MSTATUS : 0x00001889 MTVEC : 0x40800001 MCAUSE : 0xdeadc0de MTVAL : 0xdeadc0de
--- 0x40800001: _vector_table at /Users/$USER/esp/esp-idf/components/riscv/vectors_intc.S:54
MHARTID : 0x00000000
The New Code
Because modern buttons are so great, and because I’ve picked one with a real CLICK to it I am not going to worry about a software debounce yet. On this chip I could activate the Espressif provided glitch filter.
Added Inverse to GPIOLevel
extension GPIOLevel {
var inverse:GPIOLevel {
(self == .high) ? .high : .low
}
}
Updates to MomentaryInput
Added a variable to the struct to store the last state, which will need to be initialized using that inverse value just created.
extension MomentaryInput {
init?(_ pinNum: UInt32, activeLow:Bool = true, useInternalHardware:Bool = true) {
self.pin = InputPin(pinNumber: pinNum, activeLow:activeLow, useInternalHardware: useInternalHardware)
self.activeLevel = GPIOLevel(!activeLow)
self.lastState = self.activeLevel.inverse
}
}
var lastState:GPIOLevel
typealias OnActiveBehavior = () -> Void
mutating func onActivate(do behavior:OnActiveBehavior) {
let currentLevel = pin.readLevel()
if currentLevel != lastState && currentLevel == activeLevel {
behavior()
}
lastState = currentLevel
}
Since my code will just be using the button for this one behavior it’s fine to do the pin read in the call. If I had a lot of behaviors on different button states I’d have to be careful not to do a new read for every method, but only once per while loop. Future versions of the code will have to decide if the setup will register listeners, if listeners get called explicitly in the loop, if the button itself will register behaviors to do after the poll… TBD.
On a chip like the ESP23C6, it would be even better to hook into their existing button interrupt types.
All of that is research for another day. Today is for the easy win.
back on Main.swift
while true {
button.onActivate { print("hello") }
delay(50);
}
TADA! Thats it.
Add the HTTP call back in…
Where I’ve left the code in the branch is with the Wifi and HTTP stuff all un commented again and the new while loop looks like:
while true {
button.onActivate {
let _ = exampleClient.fetch("/")
}
delay(50); //to help out the monitor
}
Works a treat.
Summary
This was a fairly easy task to knock off the list. Especially with a soldering assist.
More things to do would be to bring the neo-pixel that came on the key cap BFF into the mix to signal different states of the send.
Theres a bit more server work to do, too.
And then both the button and the server have to decide what the secret handshake is going the be for this demo.
I guess this mean what the next post will be is a bit of a surprise… even to me!
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: How does the espressif SDK handle inputs?
- 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?
- Part 8: Can I make my ESP32C6 HTTP client use HTTPTypes?
- Part 9: Can I Swiftify that ESP32C6 HTTPClient more?
- Part 10: This Article