Files

147 lines
5.9 KiB
Markdown

# Build and deploy
Target: Windows, Arduino IDE 2.x, board package **esp32-bluepad32 4.1.0**,
original ESP32 (WROOM/WROVER). S3/C3/C6/H2 have no Bluetooth Classic, so a PS4
pad will not pair with them.
## 1. Install the board package
Preferences -> Additional board manager URLs, add:
```
https://raw.githubusercontent.com/ricardoquesada/esp32-arduino-lib-builder/master/bluepad32_files/package_esp32_bluepad32_index.json
```
Boards Manager -> install **esp32_bluepad32**. Then Tools -> Board ->
**esp32_bluepad32** -> ESP32 Dev Module.
Picking the board out of the normal `esp32` package is what gives you
`fatal error: Bluepad32.h: No such file or directory`. Bluepad32 is a
replacement board package, not a Library Manager entry, and adding it as a ZIP
library will not work.
Do **not** install Legoino or NimBLE-Arduino. If either ends up in the build you
are back to two Bluetooth host stacks fighting over one radio, which is the
whole problem this project exists to avoid.
## 2. Put the BTstack headers on the include path
Package 4.1.0 ships the BTstack and Bluepad32 headers under
`tools\sdk\<mcu>\include\`, but does not add them to the compiler's include
path. Without this step you get:
```
fatal error: btstack.h: No such file or directory
```
4.1.0 is built on the arduino-esp32 **2.x** layout, so there is no
`flags\includes` file to edit (that only exists on core 3.x). The include paths
live in `compiler.cpreprocessor.flags` in `platform.txt`. Rather than edit that
file, drop a `platform.local.txt` beside it — Arduino reads it as an override,
the original stays untouched, and rolling back is deleting one file.
In PowerShell:
```powershell
$plat = "$env:LOCALAPPDATA\Arduino15\packages\esp32-bluepad32\hardware\esp32\4.1.0"
$flags = 'compiler.cpreprocessor.flags={compiler.cpreprocessor.flags.{build.mcu}} ' +
'"-I{compiler.sdk.path}/{build.memory_type}/include" ' +
'"-I{compiler.sdk.path}/include/btstack/src" ' +
'"-I{compiler.sdk.path}/include/btstack/include" ' +
'"-I{compiler.sdk.path}/include/btstack/platform/freertos" ' +
'"-I{compiler.sdk.path}/include/bluepad32/include"'
$flags | Out-File "$plat\platform.local.txt" -Encoding ascii
Get-Content "$plat\platform.local.txt"
```
It has to be a **single line**. The `Get-Content` at the end is there to confirm
it did not wrap.
The first two tokens restate what `platform.txt` already had — the override
replaces the whole value, so they have to be repeated. `{compiler.sdk.path}`
resolves to `tools\sdk\<mcu>`, so these entries work for every MCU in the
package, not just esp32.
What each added path is for:
| Path | Provides |
| --- | --- |
| `btstack/src` | `btstack.h`, `gatt_client.h`, `btstack_run_loop.h` |
| `btstack/include` | `btstack_config.h` — separate directory, and BTstack includes it from `btstack.h`, so missing it gives you a confusing second error right after fixing the first |
| `btstack/platform/freertos` | the ESP32 run loop implementation |
| `bluepad32/include` | `uni.h`, if you later want the `uni_bt_allowlist` API |
Duplicate `-I` flags are harmless, so it does not matter if
`bluepad32/include` was already covered.
Two things to know about this edit:
* A Bluepad32 package update **wipes it**. Keep a copy of `platform.local.txt`
somewhere outside `Arduino15` — there is one in `docs/` here.
* A malformed value breaks compilation for *every* ESP32 sketch on the machine,
not just this one. If things go strange, delete the file.
## 3. Board settings
* Board: ESP32 Dev Module (under esp32_bluepad32)
* Partition Scheme: **Huge APP (3MB No OTA/1MB SPIFFS)**. BTstack with both
transports plus the GATT client does not fit the default partition table.
* Upload speed 921600 is fine; drop to 115200 if uploads fail.
## 4. Before flashing
After creating `platform.local.txt`, fully quit the Arduino IDE — closing the
sketch window is not enough, it has to re-read the platform — and clear the
build cache:
```powershell
Remove-Item "$env:LOCALAPPDATA\Temp\arduino\sketches\*" -Recurse -Force -ErrorAction SilentlyContinue
```
Then set your two hub addresses in `HUB_ADDR_STR` at the top of the sketch and
compile.
## 5. First run
1. Power both hubs and press their green buttons so they are advertising.
2. Flash, open Serial Monitor at 115200.
3. Expect `Connecting hubs, then opening for the gamepad`. Each hub's LED goes
green as it is claimed.
4. Once both are up you get `Hubs up - put the PS4 pad in pairing mode`. Hold
SHARE + PS on the controller until the light bar flashes.
5. Onboard LED on GPIO2 goes solid when the pad and both hubs are all connected.
The order matters and is deliberate: gamepad discovery stays off until the hubs
are connected, so Bluepad32's inquiry and LE scan are not running at the same
time as our LE create-connection.
## Troubleshooting
**A missing header from `btstack/3rd-party`.** Add another `-I` line for that
directory and redo step 4.
**Hubs never connect, no LE connection-complete in the log.** In order of
likelihood: the hubs went back to sleep (they time out after a couple of minutes
— press the buttons again); the addresses are wrong; or the address type is
wrong. For the last one, switch `HUB_ADDR_TYPE` to `BD_ADDR_TYPE_LE_RANDOM`.
**One hub connects, the other never does.** Expected if the first one is stuck
mid-discovery. `serviceHubConnections()` only runs one at a time by design;
check `gActive` is being released.
**Motors stutter, or a hub drops off after a few seconds.** Commands are going
out faster than the hub can absorb. Raise `MOTOR_MIN_GAP_MS`.
**Random crashes at unrelated places.** Almost certainly a BTstack call added to
`loop()`. BTstack is not thread-safe and `loop()` is not the BTstack thread —
see the header comment in the sketch.
Turn on verbose BTstack logging before guessing at any of it. Nearly every
failure mode here surfaces as a specific HCI event you can read.
---
Created by: Jess Rogerson (yelling commands at Claude.AI)