Compare commits

...

505 commits

Author SHA1 Message Date
Brent Rubell
9b79afc177
Merge pull request #798 from adafruit/as5600
As5600
2025-08-28 13:48:02 -04:00
tyeth
e60be99cbd Merge branch 'main' into as5600 2025-08-27 20:13:12 +01:00
Tyeth Gundry
19d7984a9e
Merge pull request #799 from adafruit/mlx90632
Mlx90632
2025-08-27 18:21:30 +01:00
Tyeth Gundry
8c0e9803b3 fix(partitions): 4MB NoOTA in platformIO.ini 2025-08-26 19:16:38 +01:00
Tyeth Gundry
4258c12206 chore(as5600): doxygen for readSensor 2025-08-26 18:43:45 +01:00
Tyeth Gundry
7a275e5d02 fix(as5600): check before delete 2025-08-26 18:31:45 +01:00
Tyeth Gundry
d2d51db455 PR feedback and clang format 2025-08-22 18:18:32 +01:00
Tyeth Gundry
71b8dd42d2 Doxygen fixes 2025-08-22 13:21:14 +01:00
Tyeth Gundry
6deba1dea6 clang-format 2025-08-22 13:04:10 +01:00
Tyeth Gundry
5be2eb1b4a Drop logging around model id, accuracy etc. 2025-08-22 13:03:01 +01:00
Tyeth Gundry
6de22b6d25 Add delete/nullptr check to begin (dtor not called) 2025-08-22 12:58:59 +01:00
tyeth
9fc7c60893 fix(as5600): change angle to be relative to 360 2025-08-21 16:34:28 +01:00
tyeth
fc71187a3f fix(as5600): correct fail logic in configureSensor() 2025-08-21 16:24:14 +01:00
tyeth
dda19cd00a fix(as5600): set angle correctly and log if no magnet 2025-08-21 16:14:24 +01:00
tyeth
78367af420 clang format 2025-08-21 15:24:56 +01:00
tyeth
0a43f57744 Add AS5600 2025-08-21 15:23:47 +01:00
tyeth
39a15fd584 clang 2025-08-20 17:21:19 +01:00
tyeth
40a7ecbce7 clean up object and stop infinite loops 2025-08-20 17:20:39 +01:00
tyeth
d3919890fb adjust read logic for MLX90632 if not continuous reads (offline/low-power mode?) 2025-08-20 16:25:18 +01:00
tyeth
79f372af44 fix(mlx90632): skip re-reading if recently read 2025-08-20 16:11:18 +01:00
tyeth
96fa8d2066 fix(partitions): update 4mb to No OTA in platformIO.ini 2025-08-20 15:44:36 +01:00
tyeth
dc5ff4ae9f clang-format 2025-08-20 14:54:32 +01:00
tyeth
32f85f7b47 add(mlx90632): alias B model to D driver 2025-08-20 14:45:45 +01:00
tyeth
28dff4e04d add(mlx90632): implement extended mode 2025-08-20 14:23:22 +01:00
tyeth
f007fe83ef refactor(mlx90632d): support extended range at init 2025-08-20 14:20:24 +01:00
tyeth
54ee1a632a refactor(mlx90632): use -d model distinction for medical 2025-08-20 14:13:45 +01:00
tyeth
e873237b5e add(driver): Add MLX90632 driver w/ debug info 2025-08-20 12:33:33 +01:00
Tyeth Gundry
e06ebab53a
Merge pull request #794 from tyeth/git-describe-fork-fix
fix(CI): make git version work on forks
2025-08-18 20:33:03 +01:00
tyeth
bc97ca02ad fix(CI): make git version work on forks 2025-08-18 19:40:22 +01:00
Tyeth Gundry
5e79a3725b
Merge pull request #791 from Monstertov/fix-typos
Spelling and grammar corrections in project files
2025-08-18 17:41:54 +01:00
Monstertov
68db0345da Resolved a minor textual error by changing 'supress' to 'suppress' 2025-08-14 00:44:50 +02:00
Monstertov
7f9bbb01ae Addressed typo: changed 'pubish' to 'publish' 2025-08-14 00:44:50 +02:00
Monstertov
a4c53f7727 Improved clarity by fixing typo: 'occured' corrected to 'occurred' 2025-08-14 00:44:50 +02:00
Monstertov
81c8b2697f Corrected a spelling mistake: 'occured' → 'occurred' 2025-08-14 00:44:50 +02:00
Monstertov
9b14c3932b Improved clarity by fixing typo: 'occured' corrected to 'occurred' 2025-08-14 00:44:50 +02:00
Monstertov
bfb5ef2e80 Corrected a spelling mistake: 'reseted' → 'reset' 2025-08-14 00:44:50 +02:00
Monstertov
255a958ec1 Improved clarity by fixing typo: 'detatch' corrected to 'detach' 2025-08-14 00:44:50 +02:00
Monstertov
7fd61698c2 Fixed typo in documentation/code: 'recieves' was replaced with 'receives' 2025-08-14 00:44:50 +02:00
Monstertov
0106eefbad Fixed typo in documentation/code: 'recieves' was replaced with 'receives' 2025-08-14 00:44:50 +02:00
Monstertov
c28334635d Corrected a spelling mistake: 'recieves' → 'receives' 2025-08-14 00:44:50 +02:00
Monstertov
1224fd01bc Addressed typo: changed 'recieved' to 'received' 2025-08-14 00:44:50 +02:00
Monstertov
4003fdc574 Addressed typo: changed 'identifer' to 'identifier' 2025-08-14 00:44:49 +02:00
Monstertov
e59d7913d4 Addressed typo: changed 'identifer' to 'identifier' 2025-08-14 00:44:49 +02:00
Monstertov
65476e8278 Corrected a spelling mistake: 'avaliable' → 'available' 2025-08-14 00:44:49 +02:00
Brent Rubell
114aa7aa7b
Merge pull request #790 from adafruit/add-fruitjam
Add Adafruit Fruit Jam - Mini RP2350 Computer
2025-08-13 15:56:52 -04:00
brentru
5e76adca6a Drop semver down to b110 2025-08-13 15:47:23 -04:00
Tyeth Gundry
f4788c0207
Merge pull request #789 from tyeth/ina228
Add INA228 to online mode (included as base lib for INA23x)
2025-08-13 20:39:07 +01:00
brentru
98f045e3c7 Addres @tyeth's review 2025-08-13 15:15:22 -04:00
Tyeth Gundry
315e4e8791 clang format and fix millivolts returned from bus voltage 2025-08-13 19:17:03 +01:00
brentru
80a6cdc6e0 Add Arduino_ prefix in boards.h 2025-08-13 14:13:33 -04:00
brentru
1cee8e8ca5 Add CI 2025-08-13 13:45:43 -04:00
brentru
5088cb6c8b Add AirLift 2025-08-13 13:42:31 -04:00
Tyeth Gundry
0b61e2b8a9 Add INA228 (included as base lib for INA23x) 2025-08-13 18:13:30 +01:00
brentru
74e2f53aa7 Working on FruitJam 2025-08-13 12:49:29 -04:00
brentru
0b6964b131 Fix for rp2350/rp2040 to use pstolzar 2025-08-12 16:46:03 -04:00
brentru
6304d73d88 Fix platformio.ini build script for pico sdks, weird and hardcoded 2025-08-12 16:37:25 -04:00
Tyeth Gundry
895bd13011
Merge pull request #765 from adafruit/ina238
Ina238 + 237 via a refactor of INA260 too.
2025-08-08 16:01:24 +01:00
Tyeth Gundry
029602abb0
Update build-clang-doxy.yml - switch back to main now confirmed same 2025-07-30 16:41:51 +01:00
Tyeth Gundry
ae5f4199ea
Update Wippersnapper.h - v110 2025-07-25 13:54:47 +01:00
Tyeth Gundry
fbacaa46aa
Update library.properties - v110 2025-07-25 13:53:59 +01:00
Tyeth Gundry
591f801f8a
Merge pull request #771 from kbsriram/add-dfrobot-beetle-esp32c3
Support for DFRobot Beetle ESP32C3.
2025-07-24 18:07:39 +01:00
tyeth
2e975746b5 Merge branch 'main' into ina238 2025-07-24 17:41:34 +01:00
tyeth
51dcd252bc Revert "Temporarily swap ci-arduino to ci-wippersnapper-2025-07-10-noota"
This reverts commit 51b9335df8.
2025-07-24 17:20:54 +01:00
tyeth
94bcecc020 Revert "Temporarily swap boards branch to migrate-4mb-to-esptool"
This reverts commit 860822a172.
2025-07-24 17:19:43 +01:00
Tyeth Gundry
10c9ef1542
Merge pull request #781 from adafruit/migrate-s3-boards
Migrate-s3-boards
2025-07-24 16:10:27 +01:00
tyeth
4dd956eee9 Adjust sleep retry to be >60s with fuzz 2025-07-23 20:49:01 +01:00
tyeth
ca3d5c7d19 Add error catching to tinyuf2 steps 2025-07-23 20:22:25 +01:00
tyeth
00ca0190f6 Make curl fail properly with bad http status codes 2025-07-23 19:10:55 +01:00
Tyeth Gundry
c7c007b6b9 Provide more info if tinyuf2 release fetch failure 2025-07-23 19:10:55 +01:00
Tyeth Gundry
d8595b215c Update version to 1.0.0-beta.109 2025-07-23 19:10:55 +01:00
Tyeth Gundry
81f43d589e Remove bootloader offsets as now in tinyuf2 flash_args file 2025-07-23 19:10:55 +01:00
Tyeth Gundry
6a98837c3c Reorder targets in esptool job by chip then alpha 2025-07-23 19:10:55 +01:00
Tyeth Gundry
effe76b2e1 Switch 4MB S3 boards to esptool job 2025-07-23 19:10:54 +01:00
Tyeth Gundry
8b02c9b910
Merge pull request #780 from adafruit/migrate-s2-boards
Migrate S2 boards to web-native-usb build task
2025-07-23 15:48:08 +01:00
tyeth
921527a9e2 Ensure build works without offsets before removal 2025-07-22 02:48:24 +01:00
tyeth
52edecfa07 Bump version to 108 2025-07-22 02:46:41 +01:00
tyeth
2667caf75f Migrate S2 boards to web-native-usb build task 2025-07-22 02:43:19 +01:00
Tyeth Gundry
c653e06fcf
Merge pull request #779 from adafruit/featherS2-migration
tinyuf2 build task changes (PR #774) plus Feather s2 migration
2025-07-21 20:20:58 +01:00
Tyeth Gundry
e0ccdc28fd Merge branch 'use_s3_tinyuf2_bins' into featherS2-migration 2025-07-18 21:43:00 +01:00
Tyeth Gundry
69cf749316 Split up tinyuf2 steps 2025-07-18 21:40:18 +01:00
Tyeth Gundry
714974ff13 JQ filter 2025-07-18 21:36:28 +01:00
Tyeth Gundry
0c08eddde0 Update version to 1.0.0-beta.107 2025-07-18 20:11:28 +01:00
Tyeth Gundry
01a99d9313 cleanup tinyuf2 downlaod + error handling 2025-07-18 20:10:19 +01:00
Tyeth Gundry
5964f2ee5b WIP: swap boards branch 2025-07-18 20:10:19 +01:00
Tyeth Gundry
61590ea1c0 Update tinyuf2 fetch process to use bootloaderBoardName 2025-07-18 20:10:19 +01:00
tyeth
0a757d6b8f Overwrite tinyusb boot preference 2025-07-18 20:10:19 +01:00
tyeth
b9746ad1c5 Copy bootloader/partition table files for flash_args 2025-07-18 20:10:19 +01:00
tyeth
9297c020ad Swap to using flash_args file for bin offsets 2025-07-18 20:10:19 +01:00
tyeth
17bc2a2c47 CI 2025-07-18 20:10:19 +01:00
tyeth
592c75abcd Correct XIAO tinyusb link 2025-07-18 20:10:19 +01:00
tyeth
df4d9163a6 Use tinyuf2 combined.bin as image base 2025-07-18 20:10:19 +01:00
Tyeth Gundry
3ed453636c Swap Feather ESP32-S2 to web-native-usb task 2025-07-18 20:09:32 +01:00
Tyeth Gundry
09e4a79ab1 cleanup tinyuf2 downlaod + error handling 2025-07-18 20:09:32 +01:00
Tyeth Gundry
26c6c32077 WIP: swap boards branch 2025-07-18 20:09:32 +01:00
Tyeth Gundry
7bf7357328 Update tinyuf2 fetch process to use bootloaderBoardName 2025-07-18 20:09:32 +01:00
tyeth
2fc427c908 Overwrite tinyusb boot preference 2025-07-18 20:09:32 +01:00
tyeth
451ac02e2e Copy bootloader/partition table files for flash_args 2025-07-18 20:09:32 +01:00
tyeth
3ad6500f61 Swap to using flash_args file for bin offsets 2025-07-18 20:09:31 +01:00
tyeth
87cea3a14d CI 2025-07-18 20:09:31 +01:00
tyeth
9f70757b9c Correct XIAO tinyusb link 2025-07-18 20:09:31 +01:00
tyeth
21144c0ce1 Use tinyuf2 combined.bin as image base 2025-07-18 20:09:31 +01:00
Tyeth Gundry
331c6c85ba
Merge pull request #778 from adafruit/pin-temp-lib
Pin to https://github.com/milesburton/Arduino-Temperature-Control-Lib
2025-07-18 20:08:19 +01:00
Tyeth Gundry
b45d08b0cd
make that v4.0.3 2025-07-18 19:27:08 +01:00
Tyeth Gundry
6d5c8c4a7b
pin to official release 4.0.3 not fork! 2025-07-18 19:25:05 +01:00
Tyeth Gundry
e6d7f40b7a
Got clone needs branch ref / fork
--branch pin_pid_fix https://github.com/tyeth/milesburton_Arduino-Temperature-Control-Library.git
2025-07-18 18:53:41 +01:00
Tyeth Gundry
f62527af5b
Pin to https://github.com/milesburton/Arduino-Temperature-Control-Library.git#456b2b3a79bc7b9b6ee60454d6511eb6a77aef81
Due to #777
2025-07-18 18:31:10 +01:00
Brent Rubell
f3c85efb53
Merge pull request #776 from adafruit/bump-semver-b106
Bump Semver for SSL Cert Merge
2025-07-17 09:46:33 -04:00
brentru
a6e23a95c4 bump version for ssl cert 2025-07-17 09:33:18 -04:00
Brent Rubell
5f8c3ac364
Merge pull request #770 from adafruit/update-fingerprint-2025
Update SSL Fingerprint for 2025
2025-07-16 10:12:56 -04:00
Tyeth Gundry
5513004820
Merge pull request #772 from adafruit/tyeth-xiao-board-name
Update Wippersnapper_Boards.h
2025-07-16 13:20:13 +01:00
Tyeth Gundry
c21ffb7512
Update Wippersnapper_Boards.h 2025-07-16 12:45:15 +01:00
KB Sriram
002cdfd6da Update preprocessor defines for arduino builds. 2025-07-15 06:46:37 -07:00
KB Sriram
0489a41130 Update CI flows to build DFRobot Beetle esp32c3. 2025-07-14 14:23:16 -07:00
brentru
19bb4016ff Update SSL fingerprint on esp8266 iface 2025-07-14 16:14:42 -04:00
KB Sriram
2091034df0 Support for DFRobot Beetle ESP32C3.
See https://github.com/adafruit/Wippersnapper_Boards/issues/195
2025-07-13 16:18:47 -07:00
Tyeth Gundry
398fb7d8b3
Merge branch 'main' into ina238 2025-07-11 22:52:14 +01:00
Tyeth Gundry
b637366898
Merge pull request #764 from adafruit/xiao-s3
Xiao s3
2025-07-11 22:50:44 +01:00
Tyeth Gundry
51b9335df8 Temporarily swap ci-arduino to ci-wippersnapper-2025-07-10-noota 2025-07-11 18:05:50 +01:00
Tyeth Gundry
860822a172 Temporarily swap boards branch to migrate-4mb-to-esptool 2025-07-11 17:36:04 +01:00
Tyeth Gundry
29ef4c20d9 make esptool not pinned 2025-07-11 17:32:18 +01:00
Tyeth Gundry
3308d7268f Use latest esptool for Cx builds 2025-07-11 17:06:18 +01:00
Tyeth Gundry
08fa3ac978 Migrate 4MB flash devices to No OTA esptool install method 2025-07-11 17:01:00 +01:00
Tyeth Gundry
a4723b7ff2 rename merge_bin to merge-bin 2025-07-11 16:43:34 +01:00
Tyeth Gundry
f95ec8d84d Update flash param names for newest esptool 2025-07-11 16:27:45 +01:00
Tyeth Gundry
c9e728c0a0 Merge branch 'upstream-main' into ina238 2025-07-11 16:03:51 +01:00
Tyeth Gundry
9a8033638c
Merge pull request #769 from tyeth/omron-D6T
Omron D6T thermal IR sensor (I2C)
2025-07-11 15:57:42 +01:00
Tyeth Gundry
ba22d203d3 Bump version for release v1.0.0-beta.105 2025-07-11 15:54:51 +01:00
Tyeth Gundry
1c50e12d89 D6T-1A: Move initialisation values to constructor 2025-07-11 15:47:01 +01:00
Tyeth Gundry
a1cdc0142f Add Wire include back to I2C Driver (for cpp include chain) 2025-07-11 15:45:07 +01:00
Tyeth Gundry
50b924c937 Cleanup header docstrings, and remove <wire.h> (breaks pio) 2025-07-11 15:41:15 +01:00
Tyeth Gundry
00deb173a8 Cleanup includes and unnecessary prints 2025-07-11 15:17:14 +01:00
Tyeth Gundry
fe32ce6170 clang format 2025-07-11 14:40:45 +01:00
Tyeth Gundry
999bd73547 Merge remote-tracking branch 'upstream/main' into omron-D6T 2025-07-11 13:28:12 +01:00
Tyeth Gundry
3e2f7e4043 Merge remote-tracking branch 'upstream/main' into ina238 2025-07-11 13:18:35 +01:00
Tyeth Gundry
9695762e75 Revert "Test other task for xiao"
This reverts commit ebd3938ae9.
2025-07-10 21:16:41 +01:00
Tyeth Gundry
0d6a5538b0 fix if defined for xiao 2025-07-10 21:16:24 +01:00
Tyeth Gundry
ebd3938ae9
Test other task for xiao 2025-07-10 20:29:28 +01:00
Tyeth Gundry
ec4e48bb86 CI: Fix continue-on-error usage 2025-07-10 19:28:57 +01:00
Tyeth Gundry
a8be947ec5 Enable PSRAM and kick CI 2025-07-10 19:23:12 +01:00
Tyeth Gundry
47bcf53134 Move XIAO S3 to zip+uf2 build task 2025-07-10 19:08:45 +01:00
tyeth
71f829bbdc Correct Board ID for XIAO S3 2025-07-10 19:07:51 +01:00
tyeth
bc99adf69b 8MB Partitions 2025-07-10 19:07:08 +01:00
tyeth
305cc45680 Build assets for XIAO ESP32S3 2025-07-10 19:07:08 +01:00
tyeth
f95481c52b Add Seeed Studio XIAO ESP32S3 2025-07-10 19:07:07 +01:00
Tyeth Gundry
13aa6419e6
Merge pull request #763 from adafruit/add-s3-devkitc-1-n8
Add s3 devkitc 1 n8
2025-07-10 18:58:37 +01:00
Tyeth Gundry
6ccd81433a
Switch board repo back to main 2025-07-10 18:57:30 +01:00
Tyeth Gundry
13bfecf33a
Merge pull request #760 from adafruit/sh1107
Add SH1107 for 128x64/32 OLED featherwings
2025-07-09 20:37:28 +01:00
Tyeth Gundry
c3bc7a83d6 Release version 1.0.0-beta.104 2025-07-09 20:36:55 +01:00
Tyeth Gundry
c5b8706980 clang format? 2025-07-09 20:07:02 +01:00
Tyeth Gundry
7f0f1a2df3 clang format 2025-07-09 18:37:12 +01:00
Tyeth Gundry
1e313842b6 clang format again 2025-07-09 17:27:52 +01:00
Tyeth Gundry
e0d9da4d47 Remove non default args to SSD1306 ctor 2025-07-09 17:13:01 +01:00
Tyeth Gundry
0c55b0320d Rename OLED featherwings 2025-07-09 17:11:04 +01:00
Tyeth Gundry
09c8eb0387 Remove splash screen display + delay 2025-07-09 17:08:41 +01:00
Tyeth Gundry
e632bc6373 clang format 2025-07-09 17:00:25 +01:00
Tyeth Gundry
651395638d PR Feedback 2025-07-09 15:12:43 +01:00
Tyeth Gundry
7b83905e55
Add auto created merged bin to web-native-usb assets 2025-07-09 14:07:40 +01:00
Brent Rubell
a89218cae1
Merge pull request #575 from adafruit/funhouse-display-config-recreate
Regenerate displayconfig.json if erroneous
2025-07-08 15:18:44 -04:00
tyeth
02223db340 clang format 2025-07-08 19:08:26 +01:00
tyeth
4b2859d6fb add rotation to ConfigureSSD1306 func for SH1107 2025-07-08 19:08:26 +01:00
tyeth
d46f29c84a Separate out rotation for future usage and add notes 2025-07-08 19:08:26 +01:00
tyeth
d97123bf75 Set Rotation for 128x64 OLED featherwing 2025-07-08 19:08:26 +01:00
tyeth
def13e627c SSD1306: don't call begin again on i2c (2nd bus) 2025-07-08 19:08:26 +01:00
tyeth
b93d58203d Add 32x64 SSD1306 2025-07-08 19:08:26 +01:00
tyeth
3d3d44b5ab Add 64x32 OLEDs (SH1107) 2025-07-08 19:08:16 +01:00
Tyeth Gundry
cdc6588e57 Add 128x32 OLED featherwings as SSD1306 2025-07-08 19:07:55 +01:00
Tyeth Gundry
f7ec0e5d4a
reset bootloader offset to 0x0 for esp32s3 devkit 2025-07-08 15:59:15 +01:00
tyeth
0bdbc05092 Add BSP comment for funhouse 2025-07-08 14:35:08 +01:00
Tyeth Gundry
aa2d7d40c3 Match Arduino-CLI partitions for S3 devkit 2025-07-08 14:30:48 +01:00
Tyeth Gundry
7f491da2f8 Update offset for esp32s3 devkit 2025-07-08 14:29:38 +01:00
tyeth
db31909eb0 PR feedback, relocate retry out of parseDisplayConfig 2025-07-08 12:30:04 +01:00
Tyeth Gundry
12db602a62 Regenerate displayconfig.json if erroneous 2025-07-08 12:30:04 +01:00
Tyeth Gundry
d109ea6905 feather 8mb partition 2025-07-08 12:08:38 +01:00
Tyeth Gundry
5fa3e2dc0c WIP: Swap boards branch to PR 2025-07-07 23:34:19 +01:00
Tyeth Gundry
3a9137480d Move esp32s3 devkitc to zip build task 2025-07-07 22:46:08 +01:00
tyeth
3be45da123 tested on win11 with 3.13 BSP, tinyUSB 3.7.0, and no rename_usb_config 2025-07-05 13:57:59 +01:00
tyeth
ebf5e40edd Update build flags for esp32s3 devkit 2025-07-04 18:59:12 +01:00
tyeth
b047125981 8MB partitions for 8MB boards 2025-07-02 23:43:52 +01:00
Tyeth Gundry
44024f6d15 Add missing private pointer for D6T-1A 2025-07-02 20:12:44 +01:00
Tyeth Gundry
f7c094c759 D6T: specify cell/pixel for temp reading 2025-07-02 20:05:13 +01:00
Tyeth Gundry
275bedeec7 D6T: Floats and Model name swap 2025-07-02 19:47:40 +01:00
Tyeth Gundry
172646a55a Correct D6T model name and privates usage 2025-07-02 19:31:57 +01:00
Tyeth Gundry
cfdbfd6c79 clang-format 2025-07-02 18:34:21 +01:00
Tyeth Gundry
4e9d959004 D6T: Swap to single read for both metrics 2025-07-02 18:33:27 +01:00
Tyeth Gundry
b35c2c2e56 Add OMRON D6T thermal sensor 2025-07-02 18:23:48 +01:00
tyeth
b4bf4362a4 QTPY S3 No PSRAM uses 8MB partition 2025-07-01 15:05:41 +01:00
tyeth
1c6813f529 Resolve dependency chain - Split INA260 + 2XX to cpp files, forward declare INA classes to hide enums from each other 2025-06-30 14:14:37 +01:00
tyeth
b3915857c8 Add INA237 + INA238 2025-06-29 23:33:28 +01:00
tyeth
af62bccf0d Specify 8MB partition for S3 feather (no PSRAM) 2025-06-29 21:44:05 +01:00
Tyeth Gundry
f6af170e60 Add optional psram for esp32s3 dev 2025-06-26 22:34:48 +01:00
Tyeth Gundry
92d769e321 Correct ifdef for s3 devkit 2025-06-26 22:33:36 +01:00
Tyeth Gundry
7ce619455d Add ESP32S3 build target in CI 2025-06-26 22:04:48 +01:00
Tyeth Gundry
9a144fdb01 Add ESP32S3 DevKitC-1 (N8 with 8MB flash and no PSRAM) 2025-06-26 22:03:41 +01:00
Tyeth Gundry
ab3284ecb1
Add SH1107 for 128x64/32 OLED featherwings 2025-06-19 16:30:53 +01:00
Brent Rubell
13d4ca9368
Merge pull request #759 from adafruit/fix-i2c-display-cr
Patch - \r handling for I2C Displays
2025-06-18 12:43:35 -04:00
brentru
b9a33a7397 Fix for SSD1306 2025-06-18 12:31:15 -04:00
brentru
159cf772b5 Fix again \r not showing 2025-06-17 17:06:14 -04:00
brentru
ed75830d68 Show non japanese set for / 2025-06-17 16:44:20 -04:00
brentru
6333e8e8d2 Fix \r display 2025-06-17 16:37:00 -04:00
brentru
e5a3acfb39 \r\n sequence escape 2025-06-17 13:52:21 -04:00
brentru
cb65ab35bb Patch #2 2025-06-17 13:37:49 -04:00
brentru
e2225f53e4 Patch - \r handling 2025-06-17 12:21:36 -04:00
brentru
4494e3ea13 Bump semver to b103 2025-06-17 11:28:23 -04:00
Brent Rubell
b06aea09f4
Update library.properties 2025-06-17 11:26:59 -04:00
Brent Rubell
02ace5cf52
Merge pull request #751 from adafruit/api-v1-add-i2c-output
[API v1]: Add support for I2C Output Components
2025-06-17 11:20:57 -04:00
brentru
d784e8a7ca Clang 2025-06-09 11:44:54 -04:00
brentru
dd97c84df2 Match 64972ad..1786350 2025-06-09 11:24:59 -04:00
brentru
5c61a83323 Add 20x4 2025-06-09 11:00:08 -04:00
brentru
67b851fb7b Fix - Chardisplay 16x2 2025-06-09 10:56:07 -04:00
brentru
6e9ce5cbc3 Fix - degree symbol on 7seg display 2025-06-06 13:55:10 -04:00
brentru
67abbc6cdf Fix - do not publish i2c output write back to io, there is no matching resp! 2025-06-06 12:47:35 -04:00
brentru
6bf81185f5 7seg- fix right justification bug, max chars 2025-06-06 12:37:06 -04:00
Tyeth Gundry
3eed1bcb16
Merge pull request #756 from adafruit/sparkle-motion-stick
Sparkle motion stick
2025-06-06 16:29:48 +01:00
brentru
050216d0eb alphanum - build degree symbol out of segement raw bitmask 2025-06-05 16:23:24 -04:00
brentru
eed66c7984 clear on ctor dtor 2025-06-05 14:59:13 -04:00
brentru
964760ad96 Add large OLED 2025-06-05 14:33:28 -04:00
brentru
6e7daf9027 fix SSD1306 bugs 2025-06-05 14:30:25 -04:00
tyeth
7c674fa52a Set funhouse to use Adafruit SDfat fork 2.2.54 2025-06-05 16:58:10 +01:00
tyeth
d7008d9cb0 Add build asset .generate and .skip files 2025-06-03 21:36:32 +01:00
tyeth
f544a7c5ed Bump release version to beta.102 2025-06-03 21:00:41 +01:00
tyeth
d8727d7075 Add Sparkle Motion Stick 2025-06-03 21:00:26 +01:00
Tyeth Gundry
d0463bf3b6
Merge pull request #752 from adafruit/fix-duty-cycle
Fix LEDC PWM DutyCycle
2025-05-23 20:08:20 +01:00
Tyeth Gundry
564191c4eb Bump version to 1.0.0-beta.101 2025-05-23 19:57:27 +01:00
Tyeth Gundry
bb0d40644a Clang-format PWM fix 2025-05-23 19:56:49 +01:00
brentru
486422c821 Fix build error 2025-05-21 17:03:08 -04:00
brentru
ab82347fc2 Attempt to fix the AnalogWrite issue 2025-05-21 17:00:32 -04:00
brentru
86896852e4 Turn display off before dtor'ing 2025-05-21 12:27:37 -04:00
brentru
9e1d67722c Doxygen 2025-05-20 14:52:28 -04:00
brentru
c4c0fcdb26 Add deps.! 2025-05-20 14:36:14 -04:00
brentru
fa0b3c6555 Put back auto-config scaffolding 2025-05-20 14:34:19 -04:00
brentru
47afeb7b7f Works on both display sizes 2025-05-20 14:30:09 -04:00
brentru
a86ead8457 Test on 128x32, new PBs to match 8e89fdf 2025-05-20 11:29:03 -04:00
brentru
8529924d16 Looking into SSD1306 not writing properly 2025-05-19 16:49:05 -04:00
brentru
ff4a4167d0 Add Write Msg 2025-05-19 15:55:18 -04:00
brentru
c1d96985b5 Integrate PR a1a0ab6..8e89fdf 2025-05-19 15:19:15 -04:00
brentru
092c796ed1 Fully integrate SSD1306 driver, missing write func 2025-05-19 14:42:56 -04:00
brentru
0e19aa0675 add ssd driver 2025-05-19 14:23:32 -04:00
brentru
c281ed8971 push clang 2025-05-16 17:10:47 -04:00
brentru
6202ecac62 Fix LED matrix write 2025-05-16 16:58:42 -04:00
brentru
c470fa3093 Tie in enable/disable for charlcd writes 2025-05-16 16:53:47 -04:00
brentru
3ae7029a51 Add new Pbs to match 6c842d81bf332dfc0fbfef4d2045c2d934e467f3 2025-05-16 15:58:21 -04:00
brentru
420d319cc6 address @tyeth review 2025-05-16 10:55:56 -04:00
brentru
a4d9e9d6eb clang again 2025-05-15 15:20:27 -04:00
brentru
f6c406ab86 Clang 2025-05-15 14:50:28 -04:00
brentru
00bb2bf62d Add 7seg driver 2025-05-15 11:28:58 -04:00
brentru
645fd4d77c Add CharLCD 2025-05-15 11:12:04 -04:00
brentru
cc3a3c5095 Add write commands for quadalphanum 2025-05-14 16:55:59 -04:00
brentru
5265e25462 compiles OK 2025-05-14 13:05:59 -04:00
brentru
d25aba8e72 bring in new PBs, new drivers 2025-05-14 12:53:21 -04:00
Tyeth Gundry
bcf1d08d58
Merge pull request #746 from adafruit/745-update-v1-codebase-to-use-latest-release-of-pm25-library-is_pm1006-flag
Update PM2.5 begin_UART call for PM1006 (PM25AQI v2.0.0)
2025-05-12 17:37:40 +01:00
Tyeth Gundry
f92df0a2c9 Update PM2.5 begin_UART call for PM1006 (PM25AQI v2.0.0) 2025-05-09 12:29:36 +00:00
Tyeth Gundry
3fa0d82d66
Update Wippersnapper.h - bump version to 1.0.0-beta.100 2025-04-04 18:58:54 +01:00
Tyeth Gundry
88f2a87b19
Update library.properties - bump version to 1.0.0-beta.100 2025-04-04 18:57:54 +01:00
Tyeth Gundry
f1e608691b
Merge pull request #718 from adafruit/add-INA260
Add INA260
2025-04-04 17:29:55 +01:00
tyeth
e50a1648a9 Add INA260 2025-04-04 00:38:53 +01:00
Tyeth Gundry
8e5bf4f798
Merge pull request #715 from adafruit/back-to-upstream-SPIFlash
Revert "use brentru SPIFLash fork"
2025-03-18 17:05:00 +00:00
tyeth
e18d7cb4ae Revert "use brentru SPIFLash fork"
This reverts commit cd5e7e01fb.
2025-03-18 16:45:57 +00:00
Brent Rubell
9c6ee194d4
Merge pull request #714 from adafruit/SCD-pointers-v98-fix
SCD-pointers-v98-fix
2025-03-14 10:42:32 -05:00
tyeth
5658c88d1f Correct SCD30 data check 2025-03-14 15:08:31 +00:00
tyeth
1f69fde777 Update to version 1.0.0-beta.99 2025-03-14 14:50:29 +00:00
tyeth
2bbdc1edae Fix event pointer usage for SCD sensors 2025-03-14 14:49:36 +00:00
Tyeth Gundry
31eed58731
Merge pull request #712 from adafruit/fix-i2c-scan-issue
Fix: I2C Scan on ESP32-S2
2025-03-11 21:41:00 +00:00
brentru
322c72e14b remove setclock call 2025-03-11 15:46:19 -04:00
brentru
6b3996ae57 track addresses 2025-03-11 11:49:46 -04:00
brentru
e0bb91f422 fix @tyeth reivew 2025-03-10 16:03:11 -04:00
brentru
6401b504b5 dont always print address, reorder conditional for performance boost marginal 2025-03-10 15:38:14 -04:00
brentru
89873252d4 fixing scan issue.. 2025-03-10 13:36:43 -04:00
Brent Rubell
0218e061ef
Merge pull request #711 from adafruit/revert-forked-deps
Revert SDFat Forked Dependency for Pico
2025-03-07 13:20:03 -06:00
brentru
cd5e7e01fb use brentru SPIFLash fork 2025-03-07 14:08:38 -05:00
brentru
a360a92054 install sdfat first in order? 2025-03-07 13:48:31 -05:00
brentru
80f1d87973 put back direct clone for rp2x 2025-03-07 13:39:20 -05:00
brentru
fde128ca3a fork only 2025-03-07 13:17:34 -05:00
brentru
3b20073662 try workflow? 2025-03-07 13:02:05 -05:00
brentru
25f28b4fdf revert sdfat 2025-03-07 10:09:19 -05:00
Brent Rubell
afd0e86d19
Merge pull request #708 from adafruit/fix-neopixel-bug-c6
Fix Issues: Pixel and Status Pixel
2025-03-07 09:07:47 -06:00
Tyeth Gundry
0bf00bcafa
Merge pull request #709 from tyeth/scd30-scd4x-others-poll-min-1sec
Scd30 scd4x others poll min 1sec
2025-03-07 15:06:02 +00:00
Tyeth Gundry
16c6723d3c clang format 2025-03-07 01:56:41 +00:00
Tyeth Gundry
ba1f09fde9
Merge branch 'main' into scd30-scd4x-others-poll-min-1sec 2025-03-07 01:39:59 +00:00
Tyeth Gundry
272c1fc5f8 style changes 2025-03-07 01:01:37 +00:00
Tyeth Gundry
712e434a87
Merge pull request #694 from adafruit/local-non-zero-initialised
Update I2C initialisation of locals
2025-03-06 20:15:17 +00:00
brentru
47f306c311 fix ser 2025-03-06 15:03:15 -05:00
brentru
393fffa145 Reflect using dtor instead 2025-03-06 15:01:50 -05:00
Tyeth Gundry
bcd3bd7288 Update to Google CPP style guide 2025-03-06 18:39:02 +00:00
Tyeth Gundry
d79457f92d
Merge pull request #695 from adafruit/add-lps28
Add LPS28DFW
2025-03-05 22:27:42 +00:00
Tyeth Gundry
547d46cf1b
Merge branch 'main' into add-lps28 2025-03-05 22:26:30 +00:00
Tyeth Gundry
628b98a411
Merge pull request #690 from adafruit/pico2w-ds18b20
fix: timeout datatype in haltError
2025-03-05 22:20:56 +00:00
Tyeth Gundry
d4e88a39be Update SEN6x to min 1second polling 2025-03-05 22:14:33 +00:00
Tyeth Gundry
093d51779f Refactor SEN5x to minimum poll period 1sec 2025-03-05 22:02:39 +00:00
Tyeth Gundry
722a41d3fb Correct formattiing 2025-03-05 21:44:39 +00:00
Tyeth Gundry
66fe637443 Update SCD4x to sensor event types + zero inits 2025-03-05 21:33:03 +00:00
Tyeth Gundry
39971499f2 Add minimum poll interval of 1second to SCD4x/SCD30 2025-03-05 21:21:30 +00:00
brentru
c6f15b5f1a Remove RMT header 2025-03-05 15:11:16 -05:00
brentru
fce17a3c38 Fix for C6 2025-03-05 14:53:12 -05:00
Tyeth Gundry
dfa628fea9 Swap to ints for haltError 2025-03-05 19:15:53 +00:00
tyeth
f64833ad74 fix: timeout datatype in haltError 2025-03-05 19:09:51 +00:00
brentru
53c95ace17 Look at C6 bug 2025-03-04 16:46:21 -05:00
Brent Rubell
e92e740192
Merge pull request #706 from brentru/fix-sdfat-conflict
Fix SDFat Conflict for Pico
2025-03-03 08:39:22 -06:00
brentru
abe3c9756b Add GFX 2025-02-28 16:21:05 -05:00
brentru
e2ae5a0494 Add sdfat 2025-02-28 16:08:50 -05:00
brentru
987fd605df Return to original fork 2025-02-28 16:02:33 -05:00
brentru
e77cec2730 Sensirion Core 2025-02-28 15:52:41 -05:00
brentru
e694a935ee unified sensor 2025-02-28 15:46:18 -05:00
brentru
a7a10a3d6f Add adafruit_sensor 2025-02-28 15:42:12 -05:00
brentru
7dea9042e3 fix busdevice 2025-02-28 15:39:41 -05:00
brentru
8329d2531f list out 2025-02-28 14:56:21 -05:00
brentru
b307521a77 bump ci 2025-02-28 14:49:04 -05:00
brentru
3f827eb080 Link locally, use branch 2025-02-28 14:46:55 -05:00
brentru
26e3b6490a link header 2025-02-28 14:40:41 -05:00
brentru
e187db7d91 add fork file 2025-02-28 14:37:57 -05:00
Tyeth Gundry
20d936d10d
Switch LPS28 to full range 2025-02-25 21:33:31 +00:00
Tyeth Gundry
abf14e0252
Update LPS28DFW to use extreme range of 260-4060hPa
param mode true for FS_MODE=1 (1/2048 hPa/LSB), false for FS_MODE=0 (1/4096 hPa/LSB)
2025-02-19 21:40:21 +00:00
Tyeth Gundry
929eb9a83a
Update WipperSnapper_I2C_Driver_LPS28DFW.h 2025-02-19 21:08:47 +00:00
Brent Rubell
250cbf0106
Update README.md 2025-02-19 14:29:41 -05:00
tyeth
df71485155 Fix: use correct short name for LPS28DFW 2025-02-19 14:36:49 +00:00
tyeth
df2b6b06f4 LPS28DFW: log reasons for failures 2025-02-19 14:30:10 +00:00
tyeth
36a4c89fce Add LPS28DFW 2025-02-19 13:28:27 +00:00
tyeth
923428aa6c Update I2C initialisation of locals 2025-02-14 16:34:27 +00:00
Brent Rubell
7ab9e78834
Merge pull request #689 from tyeth/scd4x-header-rename
Update WipperSnapper_I2C_Driver_SCD4X.h - renamed include
2025-02-13 15:43:37 -06:00
tyeth
b91a38752a clang format ifdefs 2025-01-31 15:57:41 +00:00
tyeth
c2fac61aae Update begin and getDataReadyStatus 2025-01-31 15:44:43 +00:00
tyeth
861d67745d Fix multiple ifdef warning 2025-01-31 15:38:39 +00:00
Tyeth Gundry
417009a564
Update WipperSnapper_I2C_Driver_SCD4X.h - update instantiation 2025-01-31 15:07:53 +00:00
Tyeth Gundry
fac20289eb
Update WipperSnapper_I2C_Driver_SCD4X.h - update class name 2025-01-31 14:52:38 +00:00
Tyeth Gundry
9c9a98dd9b
Update WipperSnapper_I2C_Driver_SCD4X.h - renamed include 2025-01-31 14:40:41 +00:00
Tyeth Gundry
4f1d110436
Update Wippersnapper.h - bump version to 1.0.0-beta.97 2025-01-24 19:42:19 +00:00
Tyeth Gundry
c17db48512
Update library.properties - bump version to 1.0.0-beta.97 2025-01-24 19:41:40 +00:00
Tyeth Gundry
19dd739b82
Merge pull request #685 from adafruit/sparkle-motion-mini
Add Sparkle motion mini
2025-01-23 22:05:03 +00:00
Tyeth Gundry
8c1d1c0d8e
Bump version to 1.0.0-beta.96 2025-01-23 20:04:58 +00:00
tyeth
13e8800825 Remove PSRAM from Sparkle Motion Mini 2025-01-23 18:27:47 +00:00
Tyeth Gundry
37b339e941
Add .test.skip and .generate files for Mini Sparkle Motion 2025-01-22 00:02:58 +00:00
Tyeth Gundry
7ce32d8511
Add Mini Sparkle Motion board 2025-01-22 00:00:08 +00:00
Tyeth Gundry
a0c8c75919
Merge pull request #682 from adafruit/staging-ssl-jan2025
Swap staging root certificate to ISRG Root X1
2025-01-15 14:25:05 +00:00
tyeth
64ce6eb922 Swap staging root certificate to ISRG Root X1 2025-01-14 21:00:46 +00:00
Tyeth Gundry
a744b2fe17
Update library.properties - bump version to 1.0.0-beta.95 2025-01-14 19:41:35 +00:00
Tyeth Gundry
b59c15e8e8
Update Wippersnapper.h - bump version to 1.0.0-beta.95 2025-01-14 19:41:15 +00:00
Tyeth Gundry
d3cd109059
Merge pull request #681 from adafruit/fixed-sen66
Fixed SEN66 CO2 overflow


Merges #675
Closes #675
Fixes #678
2025-01-14 19:30:55 +00:00
Tyeth Gundry
d9455c30e0
Merge pull request #680 from adafruit/delete_unused_boards
Delete unused boards
2025-01-14 19:15:05 +00:00
tyeth
a5c4811a3b Drop SAMD21 builds from CI dependencies 2025-01-10 18:27:33 +00:00
Tyeth Gundry
519b0ddf90 Update build-clang-doxy.yml - drop nano-33-iot + mkrwifi1010 2025-01-10 18:27:18 +00:00
tyeth
3504dc952e clang-format 2025-01-10 18:20:39 +00:00
tyeth
044029caa0 Update copyrights and fix CO2 to catch overflow not NAN
Closes SEN66 returns 65535 for first data read, better to skip first value than mess up all the graphs #678
2025-01-10 18:17:13 +00:00
tyeth
0f65b97ad5 Drop SAMD21 builds from CI dependencies 2025-01-10 17:48:41 +00:00
tyeth
fe2eae61ba Remove Nano-33-IOT and MKRWIFI1010 boards 2025-01-10 17:39:38 +00:00
Tyeth Gundry
70cf730454
Update build-clang-doxy.yml - drop nano-33-iot + mkrwifi1010 2025-01-10 17:09:25 +00:00
Martin Ebner
8086b44129 fixed typo in include 2024-12-23 09:15:31 +01:00
Martin Ebner
0957f827bb typo in library.properties 2024-12-23 00:54:39 +01:00
Martin Ebner
9df4d89aa1 add to library and WipperSnapper_I2C 2024-12-23 00:46:21 +01:00
Martin Ebner
aba5d513f8 derived from sen5x driver 2024-12-23 00:32:58 +01:00
tyeth
570c166691 Merge remote-tracking branch 'upstream/uat-xmas2024'
Closes #661
Closes #664
Closes #668
Closes #670
Closes #672
Closes #673
2024-12-21 02:39:20 +00:00
tyeth
0923b82715 20s wifi attempt timeout for PicoW/2W 2024-12-21 02:36:35 +00:00
tyeth
4c0febc001 Merge remote-tracking branch 'upstream/vcnl4200' into uat-xmas2024 2024-12-20 23:22:38 +00:00
tyeth
f46c204285 Merge remote-tracking branch 'tyeth/tinyusb-reattach-print-reset-time' into uat-xmas2024 2024-12-20 23:21:40 +00:00
tyeth
418e785c54 Merge remote-tracking branch 'upstream/status_led_brightness' into uat-xmas2024 2024-12-20 23:21:18 +00:00
tyeth
8b62a09914 Merge remote-tracking branch 'tyeth/WDT-RP2040-enable-after-wifi-connect' into uat-xmas2024 2024-12-20 23:21:01 +00:00
tyeth
bcd502d941 Merge remote-tracking branch 'upstream/pico2w' into uat-xmas2024 2024-12-20 23:19:36 +00:00
tyeth
e78470e4c7 Merge remote-tracking branch 'tyeth/wireless-rssi-sorting' into uat-xmas2024 2024-12-20 23:14:46 +00:00
tyeth
0de83b9925 Always show Wifi scan results (RSSI, channel, bssid) 2024-12-20 18:53:52 +00:00
Tyeth Gundry
9af386754d
Merge pull request #674 from adafruit/ci-nano-pb-failures
Check NanoPB failures and restore cache if needed
2024-12-20 18:11:47 +00:00
tyeth
24cf18051b Correct verbiage for RP2040 rather than Pico 2024-12-20 18:10:20 +00:00
tyeth
86936f2acf Move enableWDT to after wifi connection for all platforms 2024-12-20 18:08:47 +00:00
Tyeth Gundry
952ef3ce60
Check NanoPB failures and restore cache if needed 2024-12-20 17:50:17 +00:00
tyeth
34cd2bd7d9 Add VCNL4200 2024-12-19 22:38:44 +00:00
tyeth
b594a3b872 Add custom WDT timeout for ESP8266 2024-12-19 18:25:55 +00:00
tyeth
f87a2083ac Swap WDT timeout to milliseconds in haltError to match Arch differerences 2024-12-19 17:43:12 +00:00
tyeth
04dbf36da5 Parameterise the reset timeout for haltError 2024-12-19 17:15:46 +00:00
tyeth
9ddb1206d3 Use defined default + rem 2nd check of brightness 2024-12-19 17:02:40 +00:00
tyeth
2475f33072 RP2040 WDT=8.3secs - enable after wifi connect 2024-12-17 23:36:39 +00:00
tyeth
04f1c3cce1 USB Reattach fixes + Specify reset time remaining + secrets != 0xFF 2024-12-17 23:09:16 +00:00
tyeth
45461242f2 Report BSSID's to help distinguish wifi networks 2024-12-17 22:34:41 +00:00
tyeth
53ca34914f Stop blinding status lights 2024-12-17 22:08:19 +00:00
tyeth
e92cd181ec Add Pico2W definition to boards list + fix LEDs 2024-12-17 19:15:15 +00:00
tyeth
1ceafabf7a Swap RP2040 CI-Arduino branch back to ci-wippersnapper 2024-12-17 19:15:15 +00:00
tyeth
0f91cb9cfb Swap back to official repos since upstreaming 2024-12-17 19:15:15 +00:00
tyeth
9b8479425c Add .test.skip/.generate and CI test 2024-12-17 19:15:15 +00:00
tyeth
8ea03941be Add tinyusb to pico2w non debug target 2024-12-17 19:15:15 +00:00
tyeth
99ece2f7d3 Add RPi Pico2W build 2024-12-17 19:15:15 +00:00
Brent Rubell
16bc28af11
Merge pull request #667 from adafruit/patch-usb-msc-bug
Fix USB-MSC not re-attaching
2024-12-10 12:24:25 -06:00
brentru
2409c85e29 Address feedback 2024-12-10 13:07:06 -05:00
brentru
0a3e82204a re-attach USB msc bug 2024-12-09 11:53:24 -05:00
Tyeth Gundry
b5dd8ed474
Merge pull request #665 from mikeysklar/bme68x-pressure-units
bme68x pressure units
2024-12-06 18:35:26 +00:00
Mikey Sklar
3a66b011b0 bme68x pressure units
bme68x is show units as pascals.
2024-12-06 10:07:40 -08:00
Tyeth Gundry
b75aae3e2d
Merge pull request #662 from tyeth/wifi-testvar-fix
Update ConfigJson.cpp - set default password to blank and ssid to unset-ssid
2024-11-21 18:19:19 +00:00
Tyeth Gundry
ecc98848f2
Update Wippersnapper.h - bump version to 1.0.0-beta.94 2024-11-21 18:17:06 +00:00
Tyeth Gundry
b3b81e4944
Update library.properties - bump version to 1.0.0-beta.94 2024-11-21 18:16:32 +00:00
Tyeth Gundry
5fee86b9f0
Update ConfigJson.cpp - set default password to blank and ssid to unset-ssid 2024-11-21 17:46:25 +00:00
Tyeth Gundry
e898d1b51d
Update Wippersnapper.h - bump version to 1.0.0-beta.93 2024-11-15 20:13:46 +00:00
Tyeth Gundry
a1a4ff2ed4
Update library.properties - bump version to 1.0.0-beta.93 2024-11-15 20:08:42 +00:00
Tyeth Gundry
353b036d22
Merge pull request #652 from adafruit/add-nanopb-cache
Add caching for nanopb
2024-11-15 17:52:13 +00:00
Tyeth Gundry
0e9993b125
Merge pull request #635 from tyeth/use_analogReadMilliVolts-for-esp32-scaledAnalogRead-false
Use analogReadMilliVolts for esp32 and update hysteresis
2024-11-15 17:22:06 +00:00
Tyeth Gundry
18f08eb31a
Merge pull request #660 from thussaiththelaw/main
Added aht21 sensor to the drivers
2024-11-15 15:12:02 +00:00
tyeth
9c6187f41a Correct hysteresis and stop overflow 2024-11-14 15:25:50 +00:00
thussaiththelaw
0411093a49
Added aht21 sensor to the drivers
the aht21 uses the same library as the aht20, but a different i2c address is used so this needed to be added so the the aht21 sensor can be used.
2024-11-12 14:30:22 -07:00
tyeth
7b10b132ec Tweak passed arguments 2024-10-25 18:14:47 +01:00
tyeth
872a3f5d77 Cleanup + log thresholds 2024-10-25 18:14:47 +01:00
tyeth
2947fb63bb Add param to docstring 2024-10-25 18:14:47 +01:00
tyeth
265ce3d5b9 Refactor to calculateHysteresis 2024-10-25 18:14:47 +01:00
tyeth
0d4c7ef1d5 Switch Analog Voltage on esp32 to use analogReadMilliVolts and tweak hysteresis 2024-10-25 18:14:47 +01:00
tyeth
016e076550 Use dollar curly braces for evaluating ifs 2024-10-25 16:46:09 +01:00
tyeth
83721a01dc Correct failure negation 2024-10-25 16:13:10 +01:00
tyeth
d9adf25ed1 Only used cached NanoPB if necessary 2024-10-25 16:05:28 +01:00
Brent Rubell
270344d6cb
Merge pull request #654 from adafruit/qtpy-test-dbm
Reduce connection errors on QT Py ESP32-Sx due to 3D Antennas
2024-10-24 12:23:01 -05:00
brentru
6a2f67ae0b update platformio.ini to use 3.0.7 2024-10-24 13:06:33 -04:00
brentru
bd05dd2802 point workflow to arduino not tyeth! 2024-10-24 11:24:52 -04:00
brentru
7fe6cfa534 inclusion guard around dbm setter, for all qt py 2024-10-24 10:44:06 -04:00
Brent Rubell
63b812b4d9
Merge pull request #647 from tyeth/add-metro-s3
Add metro s3
2024-10-24 09:25:45 -05:00
brentru
45af854ed2 reduce dBm to 15dBm for all, for now, will need to ifdef guard 2024-10-23 19:09:29 -04:00
tyeth
453dc6d62c set to cache v4 2024-10-22 21:24:50 +01:00
tyeth
0760b45e44 Add caching for nanopb 2024-10-22 21:00:16 +01:00
brentru
7b419274ab bump to beta 92 2024-10-22 14:58:41 -04:00
Brent Rubell
db79e617f2
Merge pull request #651 from adafruit/test-c6-builds
Fix C6 Build
2024-10-22 13:57:47 -05:00
Brent Rubell
f0ebfd0e9c
Merge pull request #648 from adafruit/fix-release-task-extract-assets
Update release task to use nested build-files assets
2024-10-22 13:46:11 -05:00
brentru
3e48594c63 switch back to ci-arduino adafruit origin 2024-10-22 12:45:36 -04:00
brentru
c3bc657488 enforce matrix offset again 2024-10-22 12:40:18 -04:00
brentru
b0e8902675 0x0 fix 2024-10-22 12:08:42 -04:00
brentru
e3e09946ff drop all additions except esptool 4.6 2024-10-22 11:42:20 -04:00
brentru
d0dc679c5e use esptool 4.6 instead for esp32 platforms merge 2024-10-22 11:41:33 -04:00
brentru
5731ce2c56 keep offset 0x0 2024-10-22 11:16:57 -04:00
brentru
d8bc70ad24 keep 2024-10-22 11:16:30 -04:00
brentru
45ffc1e916 attempt to fill flash size 2024-10-22 10:36:28 -04:00
brentru
a999a73e9f print matrix offset 2024-10-21 17:13:53 -04:00
tyeth
3086e0d362 Rename Metro-S3 build targets to match ci-arduino 2024-10-21 21:36:25 +01:00
tyeth
9d3442c72d Correct build targets for S2/S3 debug 2024-10-21 21:36:25 +01:00
tyeth
92286c87ee Add platformIO entry + CI entries for Metro-S3/2 2024-10-21 21:36:24 +01:00
tyeth
0c3636cc69 Add support for Adafruit Metro ESP32-S3
Also add normal + debug CI builds for Metro S2+S3
2024-10-21 21:36:24 +01:00
brentru
9b2255ac1a add offset back for c6 and debug c6 2024-10-21 15:44:41 -04:00
Tyeth Gundry
800a87ebad
Merge pull request #649 from tyeth/update-staging-cert-2024-10-21
Update E5 cert for staging
2024-10-21 20:37:38 +01:00
Tyeth Gundry
f73d6fe941
Bump version to 91 2024-10-21 20:36:08 +01:00
brentru
9570cc583a fix offset attempt 2024-10-21 15:14:23 -04:00
Tyeth Gundry
1d10247540
Update E5 cert for staging 2024-10-21 18:17:53 +01:00
Tyeth Gundry
9844ee3ee7
Update release task to use nested build-files assets 2024-10-21 17:37:44 +01:00
Tyeth Gundry
13cd5b0ffb
Merge pull request #646 from adafruit/rev-tft-rename-skip-files
Add skips + generates for S3 Rev TFT debug
2024-10-18 20:25:38 +01:00
tyeth
04c39b0c34 Add skips + generates for S3 Rev TFT debug 2024-10-18 19:40:50 +01:00
Tyeth Gundry
e2045f0cd3
Merge pull request #645 from adafruit/set-rev-tft-debug-noota
Set debug build of s3-rev-tft to no_ota
2024-10-18 18:43:55 +01:00
Tyeth Gundry
ebc002a673
Set debug build of s3-rev-tft to no_ota 2024-10-18 18:31:45 +01:00
Tyeth Gundry
c0af0ade93
Merge pull request #643 from tyeth/new-pio-build-targets-funhouse-qtpys3n4r2-esp32s3devkitc
New pio build targets
2024-10-15 21:37:16 +01:00
Tyeth Gundry
e2815766d8
Merge pull request #607 from adafruit/598-preprocessor-script-for-printing-the-library-versions-to-boot_outtxt
Print the library versions to boot log
2024-10-15 19:57:07 +01:00
tyeth
86e05d2545 Remove blank line 2024-10-11 19:50:36 +01:00
tyeth
ebc522ffe4 Swap back to adafruit/ci-arduino 2024-10-11 19:44:56 +01:00
tyeth
d8c6b94b50 Cleanup espressif esp32s3 devkitc-1 target + add non-debug 2024-10-11 17:43:36 +01:00
brentru
66ab83ffa5 one . 2024-10-11 17:38:59 +01:00
brentru
13b1a3de3e build 2024-10-11 17:38:59 +01:00
brentru
dc73b7ddc8 build uf2 for examples/wippersnapper_debug/..feather_esp32s3_reverse_tft_debug.generate 2024-10-11 17:38:39 +01:00
brentru
3530c2eae9 skip debug build for this platform 2024-10-11 17:38:39 +01:00
brentru
8c66505a98 only debug this feather 2024-10-11 17:38:39 +01:00
brentru
cf3b61f81e build from brentru, add revtft debug target 2024-10-11 17:38:39 +01:00
Tyeth Gundry
30c871ef73 Switch to BSP 3.0.5 2024-10-11 17:38:39 +01:00
Tyeth Gundry
e0ebc7bb5e Add debug profile for qtpy_s3_n4r2 2024-10-11 17:38:39 +01:00
Tyeth Gundry
708b9de1f4 Add QTPY ESP32-S3 N4R2 2024-10-11 17:38:39 +01:00
tyeth
a12f51db9a Correct funhouse debug build flags 2024-10-11 17:38:39 +01:00
tyeth
d965898c7e WipperSnapper on Funhouse causes bootloop and crash.
Investigate #630
2024-10-11 17:38:39 +01:00
tyeth
2ef6d725e2 Print build dependencies on boot 2024-10-10 21:03:50 +01:00
Tyeth Gundry
901e2a4879
Merge pull request #631 from adafruit/fix-upload-download-artifact
Update Depreciated Workflow Action
2024-10-10 20:45:26 +01:00
Tyeth Gundry
d01e5d748d
Merge pull request #642 from adafruit/add-merge-to-fix-upload-download-artifact-v4
Add merge to fix upload download artifact v4
2024-10-10 20:44:51 +01:00
Tyeth Gundry
96af0e0a20
Update build-clang-doxy.yml 2024-10-10 17:19:06 +01:00
tyeth
7b51b5a41e fix one name + shorten SAMD-no-fs 2024-09-27 14:07:14 +01:00
tyeth
9dfccb6a47 Update action/andstor/file-existence-action to v3 2024-09-27 13:59:09 +01:00
tyeth
198a0e5226 Update actions/setup-python to v5 2024-09-27 13:57:16 +01:00
tyeth
574ad66ffd Add merge steps + fix c6 dev asset name 2024-09-27 13:37:51 +01:00
Tyeth Gundry
6e49411893
Merge pull request #623 from tyeth/add-HDC302x
Add HDC3021/HDC302x
2024-09-24 19:31:22 +01:00
Tyeth Gundry
06427ff916
Merge pull request #600 from adafruit/tweak-sgp30-init
Adjust SGP30 init to not call IAQinit unnecessarily
2024-09-24 19:30:50 +01:00
Tyeth Gundry
784a166af4
Merge pull request #632 from adafruit/scd30-read-data-at-once
Add retry if data not ready for SCD30
2024-09-24 19:30:33 +01:00
tyeth
2a0564b970 return true in a readable way for HDC302x 2024-09-24 18:01:09 +01:00
tyeth
d1898c962d Refactor SCD30 to improve readability 2024-09-24 17:50:00 +01:00
tyeth
8ee25a5fea format SCD30 2024-09-24 17:50:00 +01:00
tyeth
4eb816e2cc Add retry if data not ready for SCD30 2024-09-24 17:50:00 +01:00
tyeth
5d0241fd91 drop unnecessary call to _sgp30.IAQinit 2024-09-24 17:49:48 +01:00
tyeth
e1206880d9 Ignore first reading of HDC320x 2024-09-24 17:49:20 +01:00
Tyeth Gundry
0210209a94 Add HDC3021/HDC302x 2024-09-24 17:49:20 +01:00
Tyeth Gundry
2da710586f
Merge pull request #634 from adafruit/fix-funhouse-using-bsp-for-partition
fix funhouse build checking paths
2024-09-24 17:47:06 +01:00
tyeth
d286ff5899 fix funhouse build checking paths 2024-09-24 17:25:24 +01:00
Brent Rubell
47da59470d
Merge pull request #633 from adafruit/update-bcd-to-use-adafruit-ci
Update build action to build on adafruit/ci-arduino's new wippersnapper branch
2024-09-23 14:44:13 -05:00
brentru
3ab29705d0 Update action to build on adafruit/ci-arduino's new wippersnapper branch 2024-09-23 14:45:18 -04:00
brentru
9e9a19b359 update deprecated action, download artifact, to v4 2024-09-13 15:20:20 -04:00
brentru
bcb158093a fix gh release 2024-09-12 14:55:39 -04:00
brentru
41f2813956 release with v3 instead of v4 2024-09-12 14:54:54 -04:00
brentru
8c2978d378 update deprecated action download-artifact, bump other release action 2024-09-12 14:44:33 -04:00
Brent Rubell
1ab027e7b8
Merge pull request #629 from adafruit/patch-wifi-scan-issue
Fix WiFi Scan Issue
2024-09-12 13:29:47 -05:00
brentru
8f16b4fb6d push updated ref to all esp32x boards 2024-09-12 13:36:08 -04:00
brentru
a3d74c9c0b shorten names 2024-09-12 12:52:54 -04:00
brentru
9ecd9cae58 patch wifi scan issue 2024-09-12 11:27:26 -04:00
Brent Rubell
8e8ac1a85f
Merge pull request #626 from adafruit/fix-version-beta
Fix version to Beta 89
2024-09-05 13:58:28 -05:00
brentru
a429d9f429 push to beta 89 2024-09-05 14:49:32 -04:00
Brent Rubell
a751f1aade
Merge pull request #625 from adafruit/fix-fs-enumeration-bug
Fix TinyUSB Enumeration bug on ESP32-S3
2024-09-05 13:47:11 -05:00
brentru
420793d1d4 put back fs 2024-09-05 13:51:34 -04:00
brentru
76f3f6aa63 rm ws_ 2024-09-05 13:50:20 -04:00
brentru
ccb12e1e02 dont point esp32 there! 2024-09-05 12:59:26 -04:00
brentru
bde9d2f5fd point to new ref 2024-09-05 12:58:53 -04:00
brentru
1236bd025b point dev to new ref 2024-09-05 12:49:13 -04:00
brentru
b59f126dd0 wrong ref! 2024-09-05 12:23:33 -04:00
brentru
4e698782ea checkout ref 2024-09-05 12:19:19 -04:00
brentru
a5e68f0f8b add fix for tinyusb enumeration bug 2024-09-05 11:46:50 -04:00
Tyeth Gundry
59900023f6
Merge pull request #615 from adafruit/add-adafruit-feather-esp32c6
Add Adafruit Feather ESP32-C6
2024-08-20 21:22:17 +01:00
Tyeth Gundry
5c4dda0fe4 Prelease for C6 and comment/format platformio 2024-08-20 21:17:04 +01:00
tyeth
4e9cd30c00 Tweak debug builds for CI to drop _debug from board name 2024-08-20 18:50:13 +01:00
tyeth
b52f6ff976 Add C6 Debug target 2024-08-20 18:11:54 +01:00
tyeth
5f6b814aed Swap PIOArduino to develop 2024-08-20 18:11:43 +01:00
tyeth
176ff81433 Set CDC on and DebugLevel=Info for Feather C6 2024-08-20 17:28:53 +01:00
tyeth
d2e0d0929f Ignore OneWire and use OneWireNg 2024-08-14 19:45:19 +01:00
tyeth
ea3cc6205b Cleanup Espressif C6 build flags 2024-08-13 15:30:32 +01:00
tyeth
c7c441eda9 Temporarily switch OneWire to fork with C6 fix 2024-08-13 15:19:46 +01:00
tyeth
64d73b27ad Add Espressif C6 4mb PlatformIO target 2024-08-13 14:41:55 +01:00
tyeth
baa61c340c Add .test.skip and .genereate files for Feather C6 2024-08-13 14:00:07 +01:00
tyeth
9303d7b22a Specify offset arduino-platform's not as array 2024-08-13 13:49:19 +01:00
tyeth
b374aca37d Update build workflow to add C6 2024-08-13 13:44:15 +01:00
tyeth
97999e5eaa Initial adding of board def for C6 2024-08-13 13:10:35 +01:00
125 changed files with 5405 additions and 107667 deletions

File diff suppressed because it is too large Load diff

View file

@ -12,16 +12,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download build artifacts from build-platform steps
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
name: build-files
path: .
- name: List Files
run: ls
- name: Upload Assets to the GitHub Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
wippersnapper.*.uf2
wippersnapper.*.bin
wippersnapper.*.zip
build-files/wippersnapper.*.uf2
build-files/wippersnapper.*.bin
build-files/wippersnapper.*.zip

6
.gitignore vendored
View file

@ -48,4 +48,8 @@ examples/Wippersnapper_demo/build/
.pio/
# Secrets
data/
data/
# Misc. Data
tests/
venv/

View file

@ -5,5 +5,7 @@
},
"C_Cpp.dimInactiveRegions": true,
"dotnet.defaultSolution": "disable",
"cmake.configureOnOpen": false
"cmake.configureOnOpen": false,
"C_Cpp.clang_format_fallbackStyle": "Google",
"C_Cpp.clang_format_style": "file"
}

View file

@ -5,9 +5,9 @@
# Adafruit WipperSnapper
![Build CI](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/actions/workflows/build-clang-doxy.yml/badge.svg)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_Wippersnapper_Arduino/html/index.html)
Adafruit.io WipperSnapper is a firmware designed to turn any Wi-Fi capable board into an Internet-of-Things (IoT) device. No code required!
Adafruit.io WipperSnapper is a firmware designed to turn any Wi-Fi-capable board into an Internet-of-Things (IoT) device. No programming is required!
WipperSnapper works with multiple microcontroller architectures such as ESP8266, ESP32, ESP32-S2, ESP32-C3, RP2040, and ATSAMD51.
WipperSnapper works with multiple microcontroller architectures such as ESP8266, ESP32, ESP32-Sx, ESP32-Cx, RP2040, RP2350, and ATSAMD51.
You will need a **free** [Adafruit IO](https://io.adafruit.com) account to use WipperSnapper.
@ -16,17 +16,14 @@ You will need a **free** [Adafruit IO](https://io.adafruit.com) account to use W
# Get Started
[Learn how to install and use WipperSnapper by following this guide on the Adafruit Learning System - QuickStart: Adafruit IO WipperSnapper](https://learn.adafruit.com/quickstart-adafruit-io-wippersnapper).
## Get WipperSnapper
Pre-compiled binaries and UF2 files for supported hardware are provided on the [releases page](https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/releases) of this repository.
## Supported Platforms
|Platform| MCU(s) |
|--|--|
|[ESP32-x](https://github.com/espressif/arduino-esp32)| ESP32, ESP32-S2, ESP32-S3, ESP32-C3 |
|[ESP32-x](https://github.com/espressif/arduino-esp32)| ESP32, ESP32-Sx, ESP32-C3 |
|[ESP8266](https://github.com/esp8266/Arduino)| ESP8266 |
|[RP2040](https://github.com/earlephilhower/arduino-pico)| RP2040 MCU w/WiFi (i.e: Pico W) |
|[RP2350](https://github.com/earlephilhower/arduino-pico)| RP2350 MCU w/WiFi (i.e: Pico 2W) |
|[ATSAMD](https://github.com/adafruit/ArduinoCore-samd/)| SAMD51 MCU w/separate WiFi Co-Processor (i.e: Adafruit "AirLift")|
## Contributing to Adafruit.io and WipperSnapper

Binary file not shown.

View file

@ -1,45 +0,0 @@
// Adafruit IO WipperSnapper Beta
//
//
// NOTE: This software is a BETA release and in active development.
// Please report bugs or errors to
// https://github.com/adafruit/Adafruit_Wippersnapper_Arduino/issues
//
// This sketch is for devices which lack USB-MSD or LittleFS support such
// as the Arduino MKR WiFi 1010, Arduino Nano 33 IoT.
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Brent Rubell for Adafruit Industries, 2021
//
// All text above must be included in any redistribution.
#include "Wippersnapper_Networking.h"
/************************ Adafruit IO Config *******************************/
// Visit io.adafruit.com if you need to create an account,
// or if you need your Adafruit IO key.
#define IO_USERNAME "YOUR_AIO_USERNAME"
#define IO_KEY "YOUR_AIO_KEY"
/**************************** WiFi Config ***********************************/
#define WIFI_SSID "YOUR_WIFI_SSID"
#define WIFI_PASS "YOUR_WIFI_PASSWORD"
#include "Wippersnapper_Networking.h"
Wippersnapper_WiFi wipper(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
void setup() {
// Provisioning must occur prior to serial init.
wipper.provision();
Serial.begin(115200);
// while (!Serial) delay(10);
wipper.connect();
}
void loop() { wipper.run(); }

View file

@ -0,0 +1 @@

View file

@ -1,5 +1,5 @@
name=Adafruit WipperSnapper
version=1.0.0-beta.88
version=1.0.0-beta.111
author=Adafruit
maintainer=Adafruit <adafruitio@adafruit.com>
sentence=Arduino application for Adafruit.io WipperSnapper
@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper
category=Communication
url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino
architectures=*
depends=Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit INA219, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork
depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit MLX90632 Library, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit AS5600 Library, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306

View file

@ -6,7 +6,7 @@
; PlatformIO Defaults
[platformio]
description = "Adafruit.IO WipperSnapper Firmware"
default_envs = adafruit_feather_esp32s3_tft, adafruit_magtag29_esp32s2, adafruit_feather_esp32s3, featheresp32s2, adafruit_feather_esp32s2_reversetft, adafruit_metro_esp32s2, adafruit_qtpy_esp32s2, adafruit_feather_esp32s3_reversetft, adafruit_feather_esp32s3_nopsram, adafruit_feather_esp32s2_tft, adafruit_qtpy_esp32, adafruit_qtpy_esp32c3, featheresp32, adafruit_qtpy_esp32s3_nopsram, featheresp32v2, huzzah, adafruit_pyportal_m4, adafruit_pyportal_m4_titano
default_envs = adafruit_feather_esp32s3_tft, adafruit_magtag29_esp32s2, adafruit_feather_esp32s3, featheresp32s2, adafruit_feather_esp32s2_reversetft, adafruit_metro_esp32s2, adafruit_qtpy_esp32s2, adafruit_feather_esp32s3_reversetft, adafruit_feather_esp32s3_nopsram, adafruit_feather_esp32s2_tft, adafruit_qtpy_esp32, adafruit_qtpy_esp32c3, featheresp32, adafruit_qtpy_esp32s3_nopsram, featheresp32v2, huzzah, adafruit_pyportal_m4, adafruit_pyportal_m4_titano, dfrobot_beetle_esp32c3
; Common Build Environment
@ -16,20 +16,32 @@ framework = arduino
monitor_speed = 115200
lib_compat_mode = strict
lib_deps =
;;;;;;;;;;; FunHouse / LVGL Boards uncomment these ;;;;;;;;;;;;;;
; https://github.com/adafruit/Adafruit_HX8357_Library.git
; https://github.com/adafruit/Adafruit_ILI9341.git
; https://github.com/adafruit/Adafruit_STMPE610.git
; https://github.com/adafruit/Adafruit-ST7735-Library.git
; https://github.com/adafruit/Adafruit_TouchScreen.git
; https://github.com/brentru/lvgl.git#wippersnapper
; https://github.com/brentru/Adafruit_LvGL_Glue.git#development
;;;;;;;;;;; All Boards need these libraries included ;;;;;;;;;;;;;;
adafruit/Adafruit Zero DMA Library
adafruit/Adafruit TinyUSB Library
adafruit/Adafruit NeoPixel
adafruit/Adafruit SPIFlash
adafruit/Adafruit DotStar
adafruit/ENS160 - Adafruit Fork
adafruit/Adafruit SleepyDog Library
adafruit/Adafruit AHTX0
adafruit/Adafruit AS5600 Library
adafruit/Adafruit BME280 Library
adafruit/Adafruit BMP280 Library
adafruit/Adafruit BMP3XX Library
adafruit/Adafruit DPS310
adafruit/Adafruit DS248x
adafruit/Adafruit INA219
adafruit/Adafruit INA260 Library
adafruit/Adafruit INA237 and INA238 Library
adafruit/Adafruit HDC302x
adafruit/Adafruit HTS221
adafruit/Adafruit HTU21DF Library
adafruit/Adafruit HTU31D Library
@ -42,9 +54,11 @@ lib_deps =
adafruit/Adafruit Si7021 Library
adafruit/Adafruit VCNL4020 Library
adafruit/Adafruit VCNL4040
adafruit/Adafruit VCNL4200 Library
adafruit/Adafruit MCP3421
adafruit/Adafruit MCP9808 Library
adafruit/Adafruit MCP9600 Library
adafruit/Adafruit MLX90632 Library
adafruit/Adafruit MPL115A2
adafruit/Adafruit MPRLS Library
adafruit/Adafruit MS8607
@ -56,10 +70,10 @@ lib_deps =
stm32duino/STM32duino VL53L4CD
stm32duino/STM32duino VL53L4CX
adafruit/Adafruit_VL6180X
adafruit/Adafruit PM25 AQI Sensor
adafruit/Adafruit VEML7700 Library
adafruit/Adafruit LC709203F
adafruit/Adafruit LPS2X
adafruit/Adafruit LPS28
adafruit/Adafruit LPS35HW
adafruit/Adafruit seesaw Library
adafruit/Adafruit BME680 Library
@ -70,25 +84,41 @@ lib_deps =
adafruit/Adafruit TouchScreen
adafruit/Adafruit MQTT Library
bblanchon/ArduinoJson
https://github.com/PaulStoffregen/OneWire.git
adafruit/Adafruit LiquidCrystal
adafruit/Adafruit LED Backpack Library
adafruit/Adafruit PM25 AQI Sensor
adafruit/Adafruit SH110X
adafruit/Adafruit SSD1306
https://github.com/tyeth/omron-devhub_d6t-arduino.git
https://github.com/pstolarz/OneWireNg.git
; COMMENT OUT FOR RP2040/RP2350 BOARDS
https://github.com/milesburton/Arduino-Temperature-Control-Library.git
; AND UNCOMMENT FOR RP2040/RP2350 BOARDS
; https://github.com/pstolarz/Arduino-Temperature-Control-Library.git
https://github.com/Sensirion/arduino-sht.git
https://github.com/Sensirion/arduino-i2c-scd4x.git
https://github.com/Sensirion/arduino-i2c-sen5x.git
https://github.com/Sensirion/arduino-i2c-sen66.git
https://github.com/adafruit/WiFiNINA.git
https://github.com/Starmbi/hp_BH1750.git
https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git
; Common build environment for ESP32 platform
[common:esp32]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.03/platform-espressif32.zip
lib_ignore = WiFiNINA, WiFi101
platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip
;;Funhouse uses 3.0.7 of arduino-esp32 for now:
; platform = https://github.com/pioarduino/platform-espressif32/releases/download/51.03.07/platform-espressif32.zip
; This is needed for occasional new features and bug fixes
; platform = https://github.com/pioarduino/platform-espressif32#develop
lib_ignore = WiFiNINA, WiFi101, OneWire
monitor_filters = esp32_exception_decoder, time
; Common build environment for ESP8266 platform
[common:esp8266]
platform = espressif8266
lib_ignore = WiFiNINA, WiFi101, Adafruit TinyUSB Library
lib_ignore = WiFiNINA, WiFi101, Adafruit TinyUSB Library, OneWire
; Common build environment for Atmel/Microchip SAMDx platform
[common:atsamd]
@ -96,22 +126,20 @@ platform = atmelsam
platform_packages =
platformio/framework-arduino-samd-adafruit@^1.7.13
platformio/tool-jlink@^1.78811.0
lib_ldf_mode = deep
lib_ldf_mode = chain+
lib_compat_mode = strict
lib_archive = no ; debug timer issues see https://community.platformio.org/t/choose-usb-stack-as-tiny-usb/22451/5
lib_ignore = OneWire, USBHost
[common:rp2040]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
; platform_packages =
; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico
; framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
board = rpipicow
; Common build environment for Arduino-Pico platforms
[common:arduinopico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git
framework = arduino
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
build_flags = -DUSE_TINYUSB
; Once https://github.com/platformio/platformio-core > 6.1.11 these can be removed
lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library
lib_compat_mode = soft ; can be strict once pio detects SleepyDog on RP2040
lib_ignore = WiFiNINA, WiFi101, Adafruit Zero DMA Library, OneWire
lib_compat_mode = soft ; can be stricter once pio detects SleepyDog on RP2040
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Individual Board Definitions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -142,13 +170,43 @@ board = adafruit_itsybitsy_esp32
build_flags = -DARDUINO_ADAFRUIT_ITSYBITSY_ESP32
board_build.filesystem = littlefs
; Adafruit ESP32 Feather C6
[env:adafruit_feather_esp32c6_4mbflash_nopsram]
extends = common:esp32
board = adafruit_feather_esp32c6
build_flags =
-DARDUINO_ADAFRUIT_FEATHER_ESP32C6
-DARDUINO_USB_CDC_ON_BOOT=1
-DCORE_DEBUG_LEVEL=5
board_build.filesystem = littlefs
board_build.partitions = min_spiffs.csv
; Espressif ESP32-C6 4MB NO PSRAM esp32-c6-devkitm-1
[env:espressif_esp32-c6-devkitm-1]
extends = common:esp32
board = esp32-c6-devkitm-1
build_type = debug
build_flags =
-DARDUINO_ESPRESSIF_ESP32C6_DEVKITM_1
-DARDUINO_ADAFRUIT_FEATHER_ESP32C6
-DNDEBUG=1
-DDEBUG=1
-DESP_LOG_LEVEL=5
-DARDUINO_CORE_DEBUG_LEVEL=5
-DARDUINO_DEBUG_LEVEL=5
-DARDUINO_LOG_LEVEL=5
-DCORE_DEBUG_LEVEL=5
-DARDUHAL_LOG_LEVEL=5
board_build.filesystem = littlefs
board_build.partitions = min_spiffs.csv
; Adafruit Feather ESP32-S2
[env:featheresp32s2]
extends = common:esp32
board = featheresp32-s2
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2 -DBOARD_HAS_PSRAM
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S2 TFT
@ -156,7 +214,8 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s2_tft
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT -DBOARD_HAS_PSRAM
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S2 Reverse TFT
@ -164,7 +223,8 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s2_reversetft
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT -DBOARD_HAS_PSRAM
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S3 2MB PSRAM
@ -172,8 +232,8 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s3
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S3 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S3 NO PSRAM
@ -181,6 +241,7 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s3_nopsram
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S3_NOPSRAM
board_build.partitions = tinyuf2-partitions-8MB.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S3 TFT
@ -190,8 +251,8 @@ build_type = debug
debug_tool = esp-builtin
board = adafruit_feather_esp32s3_tft
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Feather ESP32-S3 Reverse TFT
@ -199,8 +260,8 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_feather_esp32s3_reversetft
build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Magtag ESP32-S2
@ -208,8 +269,8 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_magtag29_esp32s2
build_flags = -DARDUINO_MAGTAG29_ESP32S2 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Metro ESP32-S2
@ -217,8 +278,59 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_metro_esp32s2
build_flags = -DARDUINO_METRO_ESP32S2 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; debug_tool = jlink
; upload_protocol = jlink
; debug_init_break = tbreak WipperSnapper_I2C_Driver_MLX90632D
; Adafruit Metro ESP32-S3
[env:adafruit_metro_esp32s3]
extends = common:esp32
board = adafruit_metro_esp32s3
build_flags = -DARDUINO_METRO_ESP32S3 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-16MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-16MB.csv
extra_scripts = pre:rename_usb_config.py
debug_tool = jlink
; Adafruit Funhouse ESP32-S2
[env:adafruit_funhouse_esp32s2]
extends = common:esp32
board = adafruit_funhouse_esp32s2
build_flags = -DARDUINO_FUNHOUSE -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit Funhouse ESP32-S2
[env:adafruit_funhouse_esp32s2_debug]
extends = common:esp32
board = adafruit_funhouse_esp32s2
;lib_extra_dirs =
build_type = debug
build_flags =
-DARDUINO_FUNHOUSE
-DBOARD_HAS_PSRAM
-DCFG_TUSB_DEBUG=1
-DDEBUG=1
-DESP_LOG_LEVEL=ESP_LOG_VERBOSE
-DARDUINO_CORE_DEBUG_LEVEL=5
-DCORE_DEBUG_LEVEL=5
-DARDUHAL_LOG_LEVEL=5
; USB Configuration
; Uncomment if USB CDC on boot is needed
; -DARDUINO_USB_CDC_ON_BOOT=1
; -DARDUINO_USB_MODE=0 ; 0 for CDC + TinyUSB, 1 for Hardware CDC + JTAG
; LVGL Debugging
-DLV_USE_DEBUG=1
-DLV_USE_LOG=1
-DLV_LOG_PRINTF=1
-DLV_LOG_COLOR=1
-DLV_LOG_LEVEL=LV_LOG_LEVEL_TRACE
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit QT Py ESP32 Pico
@ -230,6 +342,22 @@ board_build.filesystem = littlefs
build_type = debug
build_flags = -DARDUINO_ADAFRUIT_QTPY_ESP32
; Adafruit Mini Sparkle Motion
[env:adafruit_sparklemotionmini_esp32]
extends = common:esp32
board = adafruit_sparklemotionmini_esp32
board_build.partitions = min_spiffs.csv
board_build.filesystem = littlefs
build_flags = -DARDUINO_SPARKLEMOTIONMINI_ESP32
; Adafruit Sparkle Motion Stick
[env:adafruit_sparklemotionstick_esp32]
extends = common:esp32
board = adafruit_sparklemotionstick_esp32
board_build.partitions = min_spiffs.csv
board_build.filesystem = littlefs
build_flags = -DARDUINO_SPARKLEMOTIONSTICK_ESP32
; Adafruit QT Py ESP32-C3
[env:adafruit_qtpy_esp32c3]
extends = common:esp32
@ -243,8 +371,8 @@ board_build.partitions = min_spiffs.csv
extends = common:esp32
board = adafruit_qtpy_esp32s2
build_flags = -DARDUINO_ADAFRUIT_QTPY_ESP32S2 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1
board_build.partitions = tinyuf2-partitions-4MB.csv
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit QT Py ESP32-S3 NO PSRAM
@ -252,36 +380,109 @@ extra_scripts = pre:rename_usb_config.py
extends = common:esp32
board = adafruit_qtpy_esp32s3_nopsram
build_flags = -DARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM
board_build.partitions = tinyuf2-partitions-8MB.csv
extra_scripts = pre:rename_usb_config.py
; Adafruit QT Py ESP32-S3 with PSRAM
[env:adafruit_qtpy_esp32s3_with_psram]
extends = common:esp32
board = adafruit_qtpy_esp32s3_n4r2
build_flags = -DARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2 -DBOARD_HAS_PSRAM
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
extra_scripts = pre:rename_usb_config.py
[env:adafruit_qtpy_esp32s3_with_psram_debug]
extends = common:esp32
board = adafruit_qtpy_esp32s3_n4r2
;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10
board_build.partitions = tinyuf2-partitions-4MB-noota.csv
build_type = debug
build_flags =
-DARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2
-DBOARD_HAS_PSRAM
-DCFG_TUSB_DEBUG=1
-DNDEBUG=1
-DDEBUG=1
-DESP_LOG_LEVEL=5
-DARDUINO_CORE_DEBUG_LEVEL=5
-DARDUINO_DEBUG_LEVEL=5
# -DARDUINO_DEBUG_OUTPUT=Serial
# -DARDUINO_DEBUG_BAUD=115200
-DARDUINO_USB_CDC_ON_BOOT=1
; cdc + usb otg (tinyusb)
-DARDUINO_USB_MODE=0
; hwcdc jtag
;-DARDUINO_USB_MODE=1
-DARDUINO_LOG_LEVEL=5
-DCORE_DEBUG_LEVEL=5
-DARDUHAL_LOG_LEVEL=5
extra_scripts = pre:rename_usb_config.py
; Espressif ESP32-S3 NO PSRAM espressif_esp32s3_devkitc_1_n8
[env:espressif_esp32s3_devkitc_1_n8]
extends = common:esp32
board = esp32-s3-devkitc-1
build_flags = -DARDUINO_ESPRESSIF_ESP32S3_DEVKITC_1_N8 -DUSE_TINYUSB=1 -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=1
board_build.partitions = noota_ffat.csv
; board_build.partitions = tinyuf2-partitions-8MB.csv
; extra_scripts = pre:rename_usb_config.py
; Espressif ESP32-S3 NO PSRAM espressif_esp32s3_devkitc_1_n8 (DEBUG)
[env:espressif_esp32s3_devkitc_1_n8_debug]
extends = common:esp32
board = esp32-s3-devkitc-1
build_type = debug
build_flags =
build_flags =
-DUSE_TINYUSB=1
-DARDUINO_USB_MODE=0
-DARDUINO_USB_CDC_ON_BOOT=1
-DARDUINO_ESPRESSIF_ESP32S3_DEVKITC_1_N8
-DNDEBUG=1
-DDEBUG=1
-DESP_LOG_LEVEL=5
-DARDUINO_CORE_DEBUG_LEVEL=5
-DARDUINO_DEBUG_LEVEL=5
; -DARDUINO_DEBUG_OUTPUT=Serial
; -DARDUINO_DEBUG_BAUD=115200
-DARDUINO_CORE_LOG_LEVEL=5
-DARDUINO_LOG_LEVEL=5
-DCORE_DEBUG_LEVEL=5
-DARDUHAL_LOG_LEVEL=5
; board_build.partitions = tinyuf2-partitions-8MB.csv
board_build.partitions = noota_ffat.csv
; extra_scripts = pre:rename_usb_config.py
; Seeed Studio ESP32 boards:
; Xiao ESP32S3 N8R8 (SENSE)
[env:seeed-xiao_esp32s3_n8r8]
extends = common:esp32
board = seeed_xiao_esp32s3
build_flags = -DARDUINO_XIAO_ESP32S3 -DUSE_TINYUSB -DBOARD_HAS_PSRAM -DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_MODE=0
board_build.partitions = tinyuf2-partitions-8MB.csv
extra_scripts = pre:rename_usb_config.py
; ESP8266 Boards
; Adafruit Feather HUZZAH ESP8266
[env:huzzah]
extends=common:esp8266
board = huzzah
build_flags = -DARDUINO_ESP8266_ADAFRUIT_HUZZAH
board_build.f_cpu = 80000000L
; Arduino CLI uses this from adafruit_ci#ci-wippersnapper
; esp8266:esp8266:huzzah:xtal=80,vt=flash,exception=disabled,stacksmash=disabled,ssl=all,mmu=3232,non32xfer=fast,eesz=4M2M,ip=lm2f,dbg=Disabled,lvl=None____,wipe=none,baud=115200
build_flags =
-Wl,--gc-sections
-Wl,-Map=output.map
-DARDUINO_ESP8266_ADAFRUIT_HUZZAH
-DDEBUG_ESP_PORT=Serial
-DVTABLES_IN_FLASH
-DNO_EXCEPTIONS
-DNO_STACK_SMASH_PROTECTION
-DSSL_ALL
-DMMU_3232
-DNON32XFER_FAST
-DDEBUG_DISABLED
-DDEBUG_LEVEL_NONE
board_build.eesz=4M2M
board_build.filesystem = littlefs
upload_port = /dev/cu.SLAB_USBtoUART
@ -291,8 +492,9 @@ upload_port = /dev/cu.SLAB_USBtoUART
[env:adafruit_pyportal_m4]
extends = common:atsamd
board = adafruit_pyportal_m4
build_flags = -DUSE_TINYUSB=1
build_flags = -DUSE_TINYUSB
-DADAFRUIT_PYPORTAL
extra_scripts = pre:rename_usb_config.py
; Adafruit PyPortal M4 Titano
[env:adafruit_pyportal_m4_titano]
@ -308,13 +510,13 @@ monitor_port = auto
; debug_init_break = tbreak clearConfiguration
lib_ignore = USBHost
build_flags = -DUSE_TINYUSB
-D__SAMD51J20A__
-DCRYSTALLESS
-DADAFRUIT_PYPORTAL_M4_TITANO
-D__SAMD51__
-D__FPU_PRESENT
-DARM_MATH_CM4
-mfloat-abi=hard
-D__SAMD51J20A__
-DCRYSTALLESS
-DADAFRUIT_PYPORTAL_M4_TITANO
-D__SAMD51__
-D__FPU_PRESENT
-DARM_MATH_CM4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-DCORE_DEBUG_LEVEL=5
-DARDUINO_USB_CDC_ON_BOOT=1
@ -336,17 +538,39 @@ build_flags = -DUSE_TINYUSB
[env:adafruit_metro_m4_airliftlite]
extends = common:atsamd
board = adafruit_metro_m4_airliftlite
build_flags = -DUSE_TINYUSB=1
build_flags = -DUSE_TINYUSB
-DADAFRUIT_METRO_M4_AIRLIFT_LITE
; extra_scripts = pre:rename_usb_config.py
upload_port = /dev/cu.usbmodem1201
; DFRobot Beetle ESP32-C3
[env:dfrobot_beetle_esp32c3]
extends = common:esp32
board = dfrobot_beetle_esp32c3
; Note: this board reuses a generic preprocessor define
; espressif/arduino-esp32@fcd4799c6de6eb5a5a8eba94818adf770238ecc0
; rather than creating one unique to the device.
build_flags = -DARDUINO_ESP32C3_DEV
board_build.filesystem = littlefs
board_build.partitions = min_spiffs.csv
[env:raspberypi_picow]
extends = common:rp2040
extends = common:arduinopico
board = rpipicow
build_flags =
-DUSE_TINYUSB
[env:raspberypi_picow_debug_port_only]
extends = common:arduinopico
board = rpipicow
build_flags =
-DUSE_TINYUSB
-DDEBUG_RP2040_PORT=Serial
[env:raspberypi_picow_debug]
extends = common:rp2040
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
extends = common:arduinopico
; platform = https://github.com/maxgerhardt/platform-raspberrypi.git
; platform_packages =
; framework-arduinopico @ symlink:///Users/tyeth/Projects/arduino-pico
; framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#master
@ -367,7 +591,7 @@ build_flags =
-DDEBUG_RP2040_CORE
-DDEBUG_RP2040_WIFI
-DNDEBUG
-DLWIP_DEBUG
-DLWIP_DEBUG=1
-DDEBUG_RP2040_PORT=Serial1
-DDEBUG_RP2040_UART_1
-DDEBUG_RP2040_UART=1
@ -384,4 +608,64 @@ build_flags =
; ; No USB stack
; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
[env:raspberypi_pico2w]
extends = common:arduinopico
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#develop
platform_packages =
framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git
board = rpipico2w
build_flags =
-DWIFICC=CYW43_COUNTRY_UK
-DUSE_TINYUSB
; -DARDUINO_ARCH_RP2040
; -DUSBD_MAX_POWER_MA=250
; -DPICO_CYW43_SUPPORTED=1
[env:raspberypi_pico2w_debug]
extends = common:arduinopico
board = rpipico2w
build_type = debug
framework = arduino
debug_tool = cmsis-dap
upload_protocol = cmsis-dap
; board can use both Arduino cores -- we select Arduino-Pico here
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
debug_init_break = tbreak runNetFSM
build_flags =
; -UARDUINO
; -DPICO_BUILD
-DARDUINO_ARCH_RP2040
-DUSBD_MAX_POWER_MA=250
-DPICO_CYW43_SUPPORTED=1
-DWIFICC=CYW43_COUNTRY_UK
; -DDEBUG
; -DDEBUG_RP2040_WIRE
; -DDEBUG_RP2040_SPI
; -DDEBUG_RP2040_CORE
; -DDEBUG_RP2040_WIFI
; -DNDEBUG
; -DLWIP_DEBUG
; -DDEBUG_RP2040_PORT=Serial1
; -DDEBUG_RP2040_UART_1
; -DDEBUG_RP2040_UART=1
-Og
; Enable debug stack protection
-fstack-protector
; Enable Exceptions
-DPIO_FRAMEWORK_ARDUINO_ENABLE_EXCEPTIONS
; Enable RTTI
-DPIO_FRAMEWORK_ARDUINO_ENABLE_RTTI
; ; Enable default USB Stack of Pico SDK USB Stack with none of below usb options
; Adafruit TinyUSB
-DUSE_TINYUSB
; ; No USB stack
; build_flags = -DPIO_FRAMEWORK_ARDUINO_NO_USB
; -DPIO_FRAMEWORK_ARDUINO_ENABLE_IPV6
[env:adafruit_fruitjam]
board = adafruit_fruitjam
lib_ignore = WiFi, WiFi101, Adafruit Zero DMA Library
build_flags = -DUSE_TINYUSB -DADAFRUIT_FRUITJAM_RP2350

View file

@ -108,7 +108,9 @@ void Wippersnapper::provision() {
#ifdef USE_DISPLAY
// Initialize the display
displayConfig config;
WS._fileSystem->parseDisplayConfig(config);
if (!WS._fileSystem->parseDisplayConfig(config)) {
WS._fileSystem->parseDisplayConfig(config, true);
}
WS._display = new ws_display_driver(config);
// Begin display
if (!WS._display->begin()) {
@ -174,7 +176,7 @@ void Wippersnapper::_disconnect() {
/****************************************************************************/
/*!
@brief Sets the network interface's unique identifer, typically the
@brief Sets the network interface's unique identifier, typically the
MAC address.
*/
/****************************************************************************/
@ -254,7 +256,7 @@ bool Wippersnapper::check_valid_ssid() {
/*!
@brief Configures the device's Adafruit IO credentials. This method
should be used only if filesystem-backed provisioning is
not avaliable.
not available.
*/
/****************************************************************************/
void Wippersnapper::set_user_key() {
@ -491,7 +493,7 @@ bool cbSignalMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) {
/**************************************************************************/
/*!
@brief Decodes a signal buffer protobuf message.
NOTE: Should be executed in-order after a new _buffer is recieved.
NOTE: Should be executed in-order after a new _buffer is received.
@param encodedSignalMsg
Encoded signal message.
@return true if successfully decoded signal message, false otherwise.
@ -871,6 +873,28 @@ bool cbDecodeSignalRequestI2C(pb_istream_t *stream, const pb_field_t *field,
if (!encodeI2CResponse(&msgi2cResponse)) {
return false;
}
} else if (field->tag ==
wippersnapper_signal_v1_I2CRequest_req_i2c_device_out_write_tag) {
WS_DEBUG_PRINTLN("[app] I2C Device Output Write");
// Decode stream into an I2CDeviceDeinitRequest
wippersnapper_i2c_v1_I2CDeviceOutputWrite msgDeviceWrite =
wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_zero;
// Decode stream into struct, msgI2CDeviceDeinitRequest
if (!ws_pb_decode(stream, wippersnapper_i2c_v1_I2CDeviceOutputWrite_fields,
&msgDeviceWrite)) {
WS_DEBUG_PRINTLN(
"[app] ERROR: Failed decoding I2CDeviceOutputWrite message.");
return false;
}
if (!WS._i2cPort0->Handle_I2cDeviceOutputWrite(&msgDeviceWrite)) {
WS_DEBUG_PRINTLN("[app] ERROR: Failed to write to I2C output device.");
return false; // fail out if we can't decode, we don't have a response to
// publish
}
WS_DEBUG_PRINTLN("[app] I2C Device Output Write Done");
return true; // we successfully wrote to the device, this subtype has no
// response to publish to IO
} else {
WS_DEBUG_PRINTLN("ERROR: Undefined I2C message tag");
return false; // fail out, we didn't encode anything to publish
@ -1065,7 +1089,7 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field,
/**************************************************************************/
/*!
@brief Called when the device recieves a new message from the
@brief Called when the device receives a new message from the
/servo/ topic.
@param data
Incoming data from MQTT broker.
@ -1191,7 +1215,7 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) {
#endif
return false; // fail out if we can't decode the request
}
// execute PWM pin detatch request
// execute PWM pin detach request
char *pwmPin = msgPWMDetachRequest.pin + 1;
WS._pwmComponent->detach(atoi(pwmPin));
@ -1274,7 +1298,7 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) {
/**************************************************************************/
/*!
@brief Called when the device recieves a new message from the
@brief Called when the device receives a new message from the
/pwm/ topic.
@param data
Incoming data from MQTT broker.
@ -1477,7 +1501,7 @@ bool cbDecodePixelsMsg(pb_istream_t *stream, const pb_field_t *field,
/**************************************************************************/
/*!
@brief Called when the device recieves a new message from the
@brief Called when the device receives a new message from the
/pixels/ topic.
@param data
Incoming data from MQTT broker.
@ -2494,14 +2518,27 @@ void Wippersnapper::runNetFSM() {
@brief Prints an error to the serial and halts the hardware until
the WDT bites.
@param error
The desired error to print to serial.
The error to print to serial.
@param ledStatusColor
The desired color to blink.
The color to blink.
@param seconds_until_reboot
The amount of time to wait before rebooting.
*/
/**************************************************************************/
void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) {
for (;;) {
WS_DEBUG_PRINT("ERROR [WDT RESET]: ");
void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor,
int seconds_until_reboot) {
#ifdef ARDUINO_ARCH_ESP8266
int wdt_timeout_ms = 3200;
#else
int wdt_timeout_ms = 5000;
#endif
int seconds_until_wdt_enable =
seconds_until_reboot - (int)(wdt_timeout_ms / 1000);
for (int i = 0;; i++) {
WS_DEBUG_PRINT("ERROR [WDT RESET IN ");
WS_DEBUG_PRINT(seconds_until_reboot - i);
WS_DEBUG_PRINTLN("]: ");
WS_DEBUG_PRINTLN(error);
// let the WDT fail out and reset!
statusLEDSolid(ledStatusColor);
@ -2512,6 +2549,12 @@ void Wippersnapper::haltError(String error, ws_led_status_t ledStatusColor) {
// hardware and software watchdog timers, delayMicroseconds does not.
delayMicroseconds(1000000);
#endif
if (i < seconds_until_wdt_enable) {
yield();
WS.feedWDT(); // feed the WDT for the first X-5 seconds
} else if (i == seconds_until_reboot) {
WS.enableWDT(wdt_timeout_ms);
}
}
}
@ -2693,7 +2736,7 @@ void print_reset_reason(int reason) {
break; /**<13, RTC Watch dog Reset CPU*/
case 14:
WS_DEBUG_PRINTLN("EXT_CPU_RESET");
break; /**<14, for APP CPU, reseted by PRO CPU*/
break; /**<14, for APP CPU, reset by PRO CPU*/
case 15:
WS_DEBUG_PRINTLN("RTCWDT_BROWN_OUT_RESET");
break; /**<15, Reset when the vdd voltage is not stable*/
@ -2748,15 +2791,12 @@ void Wippersnapper::connect() {
// Dump device info to the serial monitor
printDeviceInfo();
// enable global WDT
WS.enableWDT(WS_WDT_TIMEOUT);
// Generate device identifier
if (!generateDeviceUID()) {
haltError("Unable to generate Device UID");
}
// Initialize MQTT client with device identifer
// Initialize MQTT client with device identifier
setupMQTTClient(_device_uid);
WS_DEBUG_PRINTLN("Generating device's MQTT topics...");
@ -2772,7 +2812,9 @@ void Wippersnapper::connect() {
WS_DEBUG_PRINTLN("Running Network FSM...");
// Run the network fsm
runNetFSM();
WS.feedWDT();
// Enable WDT after wifi connection as wifiMulti doesnt feed WDT
WS.enableWDT(WS_WDT_TIMEOUT);
#ifdef USE_DISPLAY
WS._ui_helper->set_load_bar_icon_complete(loadBarIconCloud);
@ -2796,7 +2838,6 @@ void Wippersnapper::connect() {
#endif
// Configure hardware
WS.pinCfgCompleted = false;
while (!WS.pinCfgCompleted) {
WS_DEBUG_PRINTLN(
"Polling for message containing hardware configuration...");

View file

@ -9,7 +9,7 @@
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2020-2024 for Adafruit Industries.
* Copyright (c) Brent Rubell 2020-2025 for Adafruit Industries.
*
* BSD license, all text here must be included in any redistribution.
*
@ -142,7 +142,7 @@
#endif
#define WS_VERSION \
"1.0.0-beta.88" ///< WipperSnapper app. version (semver-formatted)
"1.0.0-beta.111" ///< WipperSnapper app. version (semver-formatted)
// Reserved Adafruit IO MQTT topics
#define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic
@ -214,7 +214,12 @@ typedef enum {
FSM_NET_ESTABLISH_MQTT,
} fsm_net_t;
#define WS_WDT_TIMEOUT 60000 ///< WDT timeout
#ifdef ARDUINO_ARCH_RP2040
#define WS_WDT_TIMEOUT 8388 ///< RP2040 Max WDT timeout
#else
#define WS_WDT_TIMEOUT 60000 ///< WDT timeout
#endif
#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks
/* MQTT Configuration */
#define WS_KEEPALIVE_INTERVAL_MS \
@ -306,7 +311,8 @@ public:
// Error handling helpers
void haltError(String error,
ws_led_status_t ledStatusColor = WS_LED_STATUS_ERROR_RUNTIME);
ws_led_status_t ledStatusColor = WS_LED_STATUS_ERROR_RUNTIME,
int seconds_until_reboot = 25);
void errorWriteHang(String error);
// MQTT topic callbacks //

View file

@ -51,6 +51,22 @@
#define STATUS_NEOPIXEL_PIN 45
#define STATUS_NEOPIXEL_NUM 1
#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation
#elif defined(ARDUINO_ESP32S3_DEV)
#define BOARD_ID "esp32s3-devkitc-1-n8"
#define USE_TINYUSB
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN 48
#define STATUS_NEOPIXEL_NUM 1
#ifdef BOARD_HAS_PSRAM
#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation
#endif
#elif defined(ARDUINO_METRO_ESP32S3)
#define BOARD_ID "metroesp32s3"
#define USE_TINYUSB
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN 46
#define STATUS_NEOPIXEL_NUM 1
#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation
#elif defined(ARDUINO_MAGTAG29_ESP32S2)
#define BOARD_ID "magtag"
#define USE_TINYUSB
@ -150,6 +166,12 @@
#define USE_LITTLEFS
#define USE_STATUS_LED
#define STATUS_LED_PIN 13
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32C6)
#define BOARD_ID "feather-esp32c6"
#define USE_LITTLEFS
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL
#define STATUS_NEOPIXEL_NUM 1
#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32_V2)
#define BOARD_ID "feather-esp32-v2"
#define USE_LITTLEFS
@ -164,19 +186,49 @@
#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL
#define STATUS_NEOPIXEL_NUM 1
#define USE_PSRAM ///< Board has PSRAM, use it for dynamic memory allocation
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
#define BOARD_ID "nano-33-iot"
#elif defined(ARDUINO_ESP32C3_DEV)
// Note: this board reuses a generic preprocessor define
// espressif/arduino-esp32@fcd4799c6de6eb5a5a8eba94818adf770238ecc0
// rather than creating one unique to the device.
#define BOARD_ID "dfrobot-beetle-esp32c3"
#define USE_LITTLEFS
#define USE_STATUS_LED
#define STATUS_LED_PIN 13
#elif defined(ARDUINO_SAMD_MKRWIFI1010)
#define BOARD_ID "mkrwifi1010"
#define USE_STATUS_LED
#define STATUS_LED_PIN 6
#define STATUS_LED_PIN LED_BUILTIN
#elif defined(ARDUINO_SPARKLEMOTIONMINI_ESP32)
#define BOARD_ID "sparklemotionmini-esp32"
#define USE_LITTLEFS
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL
#define STATUS_NEOPIXEL_NUM 1
#elif defined(ARDUINO_SPARKLEMOTIONSTICK_ESP32)
#define BOARD_ID "sparklemotionstick-esp32"
#define USE_LITTLEFS
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL
#define STATUS_NEOPIXEL_NUM 1
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
#define BOARD_ID "rpi-pico-w"
#define USE_TINYUSB
#define USE_STATUS_LED
#define STATUS_LED_PIN 32
#define STATUS_LED_PIN LED_BUILTIN
#elif defined(ARDUINO_RASPBERRY_PI_PICO_2W)
#define BOARD_ID "rpi-pico-2w"
#define USE_TINYUSB
#define USE_STATUS_LED
#define STATUS_LED_PIN LED_BUILTIN
#elif defined(ARDUINO_XIAO_ESP32S3)
#define BOARD_ID "xiao-esp32s3"
#define BOARD_HAS_PSRAM
#define USE_PSRAM
#define USE_TINYUSB
#define USE_STATUS_LED
#define STATUS_LED_PIN LED_BUILTIN
#elif defined(ARDUINO_ADAFRUIT_FRUITJAM_RP2350)
#define BOARD_ID "fruitjam"
#define USE_TINYUSB
#define USE_STATUS_NEOPIXEL
#define STATUS_NEOPIXEL_PIN PIN_NEOPIXEL
#define STATUS_NEOPIXEL_NUM 5
#else
#warning "Board type not identified within Wippersnapper_Boards.h!"
#endif

View file

@ -1,44 +1,46 @@
/*!
* @file Wippersnapper_Networking.h
*
* This file includes network interfaces at compile-time.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries.
*
* BSD license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_NETWORKING_H
#define WIPPERSNAPPER_NETWORKING_H
#if defined(ADAFRUIT_METRO_M4_EXPRESS) || \
defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \
defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT)
#include "network_interfaces/Wippersnapper_AIRLIFT.h"
/** Nina-FW (adafruit fork) networking class */
typedef Wippersnapper_AIRLIFT Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_ESP8266)
#include "network_interfaces/Wippersnapper_ESP8266.h"
/** ESP8266's networking class */
typedef Wippersnapper_ESP8266 Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_ESP32)
#include "network_interfaces/Wippersnapper_ESP32.h"
/** ESP32's networking class */
typedef Wippersnapper_ESP32 Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_RP2040)
#include "network_interfaces/ws_networking_pico.h"
typedef ws_networking_pico Wippersnapper_WiFi;
#elif defined(ARDUINO_SAMD_NANO_33_IOT) || defined(ARDUINO_SAMD_MKRWIFI1010)
/** Nina-FW (arduino) networking class */
#include "network_interfaces/Wippersnapper_WIFININA.h"
typedef Wippersnapper_WIFININA Wippersnapper_WiFi;
#else
#warning "Must define network interface in config.h!"
#endif
/*!
* @file Wippersnapper_Networking.h
*
* This file includes network interfaces at compile-time.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries.
*
* BSD license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_NETWORKING_H
#define WIPPERSNAPPER_NETWORKING_H
#ifndef WL_MAC_ADDR_LENGTH
#define WL_MAC_ADDR_LENGTH 6 ///< MAC address length - from RP2040 BSP
#endif
#define WS_MAX_ALT_WIFI_NETWORKS 3 ///< Maximum number of alternative networks
#if defined(ADAFRUIT_METRO_M4_EXPRESS) || \
defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) || defined(ADAFRUIT_PYPORTAL) || \
defined(ADAFRUIT_PYPORTAL_M4_TITANO) || defined(USE_AIRLIFT) || \
defined(ADAFRUIT_FRUITJAM_RP2350)
#include "network_interfaces/Wippersnapper_AIRLIFT.h"
/** Nina-FW (adafruit fork) networking class */
typedef Wippersnapper_AIRLIFT Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_ESP8266)
#include "network_interfaces/Wippersnapper_ESP8266.h"
/** ESP8266's networking class */
typedef Wippersnapper_ESP8266 Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_ESP32)
#include "network_interfaces/Wippersnapper_ESP32.h"
/** ESP32's networking class */
typedef Wippersnapper_ESP32 Wippersnapper_WiFi;
#elif defined(ARDUINO_ARCH_RP2040)
#include "network_interfaces/ws_networking_pico.h"
typedef ws_networking_pico Wippersnapper_WiFi;
#else
#warning "Must define network interface in config.h!"
#endif
#endif // WIPPERSNAPPER_NETWORKING_H

View file

@ -87,8 +87,13 @@ void Wippersnapper_AnalogIO::setADCResolution(int resolution) {
analogReadResolution(16);
_nativeResolution = 12;
#elif defined(ARDUINO_ARCH_ESP32)
scaleAnalogRead = true;
_nativeResolution = 13;
scaleAnalogRead = false; // handled in bsp (analogReadResolution)
analogReadResolution(resolution); // 16 bit values (shifted from 12 or 13bit)
#if defined(ESP32S3)
_nativeResolution = 13; // S3 ADC is 13-bit, others are 12-bit
#else
_nativeResolution = 12;
#endif
#elif defined(ARDUINO_ARCH_RP2040)
scaleAnalogRead = true;
_nativeResolution = 10;
@ -96,7 +101,6 @@ void Wippersnapper_AnalogIO::setADCResolution(int resolution) {
scaleAnalogRead = true;
_nativeResolution = 10;
#endif
_adcResolution = resolution;
}
@ -232,8 +236,12 @@ uint16_t Wippersnapper_AnalogIO::getPinValue(int pin) {
*/
/**********************************************************/
float Wippersnapper_AnalogIO::getPinValueVolts(int pin) {
#ifdef ARDUINO_ARCH_ESP32
return analogReadMilliVolts(pin) / 1000.0;
#else
uint16_t rawValue = getPinValue(pin);
return rawValue * getAref() / 65536;
#endif
}
/******************************************************************/
@ -303,6 +311,52 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
return true;
}
/**********************************************************/
/*!
@brief Calculates the hysteresis for the pin value.
@param pin
The desired analog pin to calculate hysteresis for.
@param pinValRaw
The pin's raw value.
@param pinValThreshHi
The pin's high threshold value.
@param pinValThreshLow
The pin's low threshold value.
*/
/**********************************************************/
void calculateHysteresis(analogInputPin pin, uint16_t pinValRaw,
uint16_t &pinValThreshHi, uint16_t &pinValThreshLow) {
// All boards ADC values scaled to 16bit, in future we may need to
// adjust dynamically
uint16_t maxDecimalValue = 65535;
// Calculate threshold values - using DEFAULT_HYSTERISIS for first third
// (1/3) of the range, then 2x DEFAULT_HYSTERISIS for the middle 1/3,
// and 4x DEFAULT_HYSTERISIS for the last 1/3. This should allow a more
// wifi blip tolerant threshold for the both ends of the range.
float CURRENT_HYSTERISIS;
if (pinValRaw < maxDecimalValue / 3) {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS;
} else if (pinValRaw < (maxDecimalValue / 3) * 2) {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 2;
} else {
CURRENT_HYSTERISIS = maxDecimalValue * DEFAULT_HYSTERISIS * 4;
}
// get the threshold values for previous pin value, but don't overflow
float overflowableThHi = pin.prvPinVal + CURRENT_HYSTERISIS;
float overflowableThLow = pin.prvPinVal - CURRENT_HYSTERISIS;
if (overflowableThHi > maxDecimalValue) {
pinValThreshHi = maxDecimalValue;
} else {
pinValThreshHi = overflowableThHi;
}
if (overflowableThLow < 0) {
pinValThreshLow = 0;
} else {
pinValThreshLow = overflowableThLow;
}
}
/**********************************************************/
/*!
@brief Checks if pin's period is expired.
@ -310,13 +364,17 @@ bool Wippersnapper_AnalogIO::encodePinEvent(
The current software timer value.
@param pin
The desired analog pin to check
@param periodOffset
Offset to add to the pin's period (used for on_change).
@returns True if pin's period expired, False otherwise.
*/
/**********************************************************/
bool Wippersnapper_AnalogIO::timerExpired(long currentTime,
analogInputPin pin) {
if (currentTime - pin.prvPeriod > pin.period && pin.period != 0L)
bool Wippersnapper_AnalogIO::timerExpired(long currentTime, analogInputPin pin,
long periodOffset) {
if (pin.period + periodOffset != 0L &&
currentTime - pin.prvPeriod > (pin.period + periodOffset)) {
return true;
}
return false;
}
@ -335,9 +393,8 @@ void Wippersnapper_AnalogIO::update() {
if (_analog_input_pins[i].enabled == true) {
// Does the pin execute on-period?
if ((long)millis() - _analog_input_pins[i].prvPeriod >
_analog_input_pins[i].period &&
_analog_input_pins[i].period != 0L) {
if (_analog_input_pins[i].period != 0L &&
timerExpired(millis(), _analog_input_pins[i])) {
WS_DEBUG_PRINT("Executing periodic event on A");
WS_DEBUG_PRINTLN(_analog_input_pins[i].pinName);
@ -359,28 +416,33 @@ void Wippersnapper_AnalogIO::update() {
encodePinEvent(_analog_input_pins[i].pinName,
_analog_input_pins[i].readMode, pinValRaw, pinValVolts);
// IMPT - reset the digital pin
// mark last execution time
_analog_input_pins[i].prvPeriod = millis();
}
// Does the pin execute on_change?
else if (_analog_input_pins[i].period == 0L) {
// not first run and timer not expired, skip
if (_analog_input_pins[i].prvPeriod != 0L &&
!timerExpired(millis(), _analog_input_pins[i], 500)) {
continue;
}
// note: on-change requires ADC DEFAULT_HYSTERISIS to check against prv
// pin value
uint16_t pinValRaw = getPinValue(_analog_input_pins[i].pinName);
uint16_t _pinValThreshHi =
_analog_input_pins[i].prvPinVal +
(_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
uint16_t _pinValThreshLow =
_analog_input_pins[i].prvPinVal -
(_analog_input_pins[i].prvPinVal * DEFAULT_HYSTERISIS);
// check if pin value has changed enough
uint16_t pinValThreshHi, pinValThreshLow;
calculateHysteresis(_analog_input_pins[i], pinValRaw, pinValThreshHi,
pinValThreshLow);
if (pinValRaw > _pinValThreshHi || pinValRaw < _pinValThreshLow) {
if (_analog_input_pins[i].prvPeriod == 0 ||
pinValRaw > pinValThreshHi || pinValRaw < pinValThreshLow) {
// Perform voltage conversion if we need to
if (_analog_input_pins[i].readMode ==
wippersnapper_pin_v1_ConfigurePinRequest_AnalogReadMode_ANALOG_READ_MODE_PIN_VOLTAGE) {
pinValVolts = pinValRaw * getAref() / 65536;
pinValVolts = getPinValueVolts(_analog_input_pins[i].pinName);
}
// Publish pin event to IO
@ -388,12 +450,13 @@ void Wippersnapper_AnalogIO::update() {
_analog_input_pins[i].readMode, pinValRaw,
pinValVolts);
} else {
// WS_DEBUG_PRINTLN("ADC has not changed enough, continue...");
// mark last execution time
_analog_input_pins[i].prvPeriod = millis();
} else { // ADC has not changed enough
continue;
}
// set the pin value in the digital pin object for comparison on next
// run
// set the pin value in the digital pin object for comparison next run
_analog_input_pins[i].prvPinVal = pinValRaw;
}
}

View file

@ -63,7 +63,8 @@ public:
void setADCResolution(int resolution);
int getADCresolution();
int getNativeResolution();
bool timerExpired(long currentTime, analogInputPin pin);
bool timerExpired(long currentTime, analogInputPin pin,
long periodOffset = 0);
void update();
bool encodePinEvent(

View file

@ -82,7 +82,6 @@ WipperSnapper_Component_I2C::WipperSnapper_Component_I2C(
} else {
_isInit = true; // if the peripheral was configured incorrectly
}
_i2c->setClock(50000);
#elif defined(ARDUINO_ARCH_ESP8266)
_i2c = new TwoWire();
_i2c->begin(msgInitRequest->i2c_pin_sda, msgInitRequest->i2c_pin_scl);
@ -143,8 +142,6 @@ wippersnapper_i2c_v1_BusResponse WipperSnapper_Component_I2C::getBusStatus() {
/************************************************************************/
wippersnapper_i2c_v1_I2CBusScanResponse
WipperSnapper_Component_I2C::scanAddresses() {
uint8_t endTransmissionRC;
uint16_t address;
wippersnapper_i2c_v1_I2CBusScanResponse scanResp =
wippersnapper_i2c_v1_I2CBusScanResponse_init_zero;
@ -156,37 +153,45 @@ WipperSnapper_Component_I2C::scanAddresses() {
// Scan all I2C addresses between 0x08 and 0x7F inclusive and return a list of
// those that respond.
WS_DEBUG_PRINTLN("EXEC: I2C Scan");
for (address = 0x08; address < 0x7F; address++) {
WS_DEBUG_PRINTLN("[i2c]: Scanning I2C Bus for Devices...");
for (uint8_t address = 1; address < 127; ++address) {
WS_DEBUG_PRINT("[i2c] Scanning Address: 0x");
WS_DEBUG_PRINTLN(address, HEX);
_i2c->beginTransmission(address);
endTransmissionRC = _i2c->endTransmission();
uint8_t endTransmissionRC = _i2c->endTransmission();
#if defined(ARDUINO_ARCH_ESP32)
// Check endTransmission()'s return code (Arduino-ESP32 ONLY)
// https://github.com/espressif/arduino-esp32/blob/master/libraries/Wire/src/Wire.cpp
if (endTransmissionRC == 5) {
WS_DEBUG_PRINTLN("ESP_ERR_TIMEOUT: I2C Bus Busy");
scanResp.bus_response =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_ERROR_HANG;
// NOTE: ESP-IDF appears to handle this "behind the scenes" by
// resetting/clearing the bus. The user should be prompted to
// perform a bus scan again.
break;
} else if (endTransmissionRC == 7) {
WS_DEBUG_PRINT("I2C_ESP_ERR: SDA/SCL shorted, requests queued: ");
WS_DEBUG_PRINTLN(endTransmissionRC);
break;
}
#endif
// Found device!
if (endTransmissionRC == 0) {
WS_DEBUG_PRINT("Found I2C Device at 0x");
WS_DEBUG_PRINTLN(address);
WS_DEBUG_PRINTLN("[i2c] Found Device!");
scanResp.addresses_found[scanResp.addresses_found_count] =
(uint32_t)address;
scanResp.addresses_found_count++;
}
#if defined(ARDUINO_ARCH_ESP32)
// Check endTransmission()'s return code (Arduino-ESP32 ONLY)
else if (endTransmissionRC == 3) {
WS_DEBUG_PRINTLN("[i2c] Did not find device: NACK on transmit of data!");
continue;
} else if (endTransmissionRC == 2) {
WS_DEBUG_PRINTLN(
"[i2c] Did not find device: NACK on transmit of address!");
continue;
} else if (endTransmissionRC == 1) {
WS_DEBUG_PRINTLN(
"[i2c] Did not find device: data too long to fit in xmit buffer!");
continue;
} else if (endTransmissionRC == 4) {
WS_DEBUG_PRINTLN(
"[i2c] Did not find device: Unspecified bus error occurred!");
continue;
} else if (endTransmissionRC == 5) {
WS_DEBUG_PRINTLN("[i2c] Did not find device: Bus timed out!");
continue;
} else {
WS_DEBUG_PRINTLN(
"[i2c] Did not find device: Unknown bus error has occurred!");
continue;
}
#endif
}
#ifndef ARDUINO_ARCH_ESP32
@ -195,8 +200,9 @@ WipperSnapper_Component_I2C::scanAddresses() {
WS.feedWDT();
#endif
WS_DEBUG_PRINT("I2C Devices Found: ")
WS_DEBUG_PRINTLN(scanResp.addresses_found_count);
WS_DEBUG_PRINT("[i2c] Scan Complete! Found: ")
WS_DEBUG_PRINT(scanResp.addresses_found_count);
WS_DEBUG_PRINTLN(" Devices on bus.");
scanResp.bus_response = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS;
return scanResp;
@ -217,6 +223,7 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
uint16_t i2cAddress = (uint16_t)msgDeviceInitReq->i2c_device_address;
if ((strcmp("aht20", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("aht21", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("am2301b", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("am2315c", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("dht20", msgDeviceInitReq->i2c_device_name) == 0)) {
@ -229,6 +236,16 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
}
_ahtx0->configureDriver(msgDeviceInitReq);
drivers.push_back(_ahtx0);
} else if (strcmp("as5600", msgDeviceInitReq->i2c_device_name) == 0) {
_as5600 = new WipperSnapper_I2C_Driver_AS5600(this->_i2c, i2cAddress);
if (!_as5600->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize AS5600 chip!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_as5600->configureDriver(msgDeviceInitReq);
drivers.push_back(_as5600);
} else if (strcmp("bh1750", msgDeviceInitReq->i2c_device_name) == 0) {
_bh1750 = new WipperSnapper_I2C_Driver_BH1750(this->_i2c, i2cAddress);
if (!_bh1750->begin()) {
@ -285,6 +302,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_bme680->configureDriver(msgDeviceInitReq);
drivers.push_back(_bme680);
WS_DEBUG_PRINTLN("BME680 Initialized Successfully!");
} else if (strcmp("d6t1a", msgDeviceInitReq->i2c_device_name) == 0) {
_d6t1a = new WipperSnapper_I2C_Driver_D6T1A(this->_i2c, i2cAddress);
if (!_d6t1a->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize D6T1A");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_d6t1a->configureDriver(msgDeviceInitReq);
drivers.push_back(_d6t1a);
WS_DEBUG_PRINTLN("D6T1A Initialized Successfully!");
} else if (strcmp("dps310", msgDeviceInitReq->i2c_device_name) == 0) {
_dps310 = new WipperSnapper_I2C_Driver_DPS310(this->_i2c, i2cAddress);
if (!_dps310->begin()) {
@ -318,6 +346,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_ens160->configureDriver(msgDeviceInitReq);
drivers.push_back(_ens160);
WS_DEBUG_PRINTLN("ENS160 Initialized Successfully!");
} else if (strcmp("hdc302x", msgDeviceInitReq->i2c_device_name) == 0) {
_hdc302x = new WipperSnapper_I2C_Driver_HDC302X(this->_i2c, i2cAddress);
if (!_hdc302x->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize HDC302X!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_hdc302x->configureDriver(msgDeviceInitReq);
drivers.push_back(_hdc302x);
WS_DEBUG_PRINTLN("HDC302X Initialized Successfully!");
} else if (strcmp("hts221", msgDeviceInitReq->i2c_device_name) == 0) {
_hts221 = new WipperSnapper_I2C_Driver_HTS221(this->_i2c, i2cAddress);
if (!_hts221->begin()) {
@ -362,6 +401,39 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_scd30->configureDriver(msgDeviceInitReq);
drivers.push_back(_scd30);
WS_DEBUG_PRINTLN("SCD30 Initialized Successfully!");
} else if (strcmp("ina237", msgDeviceInitReq->i2c_device_name) == 0) {
_ina237 = new WipperSnapper_I2C_Driver_INA237(this->_i2c, i2cAddress);
if (!_ina237->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize INA237");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_ina237->configureDriver(msgDeviceInitReq);
drivers.push_back(_ina237);
WS_DEBUG_PRINTLN("INA237 Initialized Successfully!");
} else if (strcmp("ina238", msgDeviceInitReq->i2c_device_name) == 0) {
_ina238 = new WipperSnapper_I2C_Driver_INA238(this->_i2c, i2cAddress);
if (!_ina238->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize INA238");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_ina238->configureDriver(msgDeviceInitReq);
drivers.push_back(_ina238);
WS_DEBUG_PRINTLN("INA238 Initialized Successfully!");
} else if (strcmp("ina228", msgDeviceInitReq->i2c_device_name) == 0) {
_ina228 = new WipperSnapper_I2C_Driver_INA228(this->_i2c, i2cAddress);
if (!_ina228->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize INA228");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_ina228->configureDriver(msgDeviceInitReq);
drivers.push_back(_ina228);
WS_DEBUG_PRINTLN("INA228 Initialized Successfully!");
} else if (strcmp("ina219", msgDeviceInitReq->i2c_device_name) == 0) {
_ina219 = new WipperSnapper_I2C_Driver_INA219(this->_i2c, i2cAddress);
if (!_ina219->begin()) {
@ -373,6 +445,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_ina219->configureDriver(msgDeviceInitReq);
drivers.push_back(_ina219);
WS_DEBUG_PRINTLN("INA219 Initialized Successfully!");
} else if (strcmp("ina260", msgDeviceInitReq->i2c_device_name) == 0) {
_ina260 = new WipperSnapper_I2C_Driver_INA260(this->_i2c, i2cAddress);
if (!_ina260->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize INA260");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_ina260->configureDriver(msgDeviceInitReq);
drivers.push_back(_ina260);
WS_DEBUG_PRINTLN("INA260 Initialized Successfully!");
} else if (strcmp("ltr390", msgDeviceInitReq->i2c_device_name) == 0) {
_ltr390 = new WipperSnapper_I2C_Driver_LTR390(this->_i2c, i2cAddress);
if (!_ltr390->begin()) {
@ -464,6 +547,33 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_mcp9808->configureDriver(msgDeviceInitReq);
drivers.push_back(_mcp9808);
WS_DEBUG_PRINTLN("MCP9808 Initialized Successfully!");
} else if (strcmp("mlx90632b", msgDeviceInitReq->i2c_device_name) == 0 ||
strcmp("mlx90632d_med", msgDeviceInitReq->i2c_device_name) == 0) {
_mlx90632d = new WipperSnapper_I2C_Driver_MLX90632D(this->_i2c, i2cAddress);
if (!_mlx90632d->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize MLX90632!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_mlx90632d->configureDriver(msgDeviceInitReq);
drivers.push_back(_mlx90632d);
WS_DEBUG_PRINTLN("MLX90632 Initialized Successfully!");
} else if (strcmp("mlx90632d_ext", msgDeviceInitReq->i2c_device_name) == 0) {
_mlx90632d_ext =
new WipperSnapper_I2C_Driver_MLX90632D(this->_i2c, i2cAddress);
// set extended range
if (!_mlx90632d_ext->begin() ||
!_mlx90632d_ext->ConfigureAndPrintSensorInfo(true)) {
WS_DEBUG_PRINTLN(
"ERROR: Failed to initialize MLX90632D with extended range!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_mlx90632d_ext->configureDriver(msgDeviceInitReq);
drivers.push_back(_mlx90632d_ext);
WS_DEBUG_PRINTLN("MLX90632D_EXT Initialized Successfully!");
} else if (strcmp("mpl115a2", msgDeviceInitReq->i2c_device_name) == 0) {
_mpl115a2 = new WipperSnapper_I2C_Driver_MPL115A2(this->_i2c, i2cAddress);
if (!_mpl115a2->begin()) {
@ -541,6 +651,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_vcnl4040->configureDriver(msgDeviceInitReq);
drivers.push_back(_vcnl4040);
WS_DEBUG_PRINTLN("VCNL4040 Initialized Successfully!");
} else if (strcmp("vcnl4200", msgDeviceInitReq->i2c_device_name) == 0) {
_vcnl4200 = new WipperSnapper_I2C_Driver_VCNL4200(this->_i2c, i2cAddress);
if (!_vcnl4200->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize VCNL4200!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_vcnl4200->configureDriver(msgDeviceInitReq);
drivers.push_back(_vcnl4200);
WS_DEBUG_PRINTLN("VCNL4200 Initialized Successfully!");
} else if (strcmp("veml7700", msgDeviceInitReq->i2c_device_name) == 0) {
_veml7700 = new WipperSnapper_I2C_Driver_VEML7700(this->_i2c, i2cAddress);
if (!_veml7700->begin()) {
@ -577,6 +698,22 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_sen5x->configureDriver(msgDeviceInitReq);
drivers.push_back(_sen5x);
WS_DEBUG_PRINTLN("SEN5X Initialized Successfully!");
} else if ((strcmp("sen6x", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen60", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen63C", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen65", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen66", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sen68", msgDeviceInitReq->i2c_device_name) == 0)) {
_sen6x = new WipperSnapper_I2C_Driver_SEN6X(this->_i2c, i2cAddress);
if (!_sen6x->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize SEN6X!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_sen6x->configureDriver(msgDeviceInitReq);
drivers.push_back(_sen6x);
WS_DEBUG_PRINTLN("SEN6X Initialized Successfully!");
} else if ((strcmp("sht40", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sht41", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("sht45", msgDeviceInitReq->i2c_device_name) == 0)) {
@ -670,6 +807,17 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_lps25hb->configureDriver(msgDeviceInitReq);
drivers.push_back(_lps25hb);
WS_DEBUG_PRINTLN("LPS25HB Sensor Initialized Successfully!");
} else if (strcmp("lps28dfw", msgDeviceInitReq->i2c_device_name) == 0) {
_lps28hb = new WipperSnapper_I2C_Driver_LPS28DFW(this->_i2c, i2cAddress);
if (!_lps28hb->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize LPS28DFW Sensor!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_lps28hb->configureDriver(msgDeviceInitReq);
drivers.push_back(_lps28hb);
WS_DEBUG_PRINTLN("LPS28HB Sensor Initialized Successfully!");
} else if ((strcmp("lps33hw", msgDeviceInitReq->i2c_device_name) == 0) ||
(strcmp("lps35hw", msgDeviceInitReq->i2c_device_name)) == 0) {
_lps3xhw = new WipperSnapper_I2C_Driver_LPS3XHW(this->_i2c, i2cAddress);
@ -771,6 +919,105 @@ bool WipperSnapper_Component_I2C::initI2CDevice(
_adt7410->configureDriver(msgDeviceInitReq);
drivers.push_back(_adt7410);
WS_DEBUG_PRINTLN("ADT7410 Initialized Successfully!");
} else if (strcmp("quadalphanum", msgDeviceInitReq->i2c_device_name) == 0) {
_quadAlphaNum =
new WipperSnapper_I2C_Driver_Out_QuadAlphaNum(this->_i2c, i2cAddress);
_quadAlphaNum->ConfigureI2CBackpack(
msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness,
msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment);
if (!_quadAlphaNum->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize Quad Alphanum. Display!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_drivers_out.push_back(_quadAlphaNum);
WS_DEBUG_PRINTLN("Quad Alphanum. Display Initialized Successfully!");
} else if (strcmp("chardisplay16x2", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("chardisplay20x4", msgDeviceInitReq->i2c_device_name) ==
0) {
_charLcd = new WipperSnapper_I2C_Driver_Out_CharLcd(this->_i2c, i2cAddress);
_charLcd->ConfigureCharLcd(
msgDeviceInitReq->i2c_output_add.config.char_lcd_config.rows,
msgDeviceInitReq->i2c_output_add.config.char_lcd_config.columns);
if (!_charLcd->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize Character LCD!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_drivers_out.push_back(_charLcd);
WS_DEBUG_PRINTLN("Char LCD Display Initialized Successfully!");
} else if (strcmp("7seg", msgDeviceInitReq->i2c_device_name) == 0) {
_sevenSeg = new WipperSnapper_I2C_Driver_Out_7Seg(this->_i2c, i2cAddress);
_sevenSeg->ConfigureI2CBackpack(
msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness,
msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment);
if (!_sevenSeg->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize 7-Segement LED Matrix!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
_drivers_out.push_back(_sevenSeg);
WS_DEBUG_PRINTLN("7-Segement LED Matrix Initialized Successfully!");
} else if (strcmp("fthrwingoled128x64", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("fthrwingoled128x64lg",
msgDeviceInitReq->i2c_device_name) == 0) {
WS_DEBUG_PRINTLN("SH1107 display detected!");
_sh1107 = new WipperSnapper_I2C_Driver_Out_SH1107(this->_i2c, i2cAddress);
WS_DEBUG_PRINTLN("Configuring SH1107 display...");
_sh1107->ConfigureSH1107(
(uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width,
(uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height,
(uint8_t)
msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size,
OLED_128X64_WING_ROTATION_90); // fixed as currently the only screen is
// 128x64wing (needs a rotation of 1 / 90degrees and constructor w/h swap).
if (!_sh1107->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize sh1107!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
WS_DEBUG_PRINTLN("SH1107 display configured successfully!");
_drivers_out.push_back(_sh1107);
WS_DEBUG_PRINTLN("SH1107 display initialized Successfully!");
} else if (strcmp("oled32x64large", msgDeviceInitReq->i2c_device_name) == 0 ||
strcmp("oled64x32default", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("oled64x32large", msgDeviceInitReq->i2c_device_name) == 0 ||
strcmp("fthrwingoled128x32", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("fthrwingoled128x32lg",
msgDeviceInitReq->i2c_device_name) == 0 ||
strcmp("oled128x32default", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("oled128x32large", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("oled128x64default", msgDeviceInitReq->i2c_device_name) ==
0 ||
strcmp("oled128x64large", msgDeviceInitReq->i2c_device_name) ==
0) {
WS_DEBUG_PRINTLN("SSD1306 display detected!");
_ssd1306 = new WipperSnapper_I2C_Driver_Out_Ssd1306(this->_i2c, i2cAddress);
WS_DEBUG_PRINTLN("Configuring SSD1306 display...");
_ssd1306->ConfigureSSD1306(
(uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width,
(uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height,
(uint8_t)
msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size);
if (!_ssd1306->begin()) {
WS_DEBUG_PRINTLN("ERROR: Failed to initialize ssd1306!");
_busStatusResponse =
wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL;
return false;
}
WS_DEBUG_PRINTLN("SSD1306 display configured successfully!");
_drivers_out.push_back(_ssd1306);
WS_DEBUG_PRINTLN("SSD1306 display initialized Successfully!");
} else {
WS_DEBUG_PRINTLN("ERROR: I2C device type not found!")
_busStatusResponse =
@ -819,8 +1066,9 @@ void WipperSnapper_Component_I2C::updateI2CDeviceProperties(
void WipperSnapper_Component_I2C::deinitI2CDevice(
wippersnapper_i2c_v1_I2CDeviceDeinitRequest *msgDeviceDeinitReq) {
uint16_t deviceAddr = (uint16_t)msgDeviceDeinitReq->i2c_device_address;
std::vector<WipperSnapper_I2C_Driver *>::iterator iter, end;
// Check input (sensor) drivers
std::vector<WipperSnapper_I2C_Driver *>::iterator iter, end;
for (iter = drivers.begin(), end = drivers.end(); iter != end; ++iter) {
if ((*iter)->getI2CAddress() == deviceAddr) {
// Delete the object that iter points to
@ -838,6 +1086,28 @@ void WipperSnapper_Component_I2C::deinitI2CDevice(
WS_DEBUG_PRINTLN("I2C Device De-initialized!");
}
}
// Check for output drivers
std::vector<WipperSnapper_I2C_Driver_Out *>::iterator out_iter, out_end;
for (out_iter = _drivers_out.begin(), out_end = _drivers_out.end();
out_iter != out_end; ++out_iter) {
if ((*out_iter)->getI2CAddress() == deviceAddr) {
// Set the driver to nullptr
*out_iter = nullptr;
// ESP-IDF, Eraseremove iter ptr from driver vector
#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266)
*out_iter = nullptr;
_drivers_out.erase(
remove(_drivers_out.begin(), _drivers_out.end(), nullptr),
_drivers_out.end());
#else
// Arduino can not erase-remove, erase only
_drivers_out.erase(out_iter);
#endif
WS_DEBUG_PRINTLN("I2C Device De-initialized!");
}
}
_busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS;
}
@ -1006,6 +1276,51 @@ void WipperSnapper_Component_I2C::displayDeviceEventMessage(
}
}
/*******************************************************************************/
/*!
@brief Handles an I2CDeviceOutputWrite message.
@param msgDeviceWrite
A decoded I2CDeviceOutputWrite message.
@returns True if the message was handled successfully, false otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_Component_I2C::Handle_I2cDeviceOutputWrite(
wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite) {
// Create a ptr to the base driver out
WipperSnapper_I2C_Driver_Out *driver_out = nullptr;
// Find the matching driver by address in the _drivers_out vector
for (size_t i = 0; i < _drivers_out.size(); i++) {
if (_drivers_out[i]->getI2CAddress() ==
msgDeviceWrite->i2c_device_address) {
driver_out = _drivers_out[i];
break;
}
}
if (driver_out == nullptr) {
WS_DEBUG_PRINTLN("ERROR: I2c output driver not found within drivers_out!");
return false;
}
// Call the output_msg
if (msgDeviceWrite->which_output_msg ==
wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_led_backpack_tag) {
driver_out->WriteLedBackpack(
&msgDeviceWrite->output_msg.write_led_backpack);
} else if (msgDeviceWrite->which_output_msg ==
wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_char_lcd_tag) {
driver_out->WriteMessageCharLCD(&msgDeviceWrite->output_msg.write_char_lcd);
} else if (msgDeviceWrite->which_output_msg ==
wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_ssd1306_tag) {
driver_out->WriteMessageSSD1306(
msgDeviceWrite->output_msg.write_ssd1306.message);
} else {
WS_DEBUG_PRINTLN("ERROR: Unknown i2c output message type!");
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Queries all I2C device drivers for new values. Fills and sends an
@ -1013,7 +1328,6 @@ void WipperSnapper_Component_I2C::displayDeviceEventMessage(
*/
/*******************************************************************************/
void WipperSnapper_Component_I2C::update() {
// Create response message
wippersnapper_signal_v1_I2CResponse msgi2cResponse =
wippersnapper_signal_v1_I2CResponse_init_zero;
@ -1030,11 +1344,11 @@ void WipperSnapper_Component_I2C::update() {
std::vector<WipperSnapper_I2C_Driver *>::iterator iter, end;
for (iter = drivers.begin(), end = drivers.end(); iter != end; ++iter) {
// Number of events which occured for this driver
// Number of events which occurred for this driver
msgi2cResponse.payload.resp_i2c_device_event.sensor_event_count = 0;
// Event struct
sensors_event_t event;
// Event struct - zero-initialise on each iteration
sensors_event_t event = {0};
// AMBIENT_TEMPERATURE sensor (°C)
sensorEventRead(

View file

@ -22,36 +22,52 @@
#include "drivers/WipperSnapper_I2C_Driver.h"
#include "drivers/WipperSnapper_I2C_Driver_ADT7410.h"
#include "drivers/WipperSnapper_I2C_Driver_AHTX0.h"
#include "drivers/WipperSnapper_I2C_Driver_AS5600.h"
#include "drivers/WipperSnapper_I2C_Driver_BH1750.h"
#include "drivers/WipperSnapper_I2C_Driver_BME280.h"
#include "drivers/WipperSnapper_I2C_Driver_BME680.h"
#include "drivers/WipperSnapper_I2C_Driver_BMP280.h"
#include "drivers/WipperSnapper_I2C_Driver_BMP3XX.h"
#include "drivers/WipperSnapper_I2C_Driver_D6T1A.h"
#include "drivers/WipperSnapper_I2C_Driver_DPS310.h"
#include "drivers/WipperSnapper_I2C_Driver_DS2484.h"
#include "drivers/WipperSnapper_I2C_Driver_ENS160.h"
#include "drivers/WipperSnapper_I2C_Driver_HDC302X.h"
#include "drivers/WipperSnapper_I2C_Driver_HTS221.h"
#include "drivers/WipperSnapper_I2C_Driver_HTU21D.h"
#include "drivers/WipperSnapper_I2C_Driver_HTU31D.h"
#include "drivers/WipperSnapper_I2C_Driver_INA219.h"
#include "drivers/WipperSnapper_I2C_Driver_INA228.h"
#include "drivers/WipperSnapper_I2C_Driver_INA237.h"
#include "drivers/WipperSnapper_I2C_Driver_INA238.h"
#include "drivers/WipperSnapper_I2C_Driver_INA260.h"
#include "drivers/WipperSnapper_I2C_Driver_LC709203F.h"
#include "drivers/WipperSnapper_I2C_Driver_LPS22HB.h"
#include "drivers/WipperSnapper_I2C_Driver_LPS25HB.h"
#include "drivers/WipperSnapper_I2C_Driver_LPS28DFW.h"
#include "drivers/WipperSnapper_I2C_Driver_LPS3XHW.h"
#include "drivers/WipperSnapper_I2C_Driver_LTR329_LTR303.h"
#include "drivers/WipperSnapper_I2C_Driver_LTR390.h"
#include "drivers/WipperSnapper_I2C_Driver_MAX17048.h"
#include "drivers/WipperSnapper_I2C_Driver_MCP3421.h"
#include "drivers/WipperSnapper_I2C_Driver_MCP9808.h"
#include "drivers/WipperSnapper_I2C_Driver_MLX90632D.h"
#include "drivers/WipperSnapper_I2C_Driver_MPL115A2.h"
#include "drivers/WipperSnapper_I2C_Driver_MPRLS.h"
#include "drivers/WipperSnapper_I2C_Driver_MS8607.h"
#include "drivers/WipperSnapper_I2C_Driver_NAU7802.h"
#include "drivers/WipperSnapper_I2C_Driver_Out.h"
#include "drivers/WipperSnapper_I2C_Driver_Out_7Seg.h"
#include "drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h"
#include "drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h"
#include "drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h"
#include "drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h"
#include "drivers/WipperSnapper_I2C_Driver_PCT2075.h"
#include "drivers/WipperSnapper_I2C_Driver_PM25.h"
#include "drivers/WipperSnapper_I2C_Driver_SCD30.h"
#include "drivers/WipperSnapper_I2C_Driver_SCD4X.h"
#include "drivers/WipperSnapper_I2C_Driver_SEN5X.h"
#include "drivers/WipperSnapper_I2C_Driver_SEN6X.h"
#include "drivers/WipperSnapper_I2C_Driver_SGP30.h"
#include "drivers/WipperSnapper_I2C_Driver_SGP40.h"
#include "drivers/WipperSnapper_I2C_Driver_SHT3X.h"
@ -63,6 +79,7 @@
#include "drivers/WipperSnapper_I2C_Driver_TSL2591.h"
#include "drivers/WipperSnapper_I2C_Driver_VCNL4020.h"
#include "drivers/WipperSnapper_I2C_Driver_VCNL4040.h"
#include "drivers/WipperSnapper_I2C_Driver_VCNL4200.h"
#include "drivers/WipperSnapper_I2C_Driver_VEML7700.h"
#include "drivers/WipperSnapper_I2C_Driver_VL53L0X.h"
#include "drivers/WipperSnapper_I2C_Driver_VL53L1X.h"
@ -74,6 +91,10 @@
// forward decl.
class Wippersnapper;
class WipperSnapper_I2C_Driver_INA260;
class WipperSnapper_I2C_Driver_INA237;
class WipperSnapper_I2C_Driver_INA238;
class WipperSnapper_I2C_Driver_INA228;
/**************************************************************************/
/*!
@ -99,6 +120,9 @@ public:
void update();
bool Handle_I2cDeviceOutputWrite(
wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite);
void sensorEventRead(
std::vector<WipperSnapper_I2C_Driver *>::iterator &iter,
unsigned long curTime,
@ -129,9 +153,14 @@ private:
int32_t _portNum;
TwoWire *_i2c = nullptr;
wippersnapper_i2c_v1_BusResponse _busStatusResponse;
std::vector<WipperSnapper_I2C_Driver *> drivers; ///< List of sensor drivers
std::vector<WipperSnapper_I2C_Driver *>
drivers; ///< List of i2c sensor drivers
std::vector<WipperSnapper_I2C_Driver_Out *>
_drivers_out; ///< List of i2c output drivers
// Sensor driver objects
WipperSnapper_I2C_Driver_AHTX0 *_ahtx0 = nullptr;
WipperSnapper_I2C_Driver_AS5600 *_as5600 = nullptr;
WipperSnapper_I2C_Driver_D6T1A *_d6t1a = nullptr;
WipperSnapper_I2C_Driver_DPS310 *_dps310 = nullptr;
WipperSnapper_I2C_Driver_DS2484 *_ds2484 = nullptr;
WipperSnapper_I2C_Driver_ENS160 *_ens160 = nullptr;
@ -141,14 +170,21 @@ private:
WipperSnapper_I2C_Driver_BMP280 *_bmp280 = nullptr;
WipperSnapper_I2C_Driver_BMP3XX *_bmp3xx = nullptr;
WipperSnapper_I2C_Driver_BME680 *_bme680 = nullptr;
WipperSnapper_I2C_Driver_HDC302X *_hdc302x = nullptr;
WipperSnapper_I2C_Driver_HTS221 *_hts221 = nullptr;
WipperSnapper_I2C_Driver_HTU21D *_htu21d = nullptr;
WipperSnapper_I2C_Driver_HTU31D *_htu31d = nullptr;
WipperSnapper_I2C_Driver_INA219 *_ina219 = nullptr;
WipperSnapper_I2C_Driver_INA237 *_ina237 = nullptr;
WipperSnapper_I2C_Driver_INA238 *_ina238 = nullptr;
WipperSnapper_I2C_Driver_INA228 *_ina228 = nullptr;
WipperSnapper_I2C_Driver_INA260 *_ina260 = nullptr;
WipperSnapper_I2C_Driver_LTR329_LTR303 *_ltr329 = nullptr;
WipperSnapper_I2C_Driver_LTR390 *_ltr390 = nullptr;
WipperSnapper_I2C_Driver_MCP3421 *_mcp3421 = nullptr;
WipperSnapper_I2C_Driver_MCP9808 *_mcp9808 = nullptr;
WipperSnapper_I2C_Driver_MLX90632D *_mlx90632d = nullptr;
WipperSnapper_I2C_Driver_MLX90632D *_mlx90632d_ext = nullptr;
WipperSnapper_I2C_Driver_MPL115A2 *_mpl115a2 = nullptr;
WipperSnapper_I2C_Driver_MPRLS *_mprls = nullptr;
WipperSnapper_I2C_Driver_MS8607 *_ms8607 = nullptr;
@ -157,9 +193,11 @@ private:
WipperSnapper_I2C_Driver_TSL2591 *_tsl2591 = nullptr;
WipperSnapper_I2C_Driver_VCNL4020 *_vcnl4020 = nullptr;
WipperSnapper_I2C_Driver_VCNL4040 *_vcnl4040 = nullptr;
WipperSnapper_I2C_Driver_VCNL4200 *_vcnl4200 = nullptr;
WipperSnapper_I2C_Driver_VEML7700 *_veml7700 = nullptr;
WipperSnapper_I2C_Driver_SCD4X *_scd40 = nullptr;
WipperSnapper_I2C_Driver_SEN5X *_sen5x = nullptr;
WipperSnapper_I2C_Driver_SEN6X *_sen6x = nullptr;
WipperSnapper_I2C_Driver_SGP30 *_sgp30 = nullptr;
WipperSnapper_I2C_Driver_SGP40 *_sgp40 = nullptr;
WipperSnapper_I2C_Driver_PCT2075 *_pct2075 = nullptr;
@ -171,6 +209,7 @@ private:
WipperSnapper_I2C_Driver_LC709203F *_lc = nullptr;
WipperSnapper_I2C_Driver_LPS22HB *_lps22hb = nullptr;
WipperSnapper_I2C_Driver_LPS25HB *_lps25hb = nullptr;
WipperSnapper_I2C_Driver_LPS28DFW *_lps28hb = nullptr;
WipperSnapper_I2C_Driver_LPS3XHW *_lps3xhw = nullptr;
WipperSnapper_I2C_Driver_STEMMA_Soil_Sensor *_ss = nullptr;
WipperSnapper_I2C_Driver_VL53L0X *_vl53l0x = nullptr;
@ -180,6 +219,11 @@ private:
WipperSnapper_I2C_Driver_VL6180X *_vl6180x = nullptr;
WipperSnapper_I2C_Driver_MAX17048 *_max17048 = nullptr;
WipperSnapper_I2C_Driver_ADT7410 *_adt7410 = nullptr;
WipperSnapper_I2C_Driver_Out_QuadAlphaNum *_quadAlphaNum = nullptr;
WipperSnapper_I2C_Driver_Out_CharLcd *_charLcd = nullptr;
WipperSnapper_I2C_Driver_Out_7Seg *_sevenSeg = nullptr;
WipperSnapper_I2C_Driver_Out_SH1107 *_sh1107 = nullptr;
WipperSnapper_I2C_Driver_Out_Ssd1306 *_ssd1306 = nullptr;
};
extern Wippersnapper WS;

View file

@ -16,8 +16,10 @@
#ifndef WipperSnapper_I2C_Driver_H
#define WipperSnapper_I2C_Driver_H
#include "wippersnapper/i2c/v1/i2c.pb.h"
#include <Adafruit_Sensor.h>
#include <Arduino.h>
#include <Wire.h>
#define PERIOD_24HRS_AGO_MILLIS (millis() - (24 * 60 * 60 * 1000))
///< Used for last sensor read time, initially set 24hrs ago (max period)
@ -1234,7 +1236,7 @@ public:
@brief Enables the device's proximity sensor, if it exists.
*/
/*******************************************************************************/
virtual void enableSensorProximity(){};
virtual void enableSensorProximity() {};
/*******************************************************************************/
/*!

View file

@ -0,0 +1,155 @@
/*!
* @file WipperSnapper_I2C_Driver_AS5600.h
*
* Device driver for the AS5600 Magnetic Angle sensor.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2024 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_AS5600_H
#define WipperSnapper_I2C_Driver_AS5600_H
#include <Adafruit_AS5600.h>
#include "WipperSnapper_I2C_Driver.h"
#include "Wippersnapper.h"
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a AS5600 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_AS5600 : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for the AS5600 sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_AS5600(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_as5600 = nullptr;
_angle = 0;
}
/*******************************************************************************/
/*!
@brief Destructor for an AS5600 sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_AS5600() {
if (_as5600) {
delete _as5600;
_as5600 = nullptr;
}
}
/*******************************************************************************/
/*!
@brief Initializes the AS5600 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
_as5600 = new Adafruit_AS5600();
if (!_as5600->begin((uint8_t)_sensorAddress, _i2c)) {
WS_DEBUG_PRINTLN("Failed to find AS5600 chip");
return false;
}
if (!configureSensor()) {
WS_DEBUG_PRINTLN("Failed to configure AS5600 sensor");
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Configures the AS5600 sensor.
@returns True if the sensor was configured successfully, False otherwise.
*/
/*******************************************************************************/
bool configureSensor() {
return _as5600->enableWatchdog(false) &&
// Normal (high) power mode
_as5600->setPowerMode(AS5600_POWER_MODE_NOM) &&
// No Hysteresis
_as5600->setHysteresis(AS5600_HYSTERESIS_OFF) &&
// analog output (0-VCC for 0-360 degrees)
_as5600->setOutputStage(AS5600_OUTPUT_STAGE_ANALOG_FULL) &&
// setup filters
_as5600->setSlowFilter(AS5600_SLOW_FILTER_16X) &&
_as5600->setFastFilterThresh(AS5600_FAST_FILTER_THRESH_SLOW_ONLY) &&
// Reset position settings to defaults
_as5600->setZPosition(0) && _as5600->setMPosition(4095) &&
_as5600->setMaxAngle(4095);
}
/*******************************************************************************/
/*!
@brief Reads the Angle sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool readSensor() {
if (!_as5600->isMagnetDetected()) {
WS_DEBUG_PRINTLN("Magnet not detected!");
return false;
}
// Continuously read and display angle values
uint16_t rawAngle = _as5600->getRawAngle();
uint16_t angle = _as5600->getAngle();
WS_DEBUG_PRINT("AS5600 Raw: ");
WS_DEBUG_PRINT(rawAngle);
WS_DEBUG_PRINT(" | Scaled: ");
WS_DEBUG_PRINT(angle);
// Check status conditions
if (_as5600->isAGCminGainOverflow()) {
WS_DEBUG_PRINTLN(" | MH: magnet too strong");
return false;
}
if (_as5600->isAGCmaxGainOverflow()) {
WS_DEBUG_PRINTLN(" | ML: magnet too weak");
return false;
}
_angle = ((float)angle / 4095.0) * 360.0;
return true;
}
/*******************************************************************************/
/*!
@brief Reads the Angle sensor with short wait for data.
@param rawEvent
Angle sensor reading
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventRaw(sensors_event_t *rawEvent) {
if (!readSensor()) {
return false;
}
rawEvent->data[0] = _angle;
return true;
}
protected:
float _angle; ///< Current angle reading from the AS5600 sensor
Adafruit_AS5600 *_as5600; ///< Pointer to AS5600 sensor object
};
#endif // WipperSnapper_I2C_Driver_AS5600

View file

@ -130,7 +130,7 @@ public:
bool getEventPressure(sensors_event_t *pressureEvent) {
if (!bmePerformReading())
return false;
pressureEvent->pressure = (float)_bme->pressure;
pressureEvent->pressure = (float)_bme->pressure / 100.0;
return true;
}
@ -172,4 +172,4 @@ protected:
Adafruit_BME680 *_bme; ///< BME680 object
};
#endif // WipperSnapper_I2C_Driver_BME680
#endif // WipperSnapper_I2C_Driver_BME680

View file

@ -0,0 +1,142 @@
/*!
* @file WipperSnapper_I2C_Driver_D6T1A.h
*
* Device driver for a D6T1A thermal sensor.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_D6T1A_H
#define WipperSnapper_I2C_Driver_D6T1A_H
#include <OmronD6T.h>
#include "WipperSnapper_I2C_Driver.h"
/**************************************************************************/
/*!
@brief Class that provides a sensor driver for the D6T1A temperature
and pressure sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_D6T1A : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for an D6T1A sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_D6T1A(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_deviceTemp = NAN;
_objectTemp = NAN;
_lastRead = 0;
}
/*******************************************************************************/
/*!
@brief Destructor for an D6T1A sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_D6T1A() { delete _d6t1a; }
/*******************************************************************************/
/*!
@brief Initializes the D6T1A sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
_d6t1a = new OmronD6T(OmronD6T::D6T_1A, _i2c);
// attempt to initialize D6T1A
if (!_d6t1a->begin(_sensorAddress))
return false;
return true;
}
/*******************************************************************************/
/*!
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
/*******************************************************************************/
bool HasBeenReadInLast200ms() {
return _lastRead != 0 && millis() - _lastRead < 200;
}
/*******************************************************************************/
/*!
@brief Reads the sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
// dont read sensor more than once per 200ms
if (HasBeenReadInLast200ms()) {
return true;
}
_d6t1a->read();
_deviceTemp = (float)_d6t1a->ambientTempC();
_objectTemp = (float)_d6t1a->objectTempC(0, 0);
_lastRead = millis();
return true;
}
/*******************************************************************************/
/*!
@brief Gets the D6T1A's current temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
if (ReadSensorData() && _deviceTemp != NAN) {
// if the sensor was read recently, return the cached temperature
tempEvent->temperature = _deviceTemp;
return true;
}
return false; // sensor not read recently, return false
}
/*******************************************************************************/
/*!
@brief Gets the D6T1A's object temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventObjectTemp(sensors_event_t *tempEvent) {
if (ReadSensorData() && _objectTemp != NAN) {
// if the sensor was read recently, return the cached temperature
tempEvent->temperature = _objectTemp;
return true;
}
return false; // sensor not read recently, return false
}
protected:
float _deviceTemp; ///< Device temperature in Celsius
float _objectTemp; ///< Object temperature in Celsius
uint32_t _lastRead; ///< Last time the sensor was read in milliseconds
OmronD6T *_d6t1a = nullptr; ///< D6T1A object
};
#endif // WipperSnapper_I2C_Driver_D6T1A

View file

@ -0,0 +1,130 @@
/*!
* @file WipperSnapper_I2C_Driver_HDC302X.h
*
* Device driver for an HDC302X Humidity and Temperature sensor.
*/
#ifndef WipperSnapper_I2C_Driver_HDC302X_H
#define WipperSnapper_I2C_Driver_HDC302X_H
#include "WipperSnapper_I2C_Driver.h"
#include <Adafruit_HDC302x.h>
/**************************************************************************/
/*!
@brief Class that provides a sensor driver for the HDC302X humidity and
temperature sensor. This implementation uses the 1 Hz data rate.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_HDC302X : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for an HDC302X sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_HDC302X(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an HDC302X sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_HDC302X() { delete _hdc302x; }
/*******************************************************************************/
/*!
@brief Initializes the HDC302X sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
// attempt to initialize the HDC302X using the I2C interface
_hdc302x = new Adafruit_HDC302x();
if (!_hdc302x->begin(_sensorAddress, _i2c))
return false;
// set the HDC302X's data rate to 1 Hz lowest noise
_hdc302x->setAutoMode(EXIT_AUTO_MODE);
// discard first reading (It returned -45c for me once)
_hdc302x->readTemperatureHumidityOnDemand(_temp, _humidity,
TRIGGERMODE_LP0);
return true;
}
/*******************************************************************************/
/*!
@brief Reads the HDC302X's temperature and humidity data.
@returns True if the data was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
uint16_t status = _hdc302x->readStatus();
if (status & 0x0010) {
WS_DEBUG_PRINTLN(F("Device Reset Detected"));
return false;
}
if (status & 0x0001) {
WS_DEBUG_PRINTLN(
F("Checksum Verification Fail (incorrect checksum received)"));
return false;
}
if (!_hdc302x->readTemperatureHumidityOnDemand(_temp, _humidity,
TRIGGERMODE_LP0)) {
WS_DEBUG_PRINTLN(F("Failed to read temperature and humidity."));
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Gets the HDC302X's current temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
if (ReadSensorData() == false)
return false;
tempEvent->temperature = _temp;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the HDC302X's current humidity.
@param humidEvent
Pointer to an Adafruit_Sensor event.
@returns True if the humidity was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventRelativeHumidity(sensors_event_t *humidEvent) {
if (ReadSensorData() == false)
return false;
humidEvent->relative_humidity = _humidity;
return true;
}
protected:
Adafruit_HDC302x *_hdc302x; ///< Pointer to an HDC302X object
double _temp = 0.0; ///< Holds data for the HDC302X's temperature sensor
double _humidity = 0.0; ///< Holds data for the HDC302X's humidity sensor
};
#endif // WipperSnapper_I2C_Driver_HDC302X

View file

@ -0,0 +1,109 @@
/*!
* @file WipperSnapper_I2C_Driver_INA228.cpp
*
* Device driver implementation for the INA228 High Precision DC Current and
* Voltage Monitor (Avoids import conflict with INA260 typedef enum _mode etc)
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#include "WipperSnapper_I2C_Driver_INA228.h"
#include "Wippersnapper.h"
#include <Adafruit_INA228.h>
/*******************************************************************************/
/*!
@brief Constructor for a INA228 sensor.
@param i2c
The I2C interface.
@param sensorAddress
The 7-bit I2C address of the sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA228::WipperSnapper_I2C_Driver_INA228(
TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress), _ina228(nullptr) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an INA228 sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA228::~WipperSnapper_I2C_Driver_INA228() {
delete _ina228;
}
/*******************************************************************************/
/*!
@brief Initializes the INA228 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA228::begin() {
_ina228 = new Adafruit_INA228();
if (!_ina228->begin(_sensorAddress, _i2c)) {
return false;
}
// Default shunt: 0.015 ohm, 10A max current
_ina228->setShunt(0.015, 10.0);
_ina228->setAveragingCount(INA228_COUNT_16);
_ina228->setVoltageConversionTime(INA228_TIME_150_us);
_ina228->setCurrentConversionTime(INA228_TIME_280_us);
return true;
}
/*******************************************************************************/
/*!
@brief Reads a voltage sensor and converts the
reading into the expected SI unit.
@param voltageEvent
voltage sensor reading, in volts.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA228::getEventVoltage(
sensors_event_t *voltageEvent) {
voltageEvent->voltage = _ina228->getBusVoltage_V();
return true;
}
/**
* @brief Get the current sensor event.
*
* @param currentEvent Pointer to the current sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA228::getEventCurrent(
sensors_event_t *currentEvent) {
currentEvent->current = _ina228->getCurrent_mA();
return true;
}
/**
* @brief Get the raw (power) sensor event.
*
* @param powerEvent Pointer to the power sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA228::getEventRaw(sensors_event_t *powerEvent) {
powerEvent->data[0] = _ina228->getPower_mW();
return true;
}

View file

@ -0,0 +1,43 @@
/*!
* @file WipperSnapper_I2C_Driver_INA228.h
*
* Device driver for the INA228 High Precision DC Current and Voltage Monitor
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_INA228_H
#define WipperSnapper_I2C_Driver_INA228_H
#include "WipperSnapper_I2C_Driver.h"
#include "Wippersnapper.h"
// Forward declaration
class Adafruit_INA228;
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a INA228 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_INA228 : public WipperSnapper_I2C_Driver {
public:
WipperSnapper_I2C_Driver_INA228(TwoWire *i2c, uint16_t sensorAddress);
~WipperSnapper_I2C_Driver_INA228();
bool begin();
bool getEventVoltage(sensors_event_t *voltageEvent);
bool getEventCurrent(sensors_event_t *currentEvent);
bool getEventRaw(sensors_event_t *powerEvent);
protected:
Adafruit_INA228 *_ina228; ///< Pointer to INA228 sensor object
};
#endif // WipperSnapper_I2C_Driver_INA228_H

View file

@ -0,0 +1,114 @@
/*!
* @file WipperSnapper_I2C_Driver_INA237.cpp
*
* Device driver implementation for the INA237 DC Current and Voltage Monitor
* (Avoids import conflict with INA260 typedef enum _mode etc)
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#include "WipperSnapper_I2C_Driver_INA237.h"
#include "Wippersnapper.h"
#include <Adafruit_INA237.h>
/*******************************************************************************/
/*!
@brief Constructor for a INA237 sensor.
@param i2c
The I2C interface.
@param sensorAddress
The 7-bit I2C address of the sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA237::WipperSnapper_I2C_Driver_INA237(
TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress), _ina237(nullptr) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an INA237 sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA237::~WipperSnapper_I2C_Driver_INA237() {
delete _ina237;
}
/*******************************************************************************/
/*!
@brief Initializes the INA237 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA237::begin() {
_ina237 = new Adafruit_INA237();
if (!_ina237->begin(_sensorAddress, _i2c)) {
return false;
}
// Configuration based on INA237 example sketch
// Set default shunt resistance and maximum current
// Default 0.015 ohm shunt, 10A max current
_ina237->setShunt(0.015, 10.0);
// Set averaging for better accuracy (16 samples)
_ina237->setAveragingCount(INA2XX_COUNT_16);
// Set conversion times as per example
_ina237->setVoltageConversionTime(INA2XX_TIME_150_us);
_ina237->setCurrentConversionTime(INA2XX_TIME_280_us);
return true;
}
/*******************************************************************************/
/*!
@brief Reads a voltage sensor and converts the
reading into the expected SI unit.
@param voltageEvent
voltage sensor reading, in volts.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA237::getEventVoltage(
sensors_event_t *voltageEvent) {
voltageEvent->voltage = _ina237->getBusVoltage_V();
return true;
}
/**
* @brief Get the current sensor event.
*
* @param currentEvent Pointer to the current sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA237::getEventCurrent(
sensors_event_t *currentEvent) {
currentEvent->current = _ina237->getCurrent_mA();
return true;
}
/**
* @brief Get the raw (power) sensor event.
*
* @param powerEvent Pointer to the power sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA237::getEventRaw(sensors_event_t *powerEvent) {
powerEvent->data[0] = _ina237->getPower_mW();
return true;
}

View file

@ -0,0 +1,45 @@
/*!
* @file WipperSnapper_I2C_Driver_INA237.h
*
* Device driver for the INA237 DC Current and Voltage Monitor
* 16-bit ADC with ±0.3% gain error, ±50µV offset voltage
* Cost-effective version, lower precision than INA238
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_INA237_H
#define WipperSnapper_I2C_Driver_INA237_H
#include "WipperSnapper_I2C_Driver.h"
#include "Wippersnapper.h"
// Forward declaration
class Adafruit_INA237;
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a INA237 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_INA237 : public WipperSnapper_I2C_Driver {
public:
WipperSnapper_I2C_Driver_INA237(TwoWire *i2c, uint16_t sensorAddress);
~WipperSnapper_I2C_Driver_INA237();
bool begin();
bool getEventVoltage(sensors_event_t *voltageEvent);
bool getEventCurrent(sensors_event_t *currentEvent);
bool getEventRaw(sensors_event_t *powerEvent);
protected:
Adafruit_INA237 *_ina237; ///< Pointer to INA237 sensor object
};
#endif // WipperSnapper_I2C_Driver_INA237

View file

@ -0,0 +1,114 @@
/*!
* @file WipperSnapper_I2C_Driver_INA238.cpp
*
* Device driver implementation for the INA238 High-precision DC Current and
* Voltage Monitor (Avoids import conflict with INA260 typedef enum _mode etc)
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#include "WipperSnapper_I2C_Driver_INA238.h"
#include "Wippersnapper.h"
#include <Adafruit_INA238.h>
/*******************************************************************************/
/*!
@brief Constructor for a INA238 sensor.
@param i2c
The I2C interface.
@param sensorAddress
The 7-bit I2C address of the sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA238::WipperSnapper_I2C_Driver_INA238(
TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress), _ina238(nullptr) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an INA238 sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA238::~WipperSnapper_I2C_Driver_INA238() {
delete _ina238;
}
/*******************************************************************************/
/*!
@brief Initializes the INA238 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA238::begin() {
_ina238 = new Adafruit_INA238();
if (!_ina238->begin(_sensorAddress, _i2c)) {
return false;
}
// Configuration based on INA238 example sketch
// Set default shunt resistance and maximum current
// Default 0.015 ohm shunt, 10A max current
_ina238->setShunt(0.015, 10.0);
// Set averaging for better accuracy (16 samples)
_ina238->setAveragingCount(INA2XX_COUNT_16);
// Set conversion times as per example
_ina238->setVoltageConversionTime(INA2XX_TIME_150_us);
_ina238->setCurrentConversionTime(INA2XX_TIME_280_us);
return true;
}
/*******************************************************************************/
/*!
@brief Reads a voltage sensor and converts the
reading into the expected SI unit.
@param voltageEvent
voltage sensor reading, in volts.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA238::getEventVoltage(
sensors_event_t *voltageEvent) {
voltageEvent->voltage = _ina238->getBusVoltage_V();
return true;
}
/**
* @brief Get the current sensor event.
*
* @param currentEvent Pointer to the current sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA238::getEventCurrent(
sensors_event_t *currentEvent) {
currentEvent->current = _ina238->getCurrent_mA();
return true;
}
/**
* @brief Get the Raw (power) sensor event.
*
* @param powerEvent Pointer to the power sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA238::getEventRaw(sensors_event_t *powerEvent) {
powerEvent->data[0] = _ina238->getPower_mW();
return true;
}

View file

@ -0,0 +1,44 @@
/*!
* @file WipperSnapper_I2C_Driver_INA238.h
*
* Device driver for the INA238 High-precision DC Current and Voltage Monitor
* 16-bit ADC with ±0.1% gain error, ±5µV offset voltage
* Higher precision version compared to INA237
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_INA238_H
#define WipperSnapper_I2C_Driver_INA238_H
#include "WipperSnapper_I2C_Driver.h"
// Forward declaration
class Adafruit_INA238;
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a INA238 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_INA238 : public WipperSnapper_I2C_Driver {
public:
WipperSnapper_I2C_Driver_INA238(TwoWire *i2c, uint16_t sensorAddress);
~WipperSnapper_I2C_Driver_INA238();
bool begin();
bool getEventVoltage(sensors_event_t *voltageEvent);
bool getEventCurrent(sensors_event_t *currentEvent);
bool getEventRaw(sensors_event_t *powerEvent);
protected:
Adafruit_INA238 *_ina238; ///< Pointer to INA238 sensor object
};
#endif // WipperSnapper_I2C_Driver_INA238

View file

@ -0,0 +1,89 @@
/*!
* @file WipperSnapper_I2C_Driver_INA260.cpp
*
* Device driver implementation for the INA260 DC Current and Voltage Monitor
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#include "WipperSnapper_I2C_Driver_INA260.h"
#include "Wippersnapper.h"
#include <Adafruit_INA260.h>
/*******************************************************************************/
/*!
@brief Constructor for a INA260 sensor.
@param i2c
The I2C interface.
@param sensorAddress
The 7-bit I2C address of the sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA260::WipperSnapper_I2C_Driver_INA260(
TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress), _ina260(nullptr) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an INA260 sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_INA260::~WipperSnapper_I2C_Driver_INA260() {
delete _ina260;
}
/*******************************************************************************/
/*!
@brief Initializes the INA260 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA260::begin() {
_ina260 = new Adafruit_INA260();
if (!_ina260->begin(_sensorAddress, _i2c)) {
return false;
}
// TODO: use setCalibration()
return true;
}
/*******************************************************************************/
/*!
@brief Reads a voltage sensor and converts the
reading into the expected SI unit.
@param voltageEvent
voltage sensor reading, in volts.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool WipperSnapper_I2C_Driver_INA260::getEventVoltage(
sensors_event_t *voltageEvent) {
voltageEvent->voltage = _ina260->readBusVoltage() / 1000.0f;
return true;
}
/**
* @brief Get the current sensor event.
*
* @param currentEvent Pointer to the current sensor event.
*
* @returns True if the sensor event was obtained successfully, False
* otherwise.
*/
bool WipperSnapper_I2C_Driver_INA260::getEventCurrent(
sensors_event_t *currentEvent) {
currentEvent->current = _ina260->readCurrent();
return true;
}

View file

@ -0,0 +1,41 @@
/*!
* @file WipperSnapper_I2C_Driver_INA260.h
*
* Device driver for the INA260 DC Current and Voltage Monitor
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_INA260_H
#define WipperSnapper_I2C_Driver_INA260_H
#include "WipperSnapper_I2C_Driver.h"
// Forward declaration
class Adafruit_INA260;
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a INA260 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_INA260 : public WipperSnapper_I2C_Driver {
public:
WipperSnapper_I2C_Driver_INA260(TwoWire *i2c, uint16_t sensorAddress);
~WipperSnapper_I2C_Driver_INA260();
bool begin();
bool getEventVoltage(sensors_event_t *voltageEvent);
bool getEventCurrent(sensors_event_t *currentEvent);
protected:
Adafruit_INA260 *_ina260 = nullptr; ///< Pointer to INA260 sensor object
};
#endif // WipperSnapper_I2C_Driver_INA260

View file

@ -0,0 +1,151 @@
/*!
* @file WipperSnapper_I2C_Driver_LPS28DFW.h
*
* Device driver for a LPS28DFW precision pressure sensor breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_LPS28DFW_H
#define WipperSnapper_I2C_Driver_LPS28DFW_H
#include "WipperSnapper_I2C_Driver.h"
#include <Adafruit_LPS28.h>
/**************************************************************************/
/*!
@brief Class that provides a sensor driver for the LPS28DFW temperature
and pressure sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_LPS28DFW : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for an LPS28DFW sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_LPS28DFW(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an LPS28DFW sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_LPS28DFW() { delete _lps28; }
/*******************************************************************************/
/*!
@brief Initializes the LPS28DFW sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
_lps28 = new Adafruit_LPS28();
// attempt to initialize LPS28DFW
if (!_lps28->begin(_i2c, _sensorAddress))
return false;
// Set up sample rate and filter initialization
if (!_lps28->setDataRate(LPS28_ODR_ONESHOT)) {
WS_DEBUG_PRINTLN("Failed to set data rate");
return false;
}
if (!_lps28->setAveraging(LPS28_AVG_512)) {
WS_DEBUG_PRINTLN("Failed to set averaging");
return false;
}
if (!_lps28->setFullScaleMode(true)) {
WS_DEBUG_PRINTLN("Failed to set 4060hPa max mode");
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Reads the sensor and stores the data in the object.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool readSensor() {
// grab one reading to seed the sensor
if (!_lps28->triggerOneShot()) {
return false;
}
// Wait (block up to 100ms) until data is ready
for (uint8_t i = 0; i < 100; i++) {
if (_lps28->getStatus() & LPS28_STATUS_PRESS_READY) {
if (_temp == NULL) {
_temp = _lps28->getTemperatureSensor();
}
if (_pressure == NULL) {
_pressure = _lps28->getPressureSensor();
}
return true;
}
delay(1);
}
return false;
}
/*******************************************************************************/
/*!
@brief Gets the LPS28DFW's current temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
if (!readSensor())
return false;
_temp->getEvent(tempEvent);
return true;
}
/*******************************************************************************/
/*!
@brief Reads a pressure sensor and converts
the reading into the expected SI unit.
@param pressureEvent
Pointer to an Adafruit_Sensor event.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventPressure(sensors_event_t *pressureEvent) {
if (!readSensor())
return false;
_pressure->getEvent(pressureEvent);
return true;
}
protected:
Adafruit_LPS28 *_lps28 = nullptr; ///< LPS28DFW object
Adafruit_Sensor *_temp =
NULL; ///< Ptr to an adafruit_sensor representing the temperature
Adafruit_Sensor *_pressure =
NULL; ///< Ptr to an adafruit_sensor representing the pressure
};
#endif // WipperSnapper_I2C_Driver_LPS28DFW

View file

@ -0,0 +1,233 @@
/*!
* @file WipperSnapper_I2C_Driver_MLX90632D.h
*
* Device driver for a Melexis MLX90632-D (medical) thermal FIR sensor.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_MLX90632D_H
#define WipperSnapper_I2C_Driver_MLX90632D_H
#include <Adafruit_MLX90632.h>
#include "WipperSnapper_I2C_Driver.h"
/**************************************************************************/
/*!
@brief Sensor driver for the Melexis MLX90632-D temperature sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_MLX90632D : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for an MLX90632 sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_MLX90632D(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_mlx90632 = nullptr;
_deviceTemp = NAN;
_objectTemp = NAN;
_lastRead = 0;
}
/*******************************************************************************/
/*!
@brief Destructor for an MLX90632 sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_MLX90632D() {
if (_mlx90632) {
delete _mlx90632;
_mlx90632 = nullptr;
}
}
/*******************************************************************************/
/*!
@brief Initializes the MLX90632 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
if (_mlx90632) {
delete _mlx90632;
_mlx90632 = nullptr;
}
_mlx90632 = new Adafruit_MLX90632();
// attempt to initialize MLX90632
if (!_mlx90632->begin(_sensorAddress, _i2c))
return false;
return ConfigureAndPrintSensorInfo();
}
/*******************************************************************************/
/*!
@brief Configures the MLX90632 sensor and prints its information.
@param extendedInsteadOfMedicalRange
If true, configures the sensor for extended temperature
range/acc.
@returns True if configuration fetching and setting were successful.
*/
/*******************************************************************************/
bool ConfigureAndPrintSensorInfo(bool extendedInsteadOfMedicalRange = false) {
// Reset the device
if (!_mlx90632->reset()) {
WS_DEBUG_PRINTLN(F("Device reset failed"));
return false;
}
uint16_t productCode = _mlx90632->getProductCode();
// Decode product code bits
uint8_t fov = (productCode >> 8) & 0x3;
uint8_t package = (productCode >> 5) & 0x7;
uint8_t accuracy = productCode & 0x1F;
if (!_mlx90632->setMode(MLX90632_MODE_CONTINUOUS)) {
WS_DEBUG_PRINTLN(F("Failed to set mode"));
return false;
}
// set accuracy mode based on medical if detected
if (accuracy == 1) {
// Set and get measurement select (medical)
if (!extendedInsteadOfMedicalRange &&
!_mlx90632->setMeasurementSelect(MLX90632_MEAS_MEDICAL)) {
WS_DEBUG_PRINTLN(F("Failed to set measurement select to Medical"));
return false;
} else if (extendedInsteadOfMedicalRange &&
!_mlx90632->setMeasurementSelect(
MLX90632_MEAS_EXTENDED_RANGE)) {
WS_DEBUG_PRINTLN(
F("Failed to set measurement select to Extended Range"));
return false;
}
}
// Set and get refresh rate (default to 2Hz)
if (!_mlx90632->setRefreshRate(MLX90632_REFRESH_2HZ)) {
WS_DEBUG_PRINTLN(F("Failed to set refresh rate to 2Hz"));
return false;
}
if (!_mlx90632->resetNewData()) {
WS_DEBUG_PRINTLN(F("Failed to reset new data flag"));
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
/*******************************************************************************/
bool HasBeenReadInLast200ms() {
return _lastRead != 0 && millis() - _lastRead < 200;
}
/*******************************************************************************/
/*!
@brief Reads the sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
bool result = false;
if (HasBeenReadInLast200ms()) {
WS_DEBUG_PRINTLN(F("Sensor was read recently, using cached data"));
return true;
}
// Check if we need to trigger a new measurement for step modes
mlx90632_mode_t currentMode = _mlx90632->getMode();
if (currentMode == MLX90632_MODE_STEP ||
currentMode == MLX90632_MODE_SLEEPING_STEP) {
// Trigger single measurement (SOC bit) for step modes
if (!_mlx90632->startSingleMeasurement()) {
WS_DEBUG_PRINTLN(F("Failed to start single measurement"));
return false;
}
delay(510); // Wait for measurement to complete @ 2Hz
}
// Only check new data flag - much more efficient for continuous mode
if (_mlx90632->isNewData()) {
_deviceTemp = _mlx90632->getAmbientTemperature();
_objectTemp = _mlx90632->getObjectTemperature();
if (isnan(_objectTemp)) {
WS_DEBUG_PRINTLN(F("NaN (invalid cycle position)"));
return false;
}
result = true;
_lastRead = millis();
// Reset new data flag after reading
if (!_mlx90632->resetNewData()) {
WS_DEBUG_PRINTLN(F("Failed to reset new data flag"));
}
} else {
WS_DEBUG_PRINTLN(F("No new data available, skipping read"));
}
return result;
}
/*******************************************************************************/
/*!
@brief Gets the MLX90632's current temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
if (ReadSensorData() && _deviceTemp != NAN) {
tempEvent->temperature = _deviceTemp;
return true;
}
return false; // sensor not read recently, return false
}
/*******************************************************************************/
/*!
@brief Gets the MLX90632's object temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventObjectTemp(sensors_event_t *tempEvent) {
if (ReadSensorData() && _objectTemp != NAN) {
tempEvent->temperature = _objectTemp;
return true;
}
return false; // sensor not read recently, return false
}
protected:
double _deviceTemp; ///< Device temperature in Celsius
double _objectTemp; ///< Object temperature in Celsius
uint32_t _lastRead; ///< Last time the sensor was read in milliseconds
Adafruit_MLX90632 *_mlx90632 = nullptr; ///< MLX90632 object
};
#endif // WipperSnapper_I2C_Driver_MLX90632D_H

View file

@ -0,0 +1,145 @@
/*!
* @file WipperSnapper_I2C_Driver_Out.h
*
* Derived class for I2C output driver components
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_H
#include "WipperSnapper_I2C_Driver.h"
#include <Arduino.h>
/*!
@brief Derived class for I2C output component drivers.
*/
class WipperSnapper_I2C_Driver_Out : public WipperSnapper_I2C_Driver {
public:
/*!
@brief Creates a new I2C output component driver.
@param i2c
The I2C hardware interface, default is Wire.
@param sensorAddress
The I2C sensor's unique address.
*/
WipperSnapper_I2C_Driver_Out(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
// No-op constructor
}
/*!
@brief Destructor for an I2C output component.
*/
virtual ~WipperSnapper_I2C_Driver_Out() {
// No-op destructor
}
/*!
@brief Writes a message to an i2c output device.
@param message
The message to be displayed.
*/
virtual void WriteMessage(const char *message) {
// noop
}
/*!
@brief Configures a SSD1306 OLED display. Must be called before driver
begin()
@param width
The width of the display in pixels.
@param height
The height of the display in pixels.
@param text_size
The display's text size.
@param rotation
The rotation of the display in degrees, default is 0.
*/
virtual void ConfigureSSD1306(uint8_t width, uint8_t height,
uint8_t text_size, uint8_t rotation = 0) {
// noop
}
/*!
@brief Writes a message to the SSD1306 display.
@param message
The message to be displayed.
*/
virtual void WriteMessageSSD1306(const char *message) {
// noop
}
/*!
@brief Configures a LED backpack.
@param brightness
The brightness of the LED backpack.
@param alignment
The alignment of the LED backpack.
*/
virtual void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) {
// noop
}
/*!
@brief Sets the brightness of the LED backpack.
@param b
The brightness value, from 0 (off) to 15 (full brightness).
*/
virtual void SetLedBackpackBrightness(uint8_t b) {
// noop
}
/*!
@brief Writes a message to the LED backpack.
@param msg_write
Pointer to a wippersnapper_i2c_v1_LedBackpackWrite message.
*/
void WriteLedBackpack(wippersnapper_i2c_v1_LEDBackpackWrite *msg_write) {
WriteMessage(msg_write->message);
}
/*!
@brief Configures a character LCD.
@param rows
The number of rows in the LCD.
@param cols
The number of columns in the LCD.
*/
virtual void ConfigureCharLcd(uint32_t rows, uint32_t cols) {
// noop
}
/*!
@brief Turns the character LCD backlight on or off.
@param enable
True to enable the backlight, false to disable it.
*/
void EnableCharLcdBacklight(bool enable) {
// noop
}
/*!
@brief Writes a message to the LCD.
@param write_char_lcd
Points to a CharLCDWrite message.
@param enable_backlight
True if the backlight should be enabled, false otherwise.
*/
void WriteMessageCharLCD(wippersnapper_i2c_v1_CharLCDWrite *write_char_lcd,
bool enable_backlight = true) {
EnableCharLcdBacklight(enable_backlight);
WriteMessage(write_char_lcd->message);
}
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_H

View file

@ -0,0 +1,209 @@
/*!
* @file WipperSnapper_I2C_Driver_Out_7Seg.h
*
* Device driver designed specifically to work with the Adafruit LED 7-Segment
* I2C backpacks:
* ----> http://www.adafruit.com/products/881
* ----> http://www.adafruit.com/products/880
* ----> http://www.adafruit.com/products/879
* ----> http://www.adafruit.com/products/878
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell for Adafruit Industries 2025
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H
#include "WipperSnapper_I2C_Driver_Out.h"
#include <Adafruit_LEDBackpack.h>
#include <Arduino.h>
#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment
#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment
#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment
#define LED_BACKPACK_ALIGNMENT_DEFAULT \
LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment
#define LED_MAX_CHARS \
5 ///< Maximum characters for 7-segment display, including ':'
#define LED_BACKPACK_DEGREE_SYMBOL \
0b01100011 ///< Degree symbol for 7-segment display
/*!
@brief Class that provides a driver interface for 7-Segment
Displays w/I2C Backpack
*/
class WipperSnapper_I2C_Driver_Out_7Seg : public WipperSnapper_I2C_Driver_Out {
public:
/*******************************************************************************/
/*!
@brief Constructor for a 7-Segment display driver.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_Out_7Seg(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*!
@brief Destructor for a 7-Segment display driver.
*/
~WipperSnapper_I2C_Driver_Out_7Seg() {
if (_matrix != nullptr) {
delete _matrix;
_matrix = nullptr;
}
}
/*!
@brief Initializes the 7-segment LED matrix and begins I2C
communication.
@returns True if initialized successfully, False otherwise.
*/
bool begin() {
_matrix = new Adafruit_7segment();
bool did_begin = _matrix->begin(_sensorAddress, _i2c);
return did_begin;
}
/*!
@brief Configures the LED matrix's I2C backpack.
@param brightness
The brightness of the i2c backpack (0-15).
@param alignment
The alignment of the i2c backpack's LED matrix (left/right).
*/
void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) {
if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) {
_alignment = LED_BACKPACK_ALIGNMENT_RIGHT;
} else {
_alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
}
// Note: Adafruit_LEDBackpack normalizes only > 15, but not < 0,
// so, here we're normalizing < 0 to 8 (median brightness)
if (brightness < 0) {
brightness = 8; // Set to median brightness if out of range
}
}
/*!
@brief Sets the brightness of the LED backpack.
@param b
The brightness value, from 0 (off) to 15 (full brightness).
*/
void SetLedBackpackBrightness(uint8_t b) {
if (_matrix == nullptr) {
return;
}
_matrix->setBrightness(b);
}
/*!
@brief Writes the first four characters of a message to the Adafruit
7-segment LED matrix.
@param message
The message to be displayed.
*/
void WriteMessage(const char *message) {
if (_matrix == nullptr || message == nullptr) {
return;
}
// Clear before writing
_matrix->clear();
// Calculate the number of characters to display
size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS);
// Set the starting position based on alignment
int pos_start;
if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) {
pos_start = 0; // start at the leftmost position of the display
} else {
// Exclude decimal points from the character count because those get
// displayed on a "special" segment of the LED display
int seg_chars = 0;
for (size_t i = 0; i < len_display; i++) {
if (message[i] != '.') {
seg_chars++;
}
}
// start at the rightmost position of the display
switch (seg_chars) {
case 4:
pos_start = 0;
break;
case 3:
pos_start = 1;
break;
case 2:
pos_start = 3; // if 2 characters, start at position 3 is required
// because ':' is position 2 and we need to skip it
break;
case 1:
pos_start = 4;
break;
default:
pos_start = 0; // if no characters or overflow, start at position 0
break;
}
}
// Write to the display's buffer
int cur_idx = pos_start;
for (size_t i = 0; i < len_display; i++) {
// skip position 2
if (cur_idx == 2) {
cur_idx++;
}
// Save the character because if there's a decimal, we need to skip it in
// the buffer
char ch = message[i];
// Look-ahead for a decimal point to attach to the current character
bool display_dot = false;
if (i + 1 < len_display && message[i + 1] == '.') {
display_dot = true;
i++;
len_display++;
} else if (message[i] == 0xC2 && message[i + 1] == 0xB0 &&
i + 1 < strlen(message)) {
// Write degree symbol
_matrix->writeDigitRaw(cur_idx, LED_BACKPACK_DEGREE_SYMBOL);
i++;
cur_idx++;
continue; // skip to next character
}
// Write the character to the display buffer
_matrix->writeDigitAscii(cur_idx, ch, display_dot);
cur_idx++;
}
// Issue the buffered data in RAM to the display
_matrix->writeDisplay();
}
protected:
Adafruit_7segment *_matrix =
nullptr; ///< ptr to a 7-segment LED matrix object
int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15
///< (full brightness)
uint32_t _alignment =
LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the
///< message displayed
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H

View file

@ -0,0 +1,163 @@
/*!
* @file WipperSnapper_I2C_Driver_Out_CharLcd.h
*
* Device driver for I2C Character LCDs (HD44780)
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell for Adafruit Industries 2025
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H
#include "WipperSnapper_I2C_Driver_Out.h"
#include <Adafruit_LiquidCrystal.h>
/*!
@brief Class that provides a driver interface for a lcd character display.
This class is a wrapper around the Adafruit_LiquidCrystal library.
*/
class WipperSnapper_I2C_Driver_Out_CharLcd
: public WipperSnapper_I2C_Driver_Out {
public:
/*!
@brief Constructor for a LCD character display.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
WipperSnapper_I2C_Driver_Out_CharLcd(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*!
@brief Destructor for an MS8607 sensor.
*/
~WipperSnapper_I2C_Driver_Out_CharLcd() {
if (_lcd != nullptr) {
delete _lcd;
_lcd = nullptr;
}
}
/*!
@brief Initializes the drvOutQuadAlphaNum component and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
bool begin() {
_lcd = new Adafruit_LiquidCrystal(_sensorAddress, _i2c);
bool did_begin = _lcd->begin(_cols, _rows);
if (did_begin) {
_lcd->setBacklight(HIGH);
}
return did_begin;
}
/*!
@brief Writes a message to the LCD.
@note MUST be called prior to begin() to configure the LCD's size
@param rows
The number of rows in the LCD.
@param cols
The number of columns in the LCD.
*/
void ConfigureCharLcd(uint8_t rows, uint8_t cols) {
_rows = rows;
_cols = cols;
}
/*!
@brief Turns the character LCD backlight on or off.
@param enable
True to enable the backlight, false to disable it.
*/
void EnableCharLcdBacklight(bool enable = true) {
if (_lcd == nullptr)
return;
if (enable) {
_lcd->setBacklight(HIGH);
} else {
_lcd->setBacklight(LOW);
}
}
/*!
@brief Writes a message to the LCD.
@param message
The message to be displayed.
*/
void WriteMessage(const char *message) {
if (_lcd == nullptr)
return;
// Before writing, let's clear the display
_lcd->clear();
size_t message_length = strlen(message);
size_t cur_idx = 0; // Current index in the message
// Write each row until it hits: \n, or the end of the message, or the last
// column/row position
for (int cur_row = 0; cur_row < _rows && cur_idx < message_length;
cur_row++) {
// Write each row out at the beginning of the row
_lcd->setCursor(0, cur_row);
for (int cur_col = 0; cur_col < _cols && cur_idx < message_length;
cur_col++) {
char c = message[cur_idx];
if (c == '\\' && cur_idx + 1 < message_length &&
(message[cur_idx + 1] == 'n' || message[cur_idx + 1] == 'r')) {
// Handle \r\n sequence as a single newline
if (message[cur_idx + 1] == 'r' && cur_idx + 3 < message_length &&
message[cur_idx + 2] == '\\' && message[cur_idx + 3] == 'n') {
cur_idx += 4; // Skip \r\n and don't move the cursor two rows
break; // Move to the next row
} else {
if (message[cur_idx + 1] == 'r') {
_lcd->write('\\');
_lcd->write('r');
cur_idx += 2; // Skip the \r
} else {
cur_idx += 2; // Skip the \n
break; // Move to the next row
}
}
} else if ((c == 0x0A || c == 0x0D) && cur_idx + 1 < message_length) {
if (c == 0x0A && cur_idx + 1 < message_length &&
message[cur_idx + 1] == 0x0D) {
cur_idx += 2; // Skip both LF and CR characters
} else {
cur_idx += 1; // Skip single newline character
}
break; // and move to the next row
} else if (c == 194 && cur_idx + 1 < message_length &&
message[cur_idx + 1] == 176) {
cur_idx += 2; // Skip the degree symbol sequence in the buffer
_lcd->write(0xDF); // and write the degree symbol
} else {
_lcd->write(c);
cur_idx++;
}
}
}
}
protected:
Adafruit_LiquidCrystal *_lcd =
nullptr; ///< Pointer to the Adafruit_LiquidCrystal object
uint8_t _rows; ///< Number of rows in the display
uint8_t _cols; ///< Number of columns in the display
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H

View file

@ -0,0 +1,178 @@
/*!
* @file WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h
*
* Device driver for Quad Alphanumeric Displays w/I2C Backpack
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell for Adafruit Industries 2025
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H
#include "WipperSnapper_I2C_Driver_Out.h"
#include <Adafruit_LEDBackpack.h>
#include <Arduino.h>
#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment
#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment
#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment
#define LED_BACKPACK_ALIGNMENT_DEFAULT \
LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment
#define LED_MAX_CHARS \
4 ///< Maximum number of characters to display on the alphanumeric display
#define ALPHANUM_DEGREE_SYMBOL \
0b0000000011100011 ///< Degree symbol for alphanumeric display
/*!
@brief Class that provides a driver interface for Quad Alphanumeric
Displays w/I2C Backpack
*/
class WipperSnapper_I2C_Driver_Out_QuadAlphaNum
: public WipperSnapper_I2C_Driver_Out {
public:
/*******************************************************************************/
/*!
@brief Constructor for an MS8607 sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_Out_QuadAlphaNum(TwoWire *i2c,
uint16_t sensorAddress)
: WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*!
@brief Destructor for an MS8607 sensor.
*/
~WipperSnapper_I2C_Driver_Out_QuadAlphaNum() {
if (_alpha4 != nullptr) {
delete _alpha4;
_alpha4 = nullptr;
}
}
/*!
@brief Initializes the drvOutQuadAlphaNum component and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
bool begin() {
_alpha4 = new Adafruit_AlphaNum4();
bool did_begin = _alpha4->begin(_sensorAddress, _i2c);
_alpha4->setBrightness(_brightness);
return did_begin;
}
/*!
@brief Configures a LED backpack.
@param brightness
The brightness of the LED backpack.
@param alignment
The alignment of the LED backpack.
*/
void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) {
if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) {
_alignment = LED_BACKPACK_ALIGNMENT_RIGHT;
} else {
_alignment = LED_BACKPACK_ALIGNMENT_DEFAULT;
}
_brightness = brightness;
}
/*!
@brief Sets the brightness of the LED backpack.
@param b
The brightness value, from 0 (off) to 15 (full brightness).
*/
void SetLedBackpackBrightness(uint8_t b) {
if (_alpha4 == nullptr) {
return;
}
_alpha4->setBrightness(b);
}
/*!
@brief Writes the first four characters of a message to the quad
alphanumeric display.
@param message
The message to be displayed.
*/
void WriteMessage(const char *message) {
if (_alpha4 == nullptr || message == nullptr) {
return;
}
// Clear before writing
_alpha4->clear();
// Calculate the number of characters to display
size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS);
// Set the starting position based on alignment
int pos_start;
if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) {
pos_start = 0; // start at the leftmost position of the display
} else {
// Exclude decimal points from the character count because those get
// displayed on a "special" segment of the LED display
int seg_chars = 0;
for (size_t i = 0; i < len_display; i++) {
if (message[i] != '.') {
seg_chars++;
}
}
// start at the rightmost position of the display
pos_start = LED_MAX_CHARS - seg_chars;
}
// Write to the display's buffer
int cur_idx = pos_start;
for (size_t i = 0; i < len_display; i++) {
// Save the character because if there's a decimal, we need to skip it in
// the buffer
char ch = message[i];
// Look-ahead for a decimal point to attach to the current character
bool display_dot = false;
if (i + 1 < len_display && message[i + 1] == '.') {
display_dot = true;
i++;
len_display++;
} else if (message[i] == 0xC2 && message[i + 1] == 0xB0 &&
i + 1 < strlen(message)) {
// Write the degree symbol
_alpha4->writeDigitRaw(cur_idx, ALPHANUM_DEGREE_SYMBOL);
i++;
cur_idx++;
continue;
}
// Write the character to the display buffer
_alpha4->writeDigitAscii(cur_idx, ch, display_dot);
cur_idx++;
}
// Issue the buffered data in RAM to the display
_alpha4->writeDisplay();
}
protected:
Adafruit_AlphaNum4 *_alpha4 =
nullptr; ///< ptr to a 4-digit alphanumeric display object
int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15
///< (full brightness)
uint32_t _alignment =
LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the
///< message displayed
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H

View file

@ -0,0 +1,208 @@
/*!
* @file WipperSnapper_I2C_Driver_Out_SH1107.h
*
* Device driver for a SH1107 OLED Display
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry for Adafruit Industries 2025
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H
#include "WipperSnapper_I2C_Driver_Out.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <Arduino.h>
#define WS_SH1107_DEFAULT_WIDTH \
128 ///< Default width for a sh1107 128x64 display
#define WS_SH1107_DEFAULT_HEIGHT \
64 ///< Default height for a sh1107 128x64 display
#define OLED_128X64_WING_WIDTH 128 ///< Width of the 128x64 OLED FeatherWing
#define OLED_128X64_WING_HEIGHT 64 ///< Height of the 128x64 OLED FeatherWing
#define OLED_128X64_WING_ROTATION_90 1 ///< Rotation of OLED FeatherWing 0-3
/*!
@brief Class that provides a driver interface for a SH1107
OLED Display
*/
class WipperSnapper_I2C_Driver_Out_SH1107
: public WipperSnapper_I2C_Driver_Out {
public:
/*******************************************************************************/
/*!
@brief Constructor for an SH1107 OLED display.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_Out_SH1107(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_width = WS_SH1107_DEFAULT_WIDTH;
_height = WS_SH1107_DEFAULT_HEIGHT;
}
/*!
@brief Destructor for a SH1107 OLED display.
*/
~WipperSnapper_I2C_Driver_Out_SH1107() {
if (_display != nullptr) {
_display->clearDisplay();
_display->display();
_display->oled_command(SH110X_DISPLAYOFF);
delete _display;
_display = nullptr;
}
}
/*!
@brief Initializes the SH1107 display and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
bool begin() {
if (_width == OLED_128X64_WING_WIDTH &&
_height == OLED_128X64_WING_HEIGHT &&
_rotation == OLED_128X64_WING_ROTATION_90) {
// featherwing needs to be rotated 90 degrees and swap w/h ctor args
_display = new Adafruit_SH1107(_height, _width, _i2c);
} else {
_display = new Adafruit_SH1107(_width, _height, _i2c);
}
if (!_display->begin(_sensorAddress, true))
return false;
// Clear the buffer.
_display->clearDisplay();
_display->display();
_display->setRotation(_rotation); // 0-3, not degrees for SH1107
// Configure the text size and color
_display->setTextSize(_text_sz);
_display->setTextColor(SH110X_WHITE);
_display->setCursor(0, 0);
// Clear the buffer
_display->clearDisplay();
_display->display();
return true;
}
/*!
@brief Configures a SH1107 OLED display. Must be called before driver
begin()
@param width
The width of the display in pixels.
@param height
The height of the display in pixels.
@param text_size
The magnification factor for the text size.
@param rotation
The rotation of the display in degrees, default is 0.
*/
void ConfigureSH1107(uint8_t width, uint8_t height, uint8_t text_size,
uint8_t rotation) {
_width = width;
_height = height;
_text_sz = text_size;
_rotation =
rotation % 90; // SH1107 requires rotation to be 0-3, not degrees
}
/*!
@brief Configures a SSD1306 OLED display. Must be called before driver
begin() - This is a fake function to match the SSD1306 interface.
@param width
The width of the display in pixels.
@param height
The height of the display in pixels.
@param text_size
The magnification factor for the text size.
@param rotation
The rotation of the display in degrees, default is 0.
*/
void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size,
uint8_t rotation) {
// This is a SH1107, not a SSD1306, so we don't need to do anything here.
ConfigureSH1107(width, height, text_size, rotation);
}
/*!
@brief Writes a message to the SH1107 display.
@param message
The message to be displayed.
*/
void WriteMessageSH1107(const char *message) {
if (_display == nullptr)
return;
// Start with a fresh display buffer
// and settings
int16_t y_idx = 0;
_display->clearDisplay();
_display->setTextSize(_text_sz);
_display->setTextColor(SH110X_WHITE);
_display->setCursor(0, y_idx);
_display->display();
// Calculate the line height based on the text size (NOTE: base height is
// 8px)
int16_t line_height = 8 * _text_sz;
uint16_t c_idx = 0;
size_t msg_size = strlen(message);
for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) {
if (message[i] == '\\' && i + 1 < msg_size &&
(message[i + 1] == 'n' || message[i + 1] == 'r')) {
// Handle \r\n sequence as a single newline
if (message[i + 1] == 'r' && i + 3 < msg_size &&
message[i + 2] == '\\' && message[i + 3] == 'n') {
// Skip to the next line
y_idx += line_height;
_display->setCursor(0, y_idx);
i += 3;
} else if (message[i + 1] == 'n') {
// Skip to the next line
y_idx += line_height;
_display->setCursor(0, y_idx);
i++;
}
} else if (message[i] == 0xC2 && message[i + 1] == 0xB0) {
_display->write(char(248));
_display->display();
i++;
} else {
_display->print(message[i]);
_display->display();
}
}
}
/*!
@brief Writes a message to the fake "SSD1306" SH1107 display.
@param message
The message to be displayed.
*/
void WriteMessageSSD1306(const char *message) {
// This is a SH1107, not a SSD1306, so we just call the SH1107 write
WriteMessageSH1107(message);
}
protected:
Adafruit_SH1107 *_display =
nullptr; ///< Pointer to the Adafruit_SH1107 object
uint8_t _width; ///< Width of the display in pixels
uint8_t _height; ///< Height of the display in pixels
uint8_t _rotation; ///< Rotation of the display (0-3)
uint8_t _text_sz; ///< Text size of the display
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H

View file

@ -0,0 +1,166 @@
/*!
* @file WipperSnapper_I2C_Driver_Out_Ssd1306.h
*
* Device driver for a SSD1306 OLED Display
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell for Adafruit Industries 2025
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H
#define WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H
#include "WipperSnapper_I2C_Driver_Out.h"
#include <Adafruit_SSD1306.h>
#include <Arduino.h>
#define WS_SSD1306_DEFAULT_WIDTH \
128 ///< Default width for a ssd1306 128x64 display
#define WS_SSD1306_DEFAULT_HEIGHT \
64 ///< Default height for a ssd1306 128x64 display
/*!
@brief Class that provides a driver interface for a SSD1306
OLED Display
*/
class WipperSnapper_I2C_Driver_Out_Ssd1306
: public WipperSnapper_I2C_Driver_Out {
public:
/*******************************************************************************/
/*!
@brief Constructor for a SSD1306 OLED display.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_Out_Ssd1306(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_width = WS_SSD1306_DEFAULT_WIDTH;
_height = WS_SSD1306_DEFAULT_HEIGHT;
}
/*!
@brief Destructor for a SSD1306 OLED display.
*/
~WipperSnapper_I2C_Driver_Out_Ssd1306() {
if (_display != nullptr) {
_display->clearDisplay();
_display->display();
_display->ssd1306_command(SSD1306_DISPLAYOFF);
delete _display;
_display = nullptr;
}
}
/*!
@brief Initializes the SSD1306 display and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
bool begin() {
// Attempt to create and allocate a SSD1306 obj.
_display = new Adafruit_SSD1306(_width, _height, _i2c);
if (!_display->begin(SSD1306_SWITCHCAPVCC, _sensorAddress))
return false;
// Configure the rotation, text size and color
_display->setRotation(_rotation);
_display->setTextSize(_text_sz);
_display->setTextColor(SSD1306_WHITE);
// Use full 256 char 'Code Page 437' font
_display->cp437(true);
// Clear the buffer
_display->clearDisplay();
_display->display();
return true;
}
/*!
@brief Configures a SSD1306 OLED display. Must be called before driver
begin()
@param width
The width of the display in pixels.
@param height
The height of the display in pixels.
@param text_size
The magnification factor for the text size.
@param rotation
The rotation of the display in degrees, default is 0.
*/
void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size,
uint8_t rotation = 0) {
_width = width;
_height = height;
_text_sz = text_size;
_rotation = rotation;
}
/*!
@brief Writes a message to the SSD1306 display.
@param message
The message to be displayed.
*/
void WriteMessageSSD1306(const char *message) {
if (_display == nullptr)
return;
// Start with a fresh display buffer
// and settings
int16_t y_idx = 0;
_display->clearDisplay();
_display->setTextSize(_text_sz);
_display->setTextColor(SSD1306_WHITE);
_display->setCursor(0, y_idx);
_display->display();
// Calculate the line height based on the text size (NOTE: base height is
// 8px)
int16_t line_height = 8 * _text_sz;
uint16_t c_idx = 0;
size_t msg_size = strlen(message);
for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) {
if (message[i] == '\\' && i + 1 < msg_size &&
(message[i + 1] == 'n' || message[i + 1] == 'r')) {
// Handle \r\n sequence as a single newline
if (message[i + 1] == 'r' && i + 3 < msg_size &&
message[i + 2] == '\\' && message[i + 3] == 'n') {
// Skip to the next line
y_idx += line_height;
_display->setCursor(0, y_idx);
i += 3;
} else if (message[i + 1] == 'n') {
// Skip to the next line
y_idx += line_height;
_display->setCursor(0, y_idx);
i++;
}
} else if (message[i] == 0xC2 && message[i + 1] == 0xB0) {
_display->write(char(248));
_display->display();
i++;
} else {
_display->print(message[i]);
_display->display();
}
}
}
protected:
Adafruit_SSD1306 *_display =
nullptr; ///< Pointer to the Adafruit_SSD1306 object
uint8_t _width; ///< Width of the display in pixels
uint8_t _height; ///< Height of the display in pixels
uint8_t _rotation; ///< Rotation of the display in degrees
uint8_t _text_sz; ///< Text size of the display
};
#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H

View file

@ -71,7 +71,7 @@ public:
*/
/*******************************************************************************/
bool getEventPM10_STD(sensors_event_t *pm10StdEvent) {
PM25_AQI_Data data;
PM25_AQI_Data data = {0};
if (!_pm25->read(&data))
return false; // couldn't read data
@ -89,7 +89,7 @@ public:
*/
/*******************************************************************************/
bool getEventPM25_STD(sensors_event_t *pm25StdEvent) {
PM25_AQI_Data data;
PM25_AQI_Data data = {0};
if (!_pm25->read(&data))
return false; // couldn't read data
@ -107,7 +107,7 @@ public:
*/
/*******************************************************************************/
bool getEventPM100_STD(sensors_event_t *pm100StdEvent) {
PM25_AQI_Data data;
PM25_AQI_Data data = {0};
if (!_pm25->read(&data))
return false; // couldn't read data
@ -116,7 +116,7 @@ public:
}
protected:
Adafruit_PM25AQI *_pm25; ///< PM25 driver object
Adafruit_PM25AQI *_pm25 = nullptr; ///< PM25 driver object
};
#endif // WipperSnapper_I2C_Driver_PM25

View file

@ -53,6 +53,56 @@ public:
return _scd->begin((uint8_t)_sensorAddress, _i2c);
}
/*******************************************************************************/
/*!
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
bool HasBeenReadInLastSecond() {
return _lastRead != 0 && millis() - _lastRead < 1000;
}
/*******************************************************************************/
/*!
@brief Checks if the sensor is ready to be read
@returns True if the sensor is ready, False otherwise.
*/
/*******************************************************************************/
bool IsSensorReady() {
if (!_scd->dataReady()) {
// failed, one more quick attempt
delay(100);
if (!_scd->dataReady()) {
return false;
}
}
return true;
}
/*******************************************************************************/
/*!
@brief Reads the SCD30 sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
// dont read sensor more than once per second
if (HasBeenReadInLastSecond()) {
return true;
}
if (!IsSensorReady()) {
return false;
}
if (!_scd->getEvent(&_humidity, &_temperature)) {
return false;
}
_CO2.CO2 = _scd->CO2;
_lastRead = millis();
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SCD30's current temperature.
@ -64,14 +114,11 @@ public:
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
// check if sensor is enabled and data is available
if (_tempSensorPeriod != 0 && (!_scd->dataReady()))
return false;
// attempt to get temperature data
sensors_event_t humidEvent;
if (!_scd->getEvent(&humidEvent, tempEvent))
if (!ReadSensorData()) {
return false;
}
*tempEvent = _temperature;
return true;
}
@ -86,14 +133,11 @@ public:
/*******************************************************************************/
bool getEventRelativeHumidity(sensors_event_t *humidEvent) {
// check if sensor is enabled and data is available
if (_humidSensorPeriod != 0 && (!_scd->dataReady()))
return false;
// attempt to get temperature data
sensors_event_t tempEvent;
if (!_scd->getEvent(humidEvent, &tempEvent))
if (!ReadSensorData()) {
return false;
}
*humidEvent = _humidity;
return true;
}
@ -108,15 +152,20 @@ public:
/*******************************************************************************/
bool getEventCO2(sensors_event_t *co2Event) {
// check if sensor is enabled and data is available
if (_CO2SensorPeriod != 0 && (!_scd->dataReady()))
if (!ReadSensorData()) {
return false;
}
co2Event->CO2 = _scd->CO2;
*co2Event = _CO2;
return true;
}
protected:
Adafruit_SCD30 *_scd; ///< SCD30 driver object
Adafruit_SCD30 *_scd = nullptr; ///< SCD30 driver object
ulong _lastRead = 0uL; ///< Last time the sensor was read
sensors_event_t _temperature = {0}; ///< Temperature
sensors_event_t _humidity = {0}; ///< Relative Humidity
sensors_event_t _CO2 = {0}; ///< CO2
};
#endif // WipperSnapper_I2C_Driver_SCD30

View file

@ -18,7 +18,7 @@
#define WipperSnapper_I2C_Driver_SCD4X_H
#include "WipperSnapper_I2C_Driver.h"
#include <SensirionI2CScd4x.h>
#include <SensirionI2cScd4x.h>
#include <Wire.h>
/**************************************************************************/
@ -51,42 +51,78 @@ public:
*/
/*******************************************************************************/
bool begin() {
_scd = new SensirionI2CScd4x();
_scd->begin(*_i2c);
_scd = new SensirionI2cScd4x();
_scd->begin(*_i2c, _sensorAddress);
// stop previously started measurement
if (_scd->stopPeriodicMeasurement())
if (_scd->stopPeriodicMeasurement() != 0) {
return false;
}
// start measurements
if (_scd->startPeriodicMeasurement())
if (_scd->startPeriodicMeasurement() != 0) {
return false;
}
return true;
}
/********************************************************************************/
/*******************************************************************************/
/*!
@brief Attempts to read the SCD4x's sensor measurements
@returns True if the measurements were read without errors, False
if read errors occured or if sensor did not have data ready.
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
/********************************************************************************/
bool readSensorMeasurements() {
uint16_t error;
bool isDataReady = false;
delay(100);
/*******************************************************************************/
bool HasBeenReadInLastSecond() {
return _lastRead != 0 && millis() - _lastRead < 1000;
}
// Check if data is ready
error = _scd->getDataReadyFlag(isDataReady);
if (error || !isDataReady)
/*******************************************************************************/
/*!
@brief Checks if the sensor is ready to be read
@returns True if the sensor is ready, False otherwise.
*/
/*******************************************************************************/
bool IsSensorReady() {
bool isDataReady = false;
for (int i = 0; i < 2; i++) {
uint16_t error = _scd->getDataReadyStatus(isDataReady);
if (error == 0 && isDataReady) {
return true;
}
delay(100);
}
return false;
}
/*******************************************************************************/
/*!
@brief Reads the sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
// dont read sensor more than once per second
if (HasBeenReadInLastSecond()) {
return true;
}
if (!IsSensorReady()) {
return false;
}
// Read SCD4x measurement
error = _scd->readMeasurement(_co2, _temperature, _humidity);
if (error || _co2 == 0)
uint16_t co2 = 0;
float temperature = 0;
float humidity = 0;
int16_t error = _scd->readMeasurement(co2, temperature, humidity);
if (error != 0 || co2 == 0) {
return false;
}
_CO2.CO2 = co2;
_temperature.temperature = temperature;
_humidity.relative_humidity = humidity;
_lastRead = millis();
return true;
}
@ -101,10 +137,11 @@ public:
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
// read all sensor measurements
if (!readSensorMeasurements())
if (!ReadSensorData()) {
return false;
}
tempEvent->temperature = _temperature;
*tempEvent = _temperature;
return true;
}
@ -119,10 +156,11 @@ public:
/*******************************************************************************/
bool getEventRelativeHumidity(sensors_event_t *humidEvent) {
// read all sensor measurements
if (!readSensorMeasurements())
if (!ReadSensorData()) {
return false;
}
humidEvent->relative_humidity = _humidity;
*humidEvent = _humidity;
return true;
}
@ -137,18 +175,20 @@ public:
/*******************************************************************************/
bool getEventCO2(sensors_event_t *co2Event) {
// read all sensor measurements
if (!readSensorMeasurements())
if (!ReadSensorData()) {
return false;
}
co2Event->CO2 = (float)_co2;
*co2Event = _CO2;
return true;
}
protected:
SensirionI2CScd4x *_scd; ///< SCD4x driver object
uint16_t _co2; ///< SCD4x co2 reading
float _temperature; ///< SCD4x temperature reading
float _humidity; ///< SCD4x humidity reading
SensirionI2cScd4x *_scd = nullptr; ///< SCD4x driver object
sensors_event_t _temperature = {0}; ///< Temperature
sensors_event_t _humidity = {0}; ///< Relative Humidity
sensors_event_t _CO2 = {0}; ///< CO2
ulong _lastRead = 0uL; ///< Last time the sensor was read
};
#endif // WipperSnapper_I2C_Driver_SCD4X
#endif // WipperSnapper_I2C_Driver_SCD4X_H

View file

@ -1,14 +1,13 @@
/*!
* @file WipperSnapper_I2C_Driver_SEN5X.h
*
* Device driver for the SEN5X CO2, Temperature, and Humidity sensor.
* TEMPORARY HACK
* Device driver for the SEN5X air quality sensors.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Marni Brewster 2022 for Adafruit Industries.
* Copyright (c) Tyeth Gundry 2022 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
@ -44,6 +43,14 @@ public:
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_massConcentrationPm1p0 = NAN;
_massConcentrationPm2p5 = NAN;
_massConcentrationPm4p0 = NAN;
_massConcentrationPm10p0 = NAN;
_ambientHumidity = NAN;
_ambientTemperature = NAN;
_vocIndex = NAN;
_noxIndex = NAN;
}
/*******************************************************************************/
@ -69,6 +76,60 @@ public:
return true;
}
/*******************************************************************************/
/*!
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
bool HasBeenReadInLastSecond() {
return _lastRead != 0 && millis() - _lastRead < 1000;
}
/*******************************************************************************/
/*!
@brief Checks if the sensor is ready to be read
@returns True if the sensor is ready, False otherwise.
*/
/*******************************************************************************/
bool IsSensorReady() {
bool isDataReady = false;
for (int i = 0; i < 2; i++) {
uint16_t error = _sen->readDataReady(isDataReady);
if (error == 0 && isDataReady) {
return true;
}
delay(100);
}
return false;
}
/*******************************************************************************/
/*!
@brief Reads the sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
// dont read sensor more than once per second
if (HasBeenReadInLastSecond()) {
return true;
}
if (!IsSensorReady()) {
return false;
}
uint16_t error = _sen->readMeasuredValues(
_massConcentrationPm1p0, _massConcentrationPm2p5,
_massConcentrationPm4p0, _massConcentrationPm10p0, _ambientHumidity,
_ambientTemperature, _vocIndex, _noxIndex);
if (error != 0) {
return false;
}
_lastRead = millis();
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN5X's current temperature.
@ -79,20 +140,10 @@ public:
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_tempSensorPeriod != 0 && error != 0) || ambientTemperature == NAN) {
if (!ReadSensorData() || _ambientTemperature == NAN) {
return false;
}
tempEvent->temperature = ambientTemperature;
tempEvent->temperature = _ambientTemperature;
return true;
}
@ -106,20 +157,10 @@ public:
*/
/*******************************************************************************/
bool getEventRelativeHumidity(sensors_event_t *humidEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_humidSensorPeriod != 0 && error != 0) || ambientHumidity == NAN) {
if (!ReadSensorData() || _ambientHumidity == NAN) {
return false;
}
humidEvent->relative_humidity = ambientHumidity;
humidEvent->relative_humidity = _ambientHumidity;
return true;
}
@ -136,20 +177,10 @@ public:
*/
/*******************************************************************************/
bool getEventNOxIndex(sensors_event_t *noxIndexEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_NOxIndexPeriod != 0 && error != 0) || noxIndex == NAN) {
if (!ReadSensorData() || _noxIndex == NAN) {
return false;
}
noxIndexEvent->nox_index = noxIndex;
noxIndexEvent->nox_index = _noxIndex;
return true;
}
@ -163,20 +194,10 @@ public:
*/
/*******************************************************************************/
bool getEventVOCIndex(sensors_event_t *vocIndexEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_VOCIndexPeriod != 0 && error != 0) || vocIndex == NAN) {
if (!ReadSensorData() || _vocIndex == NAN) {
return false;
}
vocIndexEvent->voc_index = vocIndex;
vocIndexEvent->voc_index = _vocIndex;
return true;
}
@ -190,22 +211,11 @@ public:
*/
/*******************************************************************************/
bool getEventPM10_STD(sensors_event_t *pm10StdEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_PM10SensorPeriod != 0 && error != 0) ||
massConcentrationPm1p0 == NAN ||
massConcentrationPm1p0 == OVERFLOW_SEN55) {
if (!ReadSensorData() || _massConcentrationPm1p0 == NAN ||
_massConcentrationPm1p0 == OVERFLOW_SEN55) {
return false;
}
pm10StdEvent->pm10_std = massConcentrationPm1p0;
pm10StdEvent->pm10_std = _massConcentrationPm1p0;
return true;
}
@ -219,22 +229,11 @@ public:
*/
/*******************************************************************************/
bool getEventPM25_STD(sensors_event_t *pm25StdEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_PM25SensorPeriod != 0 && error != 0) ||
massConcentrationPm2p5 == NAN ||
massConcentrationPm2p5 == OVERFLOW_SEN55) {
if (!ReadSensorData() || _massConcentrationPm2p5 == NAN ||
_massConcentrationPm2p5 == OVERFLOW_SEN55) {
return false;
}
pm25StdEvent->pm25_std = massConcentrationPm2p5;
pm25StdEvent->pm25_std = _massConcentrationPm2p5;
return true;
}
@ -248,22 +247,11 @@ public:
*/
/*******************************************************************************/
bool getEventPM40_STD(sensors_event_t *pm40StdEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_PM25SensorPeriod != 0 && error != 0) ||
massConcentrationPm4p0 == NAN ||
massConcentrationPm4p0 == OVERFLOW_SEN55) {
if (!ReadSensorData() || _massConcentrationPm4p0 == NAN ||
_massConcentrationPm4p0 == OVERFLOW_SEN55) {
return false;
}
pm40StdEvent->data[0] = massConcentrationPm4p0;
pm40StdEvent->data[0] = _massConcentrationPm4p0;
return true;
}
@ -277,27 +265,25 @@ public:
*/
/*******************************************************************************/
bool getEventPM100_STD(sensors_event_t *pm100StdEvent) {
float massConcentrationPm1p0, massConcentrationPm2p5,
massConcentrationPm4p0, massConcentrationPm10p0, ambientHumidity,
ambientTemperature, vocIndex, noxIndex;
uint16_t error;
error = _sen->readMeasuredValues(
massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
noxIndex);
if ((_PM100SensorPeriod != 0 && error != 0) ||
massConcentrationPm10p0 == NAN ||
massConcentrationPm10p0 == OVERFLOW_SEN55) {
if (!ReadSensorData() || _massConcentrationPm10p0 == NAN ||
_massConcentrationPm10p0 == OVERFLOW_SEN55) {
return false;
}
pm100StdEvent->pm100_std = massConcentrationPm10p0;
pm100StdEvent->pm100_std = _massConcentrationPm10p0;
return true;
}
protected:
SensirionI2CSen5x *_sen; ///< SEN5X driver object
SensirionI2CSen5x *_sen = nullptr; ///< SEN5X driver object
float _massConcentrationPm1p0; ///< PM1.0 mass concentration
float _massConcentrationPm2p5; ///< PM2.5 mass concentration
float _massConcentrationPm4p0; ///< PM4.0 mass concentration
float _massConcentrationPm10p0; ///< PM10.0 mass concentration
float _ambientHumidity; ///< Ambient humidity
float _ambientTemperature; ///< Ambient temperature
float _vocIndex; ///< VOC index
float _noxIndex; ///< NOx index
ulong _lastRead = 0uL; ///< Last time the sensor was read
};
#endif // WipperSnapper_I2C_Driver_SEN5X

View file

@ -0,0 +1,311 @@
/*!
* @file WipperSnapper_I2C_Driver_SEN6X.h
*
* Device driver for the SEN66 Particulate Matter, Temperature, Humidity, VOC,
* NOX, and CO2 sensor.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2022 for Adafruit Industries.
* Modified (c) by Martin Ebner 2024 https://github.com/MartinEbnerSensirion
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_SEN6X_H
#define WipperSnapper_I2C_Driver_SEN6X_H
#include "WipperSnapper_I2C_Driver.h"
#include <SensirionI2cSen66.h>
#include <Wire.h>
/**************************************************************************/
/*!
@brief Class that provides a driver interface for the SEN6X sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_SEN6X : public WipperSnapper_I2C_Driver {
const float OVERFLOW_SEN6X = (0xFFFF / 10); // maxes out at u_int16 / 10
public:
/*******************************************************************************/
/*!
@brief Constructor for a SEN6X sensor.
@param i2c
The I2C interface.
@param sensorAddress
7-bit device address.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_SEN6X(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
_massConcentrationPm1p0 = NAN;
_massConcentrationPm2p5 = NAN;
_massConcentrationPm4p0 = NAN;
_massConcentrationPm10p0 = NAN;
_ambientHumidity = NAN;
_ambientTemperature = NAN;
_vocIndex = NAN;
_noxIndex = NAN;
_co2 = 0uL;
}
/*******************************************************************************/
/*!
@brief Initializes the SEN6X sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
_sen = new SensirionI2cSen66();
_sen->begin(*_i2c, (uint8_t)_sensorAddress);
u_int16_t error_stop = _sen->deviceReset();
if (error_stop != 0) {
return false;
}
// Wait 1 second for sensors to start recording + 100ms for reset command
delay(1100);
u_int16_t error_start = _sen->startContinuousMeasurement();
if (error_start != 0) {
return false;
}
return true;
}
/*******************************************************************************/
/*!
@brief Checks if sensor was read within last 1s, or is the first read.
@returns True if the sensor was recently read, False otherwise.
*/
bool HasBeenReadInLastSecond() {
return _lastRead != 0 && millis() - _lastRead < 1000;
}
/*******************************************************************************/
/*!
@brief Checks if the sensor is ready to be read
@returns True if the sensor is ready, False otherwise.
*/
/*******************************************************************************/
bool IsSensorReady() {
bool isDataReady = false;
uint8_t padding = 0x0;
for (int i = 0; i < 2; i++) {
uint16_t error = _sen->getDataReady(padding, isDataReady);
if (error == 0 && isDataReady) {
return true;
}
delay(100);
}
return false;
}
/*******************************************************************************/
/*!
@brief Reads the sensor.
@returns True if the sensor was read successfully, False otherwise.
*/
/*******************************************************************************/
bool ReadSensorData() {
// dont read sensor more than once per second
if (HasBeenReadInLastSecond()) {
return true;
}
if (!IsSensorReady()) {
return false;
}
uint16_t error = _sen->readMeasuredValues(
_massConcentrationPm1p0, _massConcentrationPm2p5,
_massConcentrationPm4p0, _massConcentrationPm10p0, _ambientHumidity,
_ambientTemperature, _vocIndex, _noxIndex, _co2);
if (error != 0) {
return false;
}
_lastRead = millis();
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X's current temperature.
@param tempEvent
Pointer to an Adafruit_Sensor event.
@returns True if the temperature was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventAmbientTemp(sensors_event_t *tempEvent) {
if (!ReadSensorData() || _ambientTemperature == NAN) {
return false;
}
tempEvent->temperature = _ambientTemperature;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X's current relative humidity reading.
@param humidEvent
Pointer to an Adafruit_Sensor event.
@returns True if the humidity was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventRelativeHumidity(sensors_event_t *humidEvent) {
if (!ReadSensorData() || _ambientHumidity == NAN) {
return false;
}
humidEvent->relative_humidity = _ambientHumidity;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X's current NOX reading.
Note: If this value is unknown, which is true for SEN54,
NAN is returned. During the first 10..11 seconds after
power-on or device reset, this value will be NAN as well.
@param noxIndexEvent
Adafruit Sensor event for NOx Index (0-500, 1 is normal)
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventNOxIndex(sensors_event_t *noxIndexEvent) {
if (!ReadSensorData() || _noxIndex == NAN) {
return false;
}
noxIndexEvent->nox_index = _noxIndex;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X's current VOC reading.
@param vocIndexEvent
Adafruit Sensor event for VOC Index (1-500, 100 is normal)
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventVOCIndex(sensors_event_t *vocIndexEvent) {
if (!ReadSensorData() || _vocIndex == NAN) {
return false;
}
vocIndexEvent->voc_index = _vocIndex;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X sensor's PM1.0 STD reading.
@param pm10StdEvent
Adafruit Sensor event for PM1.0
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventPM10_STD(sensors_event_t *pm10StdEvent) {
if (!ReadSensorData() || _massConcentrationPm1p0 == NAN ||
_massConcentrationPm1p0 == OVERFLOW_SEN6X) {
return false;
}
pm10StdEvent->pm10_std = _massConcentrationPm1p0;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X sensor's PM2.5 STD reading.
@param pm25StdEvent
Adafruit Sensor event for PM2.5
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventPM25_STD(sensors_event_t *pm25StdEvent) {
if (!ReadSensorData() || _massConcentrationPm2p5 == NAN ||
_massConcentrationPm2p5 == OVERFLOW_SEN6X) {
return false;
}
pm25StdEvent->pm25_std = _massConcentrationPm2p5;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X sensor's PM4.0 STD reading.
@param pm40StdEvent
Adafruit Sensor event for PM4.0
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventPM40_STD(sensors_event_t *pm40StdEvent) {
if (!ReadSensorData() || _massConcentrationPm4p0 == NAN ||
_massConcentrationPm4p0 == OVERFLOW_SEN6X) {
return false;
}
pm40StdEvent->data[0] = _massConcentrationPm4p0;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X sensor's PM10.0 STD reading.
@param pm100StdEvent
Adafruit Sensor event for PM10.0
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventPM100_STD(sensors_event_t *pm100StdEvent) {
if (!ReadSensorData() || _massConcentrationPm10p0 == NAN ||
_massConcentrationPm10p0 == OVERFLOW_SEN6X) {
return false;
}
pm100StdEvent->pm100_std = _massConcentrationPm10p0;
return true;
}
/*******************************************************************************/
/*!
@brief Gets the SEN6X sensor's CO2 reading.
@param co2Event
Adafruit Sensor event for CO2
@returns True if the sensor value was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventCO2(sensors_event_t *co2Event) {
if (!ReadSensorData() || _co2 == 0xFFFF) {
return false;
}
co2Event->CO2 = _co2;
return true;
}
protected:
SensirionI2cSen66 *_sen = nullptr; ///< SEN6X driver object
float _massConcentrationPm1p0; ///< PM1.0 mass concentration
float _massConcentrationPm2p5; ///< PM2.5 mass concentration
float _massConcentrationPm4p0; ///< PM4.0 mass concentration
float _massConcentrationPm10p0; ///< PM10.0 mass concentration
float _ambientHumidity; ///< Ambient humidity
float _ambientTemperature; ///< Ambient temperature
float _vocIndex; ///< VOC index
float _noxIndex; ///< NOx index
uint16_t _co2; ///< CO2 value
ulong _lastRead; ///< Last time the sensor was read
};
#endif // WipperSnapper_I2C_Driver_SEN6X

View file

@ -44,11 +44,7 @@ public:
/*******************************************************************************/
bool begin() {
_sgp30 = new Adafruit_SGP30();
bool isInit = _sgp30->begin(_i2c);
if (isInit) {
_sgp30->IAQinit();
}
return isInit;
return _sgp30->begin(_i2c);
}
bool getEventECO2(sensors_event_t *senseEvent) {

View file

@ -0,0 +1,107 @@
/*!
* @file WipperSnapper_I2C_Driver_VCNL4200.h
*
* Device driver for the VCNL4200 light + proximity sensor.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Tyeth Gundry 2024 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WipperSnapper_I2C_Driver_VCNL4200_H
#define WipperSnapper_I2C_Driver_VCNL4200_H
#include "WipperSnapper_I2C_Driver.h"
#include <Adafruit_VCNL4200.h>
/**************************************************************************/
/*!
@brief Class that provides a driver interface for a VCNL4200 sensor.
*/
/**************************************************************************/
class WipperSnapper_I2C_Driver_VCNL4200 : public WipperSnapper_I2C_Driver {
public:
/*******************************************************************************/
/*!
@brief Constructor for a VCNL4200 sensor.
@param i2c
The I2C interface.
@param sensorAddress
The 7-bit I2C address of the sensor.
*/
/*******************************************************************************/
WipperSnapper_I2C_Driver_VCNL4200(TwoWire *i2c, uint16_t sensorAddress)
: WipperSnapper_I2C_Driver(i2c, sensorAddress) {
_i2c = i2c;
_sensorAddress = sensorAddress;
}
/*******************************************************************************/
/*!
@brief Destructor for an VCNL4200 sensor.
*/
/*******************************************************************************/
~WipperSnapper_I2C_Driver_VCNL4200() { delete _vcnl4200; }
/*******************************************************************************/
/*!
@brief Initializes the VCNL4200 sensor and begins I2C.
@returns True if initialized successfully, False otherwise.
*/
/*******************************************************************************/
bool begin() {
_vcnl4200 = new Adafruit_VCNL4200();
bool status = false;
// Attempt to initialize and configure VCNL4200
if (!_vcnl4200->begin(_sensorAddress, _i2c)) {
return false;
}
status = _vcnl4200->setALSshutdown(false);
status &= _vcnl4200->setProxShutdown(false);
status &= _vcnl4200->setProxHD(true); // 16bit instead of 12bit
status &= _vcnl4200->setALSIntegrationTime(VCNL4200_ALS_IT_400MS);
status &= _vcnl4200->setProxDuty(VCNL4200_PS_DUTY_1_160);
status &= _vcnl4200->setProxLEDCurrent(VCNL4200_LED_I_200MA);
status &= _vcnl4200->setProxIntegrationTime(VCNL4200_PS_IT_9T);
return status;
}
/*******************************************************************************/
/*!
@brief Performs a light sensor read using the Adafruit
Unified Sensor API.
@param lightEvent
Light sensor reading, in lux.
@returns True if the sensor event was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventLight(sensors_event_t *lightEvent) {
// Get sensor event populated in lux via AUTO integration and gain
lightEvent->light = _vcnl4200->readALSdata();
return true;
}
/*******************************************************************************/
/*!
@brief Reads the VCNL4200's proximity value into an event (no unit).
@param proximityEvent
Pointer to an Adafruit_Sensor event.
@returns True if the proximity was obtained successfully, False
otherwise.
*/
/*******************************************************************************/
bool getEventProximity(sensors_event_t *proximityEvent) {
proximityEvent->data[0] = (float)_vcnl4200->readProxData();
return true;
}
protected:
Adafruit_VCNL4200 *_vcnl4200; ///< Pointer to VCNL4200 light sensor object
};
#endif // WipperSnapper_I2C_Driver_VCNL4200

View file

@ -112,7 +112,7 @@ public:
/*******************************************************************************/
bool getEventProximity(sensors_event_t *proximityEvent) {
uint8_t NewDataReady = 0;
VL53L4CD_Result_t results;
VL53L4CD_Result_t results = {0};
uint8_t status;
// Start fresh reading, seemed to be accepting stale value
_VL53L4CD->VL53L4CD_ClearInterrupt();

View file

@ -129,7 +129,7 @@ public:
*/
/*******************************************************************************/
bool getProximity(sensors_event_t *proximityEvent, int whichObject = 0) {
VL53L4CX_MultiRangingData_t MultiRangingData;
VL53L4CX_MultiRangingData_t MultiRangingData = {0};
VL53L4CX_MultiRangingData_t *pMultiRangingData = &MultiRangingData;
uint8_t NewDataReady = 0;
int status;

View file

@ -54,7 +54,8 @@ bool ws_ledc::analogWrite(uint8_t pin, int value) {
// Calculate duty cycle for the `value` passed in
// (assumes 12-bit resolution, 2^12)
uint32_t dutyCycle = (4095 / 255) * min(value, 255);
uint32_t dutyCycle =
(uint32_t)(((double)4095 / 255.0) * min((uint32_t)value, (uint32_t)255));
// Call duty cycle write
return setDuty(pin, dutyCycle);

View file

@ -64,12 +64,19 @@ int16_t ws_pixels::allocateStrand() {
*/
/**************************************************************************/
void ws_pixels::deallocateStrand(int16_t strandIdx) {
// delete the pixel object
if (strands[strandIdx].neoPixelPtr != nullptr)
if (strands[strandIdx].neoPixelPtr != nullptr) {
// Fill with "off"
strands[strandIdx].neoPixelPtr->clear();
strands[strandIdx].neoPixelPtr->show();
// Delete the NeoPixel object
delete strands[strandIdx].neoPixelPtr;
if ((strands[strandIdx].dotStarPtr != nullptr))
} else if ((strands[strandIdx].dotStarPtr != nullptr)) {
// Fill with "off"
strands[strandIdx].dotStarPtr->clear();
strands[strandIdx].dotStarPtr->show();
delete strands[strandIdx].dotStarPtr;
}
// re-initialize status pixel (if pixel was prvsly used)
if (strands[strandIdx].pinNeoPixel == getStatusNeoPixelPin() ||
@ -243,6 +250,7 @@ bool ws_pixels::addStrand(
releaseStatusLED(); // release it!
// Create a new strand of NeoPixels
WS_DEBUG_PRINTLN("Setting up new NeoPixel Strand...");
strands[strandIdx].neoPixelPtr = new Adafruit_NeoPixel(
pixelsCreateReqMsg->pixels_num, strands[strandIdx].pinNeoPixel,
getNeoPixelStrandOrder(pixelsCreateReqMsg->pixels_ordering));

View file

@ -55,7 +55,7 @@ bool Wippersnapper::encodePubRegistrationReq() {
if (!_status)
return _status;
// pubish message
// publish message
WS.publish(WS._topic_description, _message_buffer, _message_len, 1);
WS_DEBUG_PRINTLN("Published!");
WS._boardStatus = WS_BOARD_DEF_SENT;

View file

@ -72,7 +72,7 @@ bool ws_servo::servo_attach(int pin, int minPulseWidth, int maxPulseWidth,
#ifdef ARDUINO_ARCH_ESP32
rc = servo->attach(pin, minPulseWidth, maxPulseWidth, freq);
#else
(void)freq; // supress warning when we don't use the frequency parameter
(void)freq; // suppress warning when we don't use the frequency parameter
rc = servo->attach(pin, minPulseWidth, maxPulseWidth);
#endif
if (rc == ERR_SERVO_ATTACH)

View file

@ -51,6 +51,7 @@ void initStatusLED() {
statusPixel = new Adafruit_NeoPixel(
STATUS_NEOPIXEL_NUM, STATUS_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
statusPixel->begin();
statusPixel->clear();
statusPixel->show(); // turn OFF all pixels
WS.lockStatusNeoPixel = true;
}
@ -69,6 +70,7 @@ void initStatusLED() {
STATUS_DOTSTAR_PIN_CLK, STATUS_DOTSTAR_COLOR_ORDER)
#endif
statusPixelDotStar->begin();
statusPixelDotStar->clear();
statusPixelDotStar->show(); // turn OFF all pixels
WS.lockStatusDotStar = true;
}
@ -83,7 +85,7 @@ void initStatusLED() {
#elif defined(ARDUINO_ARCH_ESP32)
WS._pwmComponent->attach(STATUS_LED_PIN, LEDC_BASE_FREQ, LEDC_TIMER_12_BIT);
WS._pwmComponent->writeDutyCycle(STATUS_LED_PIN, 0); // turn OFF
#elif defined(ARDUINO_RASPBERRY_PI_PICO_W)
#elif defined(ARDUINO_ARCH_RP2040)
digitalWrite(STATUS_LED_PIN, 0);
#else
analogWrite(STATUS_LED_PIN, 0);
@ -99,10 +101,12 @@ void initStatusLED() {
*/
/****************************************************************************/
void releaseStatusLED() {
WS_DEBUG_PRINTLN("Releasing status LED");
#ifdef USE_STATUS_NEOPIXEL
delete statusPixel; // Deallocate Adafruit_NeoPixel object, set data pin back
// to INPUT.
WS.lockStatusNeoPixel = false; // unlock
// Deallocate Adafruit_NeoPixel object, set data pin back to INPUT,
// and unlock pixel for use by pixels component
delete statusPixel;
WS.lockStatusNeoPixel = false;
#endif
#ifdef USE_STATUS_DOTSTAR
@ -177,7 +181,7 @@ void setStatusLEDColor(uint32_t color) {
#ifdef USE_STATUS_LED
if (!WS.lockStatusLED)
return; // status pixel is in-use elsewhere
#ifdef ARDUINO_RASPBERRY_PI_PICO_W
#ifdef ARDUINO_ARCH_RP2040
digitalWrite(STATUS_LED_PIN, color > 0);
#else
if (color != BLACK)
@ -236,7 +240,7 @@ void setStatusLEDColor(uint32_t color, int brightness) {
if (!WS.lockStatusLED)
return;
#ifdef ARDUINO_RASPBERRY_PI_PICO_W
#ifdef ARDUINO_ARCH_RP2040
digitalWrite(STATUS_LED_PIN, color > 0);
#else
if (color != BLACK) {

View file

@ -160,7 +160,7 @@ public:
@brief Reads the UART device's data then packs and sends it to IO.
*/
/*******************************************************************************/
virtual void send_data(){};
virtual void send_data() {};
const char *uartTopic = nullptr; ///< UART device's MQTT topic
Adafruit_MQTT *mqttClient = nullptr; ///< Pointer to MQTT client object

View file

@ -81,14 +81,17 @@ public:
/*******************************************************************************/
bool begin() override {
_aqi = new Adafruit_PM25AQI();
bool is_pm1006 = (strcmp(getDriverID(), "pm1006") == 0);
#ifdef USE_SW_UART
if (!_aqi->begin_UART(
_swSerial)) { // connect to the sensor over software serial
_swSerial, // connect to the sensor over software serial
is_pm1006)) {
return false;
}
#else
if (!_aqi->begin_UART(
_hwSerial)) { // connect to the sensor over hardware serial
_hwSerial, // connect to the sensor over hardware serial
is_pm1006)) {
return false;
}
#endif

View file

@ -11,7 +11,7 @@
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2020-2021 for Adafruit Industries.
* Copyright (c) Brent Rubell 2020-2025 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
@ -32,7 +32,9 @@
#define AIRLIFT_CONNECT_TIMEOUT_MS 20000 /*!< Connection timeout (in ms) */
#define AIRLIFT_CONNECT_RETRY_DELAY_MS 200 /*!< delay time between retries. */
#ifndef SPIWIFI
#define SPIWIFI SPI /*!< Instance of SPI interface used by an AirLift. */
#endif
extern Wippersnapper WS;
/****************************************************************************/
@ -49,9 +51,13 @@ public:
*/
/**************************************************************************/
Wippersnapper_AIRLIFT() : Wippersnapper() {
_ssPin = SPIWIFI_SS; // 10;
_ackPin = SPIWIFI_ACK; // 7;
_rstPin = SPIWIFI_RESET; // 5; // should be 7 on PyPortals
_ssPin = SPIWIFI_SS;
_ackPin = SPIWIFI_ACK;
#ifdef ESP32_RESETN
_rstPin = ESP32_RESETN; // FruitJam
#else
_rstPin = SPIWIFI_RESET;
#endif // ESP32_RESETN
#ifdef ESP32_GPIO0
_gpio0Pin = ESP32_GPIO0;
#else
@ -103,8 +109,8 @@ public:
/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
*/
/***********************************************************/
bool check_valid_ssid() {
@ -119,26 +125,33 @@ public:
return false;
}
// Was the network within secrets.json found?
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
WS_DEBUG_PRINT("SSID found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
bool foundNetwork = false;
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:");
for (uint8_t i = 0; i < n; i++) {
if (!foundNetwork && strcmp(WiFi.SSID(i), _ssid) == 0) {
foundNetwork = true;
}
}
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(" (");
uint8_t BSSID[WL_MAC_ADDR_LENGTH];
WiFi.BSSID(i, BSSID);
for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) {
if (m != 0)
WS_DEBUG_PRINT(":");
WS_DEBUG_PRINTHEX(BSSID[m]);
}
WS_DEBUG_PRINT(") ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINTLN("dB");
WS_DEBUG_PRINT("dB (ch");
WS_DEBUG_PRINT(WiFi.channel(i))
WS_DEBUG_PRINTLN(")");
}
return false;
if (!foundNetwork) {
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
}
return foundNetwork;
}
/********************************************************/
@ -229,7 +242,7 @@ public:
*/
/********************************************************/
void getMacAddr() {
uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte mac[6] = {0};
WiFi.macAddress(mac);
memcpy(WS._macAddr, mac, sizeof(mac));
}
@ -323,6 +336,7 @@ protected:
// validate co-processor's firmware version
if (!firmwareCheck()) {
// TODO: see if there's a way to add to bootlog without usb reattach
WS_DEBUG_PRINTLN("Please upgrade the firmware on the ESP module to the "
"latest version.");
}

View file

@ -103,6 +103,17 @@ public:
WiFi.disconnect();
delay(100);
// For boards with a "3D Antenna", we need to reduce the TX power
// to prevent flaky operation.
// NOTE: This is a known issue with the QT Py series of boards.
#if defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32C3) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32_PICO)
WiFi.setTxPower(WIFI_POWER_15dBm);
#endif
// Perform a network scan
int n = WiFi.scanNetworks();
if (n == 0) {
@ -110,40 +121,40 @@ public:
return false;
}
// Was the network within secrets.json found?
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
}
if (WS._isWiFiMulti) {
bool foundNetwork = false;
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:");
for (uint8_t i = 0; i < n; i++) {
if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) {
foundNetwork = true;
} else if (!foundNetwork && WS._isWiFiMulti) {
// multi network mode
for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(WS._multiNetworks[j].ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
foundNetwork = true;
}
}
}
}
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(" (");
uint8_t BSSID[WL_MAC_ADDR_LENGTH];
WiFi.BSSID(i, BSSID);
for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) {
if (m != 0)
WS_DEBUG_PRINT(":");
WS_DEBUG_PRINTHEX(BSSID[m]);
}
WS_DEBUG_PRINT(") ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINTLN("dB");
WS_DEBUG_PRINT("dB (ch");
WS_DEBUG_PRINT(WiFi.channel(i))
WS_DEBUG_PRINTLN(")");
}
return false;
if (!foundNetwork) {
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
}
return foundNetwork;
}
/********************************************************/
@ -232,30 +243,35 @@ protected:
const char *_aio_root_ca_staging =
"-----BEGIN CERTIFICATE-----\n"
"MIIEVzCCAj+gAwIBAgIRALBXPpFzlydw27SHyzpFKzgwDQYJKoZIhvcNAQELBQAw\n"
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n"
"TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjQwMzEzMDAwMDAw\n"
"WhcNMjcwMzEyMjM1OTU5WjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\n"
"RW5jcnlwdDELMAkGA1UEAxMCRTYwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATZ8Z5G\n"
"h/ghcWCoJuuj+rnq2h25EqfUJtlRFLFhfHWWvyILOR/VvtEKRqotPEoJhC6+QJVV\n"
"6RlAN2Z17TJOdwRJ+HB7wxjnzvdxEP6sdNgA1O1tHHMWMxCcOrLqbGL0vbijgfgw\n"
"gfUwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD\n"
"ATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBSTJ0aYA6lRaI6Y1sRCSNsj\n"
"v1iU0jAfBgNVHSMEGDAWgBR5tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcB\n"
"AQQmMCQwIgYIKwYBBQUHMAKGFmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0g\n"
"BAwwCjAIBgZngQwBAgEwJwYDVR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVu\n"
"Y3Iub3JnLzANBgkqhkiG9w0BAQsFAAOCAgEAfYt7SiA1sgWGCIpunk46r4AExIRc\n"
"MxkKgUhNlrrv1B21hOaXN/5miE+LOTbrcmU/M9yvC6MVY730GNFoL8IhJ8j8vrOL\n"
"pMY22OP6baS1k9YMrtDTlwJHoGby04ThTUeBDksS9RiuHvicZqBedQdIF65pZuhp\n"
"eDcGBcLiYasQr/EO5gxxtLyTmgsHSOVSBcFOn9lgv7LECPq9i7mfH3mpxgrRKSxH\n"
"pOoZ0KXMcB+hHuvlklHntvcI0mMMQ0mhYj6qtMFStkF1RpCG3IPdIwpVCQqu8GV7\n"
"s8ubknRzs+3C/Bm19RFOoiPpDkwvyNfvmQ14XkyqqKK5oZ8zhD32kFRQkxa8uZSu\n"
"h4aTImFxknu39waBxIRXE4jKxlAmQc4QjFZoq1KmQqQg0J/1JF8RlFvJas1VcjLv\n"
"YlvUB2t6npO6oQjB3l+PNf0DpQH7iUx3Wz5AjQCi6L25FjyE06q6BZ/QlmtYdl/8\n"
"ZYao4SRqPEs/6cAiF+Qf5zg2UkaWtDphl1LKMuTNLotvsX99HP69V2faNyegodQ0\n"
"LyTApr/vT01YPE46vNsDLgK+4cL6TrzC/a4WcmF5SRJ938zrv/duJHLXQIku5v0+\n"
"EwOy59Hdm0PT/Er/84dDV0CSjdR/2XuZM3kpysSKLgD1cKiDA+IRguODCxfO9cyY\n"
"Ig46v9mFmBvyH04=\n"
"cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n"
"WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n"
"ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n"
"MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n"
"h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n"
"0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U\n"
"A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW\n"
"T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH\n"
"B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC\n"
"B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv\n"
"KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn\n"
"OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn\n"
"jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw\n"
"qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI\n"
"rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV\n"
"HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq\n"
"hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL\n"
"ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ\n"
"3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK\n"
"NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5\n"
"ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur\n"
"TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC\n"
"jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc\n"
"oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq\n"
"4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA\n"
"mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d\n"
"emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=\n"
"-----END CERTIFICATE-----\n"; ///< Root certificate for io.adafruit.us
const char *_aio_root_ca_prod =

View file

@ -29,13 +29,15 @@
* important - please switch to using the modern ESP32 (and related models)
* instead of the ESP8266 to avoid updating the SSL fingerprint every year.
*
* The commented-out fingerprint below was last updated on 07/14/2025.
*
* If you've read through this and still want to use "Secure MQTT" with your
* ESP8266 project, we've left the "WiFiClientSecure" lines commented out. To
* use them, uncomment the commented out lines within this file and re-compile
* the library.
*/
// static const char *fingerprint PROGMEM = "4E C1 52 73 24 A8 36 D6 7A 4C 67
// C7 91 0C 0A 22 B9 2D 5B CA";
// static const char *fingerprint PROGMEM = "47 D2 CB 14 DF 38 97 59 C6 65 1A
// 1F 3E 00 1E 53 CC A5 17 E0";
extern Wippersnapper WS;
@ -133,40 +135,40 @@ public:
return false;
}
// Was the network within secrets.json found?
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i).c_str()) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(_ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
}
if (WS._isWiFiMulti) {
bool foundNetwork = false;
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks:");
for (uint8_t i = 0; i < n; i++) {
if (!foundNetwork && strcmp(WiFi.SSID(i).c_str(), _ssid) == 0) {
foundNetwork = true;
} else if (!foundNetwork && WS._isWiFiMulti) {
// multi network mode
for (int j = 0; j < WS_MAX_ALT_WIFI_NETWORKS; j++) {
if (strcmp(WS._multiNetworks[j].ssid, WiFi.SSID(i).c_str()) == 0) {
WS_DEBUG_PRINT("SSID (");
WS_DEBUG_PRINT(WS._multiNetworks[j].ssid);
WS_DEBUG_PRINT(") found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
foundNetwork = true;
}
}
}
}
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(" (");
uint8_t BSSID[WL_MAC_ADDR_LENGTH];
memcpy(BSSID, WiFi.BSSID(i), WL_MAC_ADDR_LENGTH);
for (int m = 0; m < WL_MAC_ADDR_LENGTH; m++) {
if (m != 0)
WS_DEBUG_PRINT(":");
WS_DEBUG_PRINTHEX(BSSID[m]);
}
WS_DEBUG_PRINT(") ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINTLN("dB");
WS_DEBUG_PRINT("dB (ch");
WS_DEBUG_PRINT(WiFi.channel(i))
WS_DEBUG_PRINTLN(")");
}
return false;
if (!foundNetwork) {
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
}
return foundNetwork;
}
/********************************************************/
@ -260,7 +262,6 @@ protected:
delay(100);
// ESP8266 MUST be in STA mode to avoid device acting as client/server
WiFi.mode(WIFI_STA);
WiFi.begin(_ssid, _pass);
_status = WS_NET_DISCONNECTED;
delay(100);
@ -274,38 +275,28 @@ protected:
WS._multiNetworks[i].pass);
}
}
// add default network
if (_wifiMulti.existsAP(_ssid) == false) {
_wifiMulti.addAP(_ssid, _pass);
}
long startRetry = millis();
WS_DEBUG_PRINTLN("CONNECTING");
while (_wifiMulti.run(5000) != WL_CONNECTED &&
millis() - startRetry < 10000) {
// ESP8266 WDT requires yield() during a busy-loop so it doesn't bite
yield();
}
if (WiFi.status() == WL_CONNECTED) {
_status = WS_NET_CONNECTED;
} else {
_status = WS_NET_DISCONNECTED;
}
} else {
// single network mode
// wait for a connection to be established
long startRetry = millis();
WS_DEBUG_PRINTLN("CONNECTING");
while (WiFi.status() != WL_CONNECTED && millis() - startRetry < 10000) {
// ESP8266 WDT requires yield() during a busy-loop so it doesn't bite
yield();
}
if (WiFi.status() == WL_CONNECTED) {
_status = WS_NET_CONNECTED;
} else {
_status = WS_NET_DISCONNECTED;
}
}
// add default network
if (_wifiMulti.existsAP(_ssid) == false) {
_wifiMulti.addAP(_ssid, _pass);
}
long startRetry = millis();
WS_DEBUG_PRINTLN("CONNECTING");
while (_wifiMulti.run(5000) != WL_CONNECTED &&
millis() - startRetry < 10000) {
// ESP8266 WDT requires yield() during a busy-loop so it doesn't bite
yield();
}
if (WiFi.status() == WL_CONNECTED) {
_status = WS_NET_CONNECTED;
} else {
_status = WS_NET_DISCONNECTED;
}
WS.feedWDT();
}
}

View file

@ -1,286 +0,0 @@
/*!
* @file Wippersnapper_WIFININA.h
*
* Network interface for the ublox wifi module on the
* Arduino MKR WiFi 1010, Arduino Nano 33 IoT and Arduino UNO WiFi Rev.2.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Copyright (c) Brent Rubell 2021 for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*
*/
#ifndef WIPPERSNAPPER_WIFININA_H
#define WIPPERSNAPPER_WIFININA_H
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>
#include <Arduino.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include "Wippersnapper.h"
#define SPIWIFI \
SPI /*!< Instance of SPI interface used by an external uBlox module. */
extern Wippersnapper WS;
/****************************************************************************/
/*!
@brief Class for using the AirLift Co-Processor network iface.
*/
/****************************************************************************/
class Wippersnapper_WIFININA : public Wippersnapper {
public:
/**************************************************************************/
/*!
@brief Initializes the Adafruit IO class for ublox devices.
@param aioUsername
Adafruit IO username
@param aioKey
Adafruit IO key
@param netSSID
Wireless Network SSID
@param netPass
Wireless Network password
*/
/**************************************************************************/
Wippersnapper_WIFININA(const char *aioUsername, const char *aioKey,
const char *netSSID, const char *netPass)
: Wippersnapper() {
_ssid = netSSID;
_pass = netPass;
_username = aioUsername;
_key = aioKey;
_wifi = &SPIWIFI;
_mqtt_client = new WiFiSSLClient;
}
/**************************************************************************/
/*!
@brief Destructor for the Adafruit IO ublox class.
*/
/**************************************************************************/
~Wippersnapper_WIFININA() {
if (_mqtt)
delete _mqtt;
}
/****************************************************************************/
/*!
@brief Configures the device's Adafruit IO credentials. This method
should be used only if filesystem-backed provisioning is
not avaliable.
*/
/****************************************************************************/
void set_user_key() {
strlcpy(WS._config.aio_user, _username, sizeof(WS._config.aio_user));
strlcpy(WS._config.aio_key, _key, sizeof(WS._config.aio_key));
}
/**********************************************************/
/*!
@brief Sets the WiFi client's ssid and password.
@param ssid
Wireless network's SSID.
@param ssidPassword
Wireless network's password.
*/
/**********************************************************/
void set_ssid_pass(const char *ssid, const char *ssidPassword) {
strlcpy(WS._config.network.ssid, ssid, sizeof(WS._config.network.ssid));
strlcpy(WS._config.network.pass, ssidPassword,
sizeof(WS._config.network.pass));
}
/**********************************************************/
/*!
@brief Sets the WiFi client's ssid and password from the
header file's credentials.
*/
/**********************************************************/
void set_ssid_pass() {
strlcpy(WS._config.network.ssid, _ssid, sizeof(WS._config.network.ssid));
strlcpy(WS._config.network.pass, _pass, sizeof(WS._config.network.pass));
}
/***********************************************************/
/*!
@brief Performs a scan of local WiFi networks.
@returns True if `_network_ssid` is found, False otherwise.
*/
/***********************************************************/
bool check_valid_ssid() {
// Set WiFi to station mode and disconnect from an AP if it was previously
// connected
WiFi.disconnect();
delay(100);
// Perform a network scan
int n = WiFi.scanNetworks();
if (n == 0) {
WS_DEBUG_PRINTLN("ERROR: No WiFi networks found!");
return false;
}
// Was the network within secrets.json found?
for (int i = 0; i < n; ++i) {
if (strcmp(_ssid, WiFi.SSID(i)) == 0) {
WS_DEBUG_PRINT("SSID found! RSSI: ");
WS_DEBUG_PRINTLN(WiFi.RSSI(i));
return true;
}
}
// User-set network not found, print scan results to serial console
WS_DEBUG_PRINTLN("ERROR: Your requested WiFi network was not found!");
WS_DEBUG_PRINTLN("WipperSnapper found these WiFi networks: ");
for (int i = 0; i < n; ++i) {
WS_DEBUG_PRINT(WiFi.SSID(i));
WS_DEBUG_PRINT(" ");
WS_DEBUG_PRINT(WiFi.RSSI(i));
WS_DEBUG_PRINTLN("dB");
}
return false;
}
/********************************************************/
/*!
@brief Sets the WiFi client.
@param wifi
Instance of SPIClass.
*/
/********************************************************/
void set_wifi(SPIClass *wifi) {
_wifi = wifi;
_mqtt_client = new WiFiSSLClient;
}
/***********************************************************/
/*!
@brief Checks the nina-fw version on the module.
@return True if firmware on the ublox module matches
the latest version of the library, False otherwise.
*/
/***********************************************************/
bool firmwareCheck() {
String fv = WiFi.firmwareVersion();
if (fv < WIFI_FIRMWARE_LATEST_VERSION)
return false;
return true;
}
/********************************************************/
/*!
@brief Gets the ESP32's unique client identifier.
@note For the ESP32, the UID is the MAC address.
*/
/********************************************************/
void getMacAddr() {
uint8_t mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
WiFi.macAddress(mac);
memcpy(WS._macAddr, mac, sizeof(mac));
}
/********************************************************/
/*!
@brief Gets the current network RSSI value
@return int32_t RSSI value
*/
/********************************************************/
int32_t getRSSI() { return WiFi.RSSI(); }
/********************************************************/
/*!
@brief Initializes the MQTT client.
@param clientID
MQTT client identifier
*/
/********************************************************/
void setupMQTTClient(const char *clientID) {
WS._mqtt = new Adafruit_MQTT_Client(
_mqtt_client, WS._config.aio_url, WS._config.io_port, clientID,
WS._config.aio_user, WS._config.aio_key);
}
/********************************************************/
/*!
@brief Returns the network status of an ESP32 module.
@return ws_status_t
*/
/********************************************************/
ws_status_t networkStatus() {
switch (WiFi.status()) {
case WL_CONNECTED:
return WS_NET_CONNECTED;
case WL_CONNECT_FAILED:
return WS_NET_CONNECT_FAILED;
case WL_IDLE_STATUS:
return WS_IDLE;
default:
return WS_NET_DISCONNECTED;
}
}
/*******************************************************************/
/*!
@brief Returns the type of network connection used by Wippersnapper
@return AIRLIFT
*/
/*******************************************************************/
const char *connectionType() { return "AIRLIFT"; }
protected:
const char *_ssid; /*!< Network SSID. */
const char *_pass; /*!< Network password. */
const char *_username; /*!< Adafruit IO username. */
const char *_key; /*!< Adafruit IO key. */
WiFiSSLClient *_mqtt_client; /*!< Instance of a secure WiFi client. */
SPIClass *_wifi; /*!< Instance of the SPI bus used by the ublox. */
/**************************************************************************/
/*!
@brief Establishes a connection with the wireless network.
*/
/**************************************************************************/
void _connect() {
// check if co-processor connected first
if (WiFi.status() == WL_NO_MODULE)
errorWriteHang("No WiFi Module Detected!");
// validate the nina-fw version
if (!firmwareCheck())
errorWriteHang("Please upgrade the firmware on the ESP module to the "
"latest version.");
if (strlen(_ssid) == 0) {
_status = WS_SSID_INVALID;
} else {
// disconnect from possible previous connection
_disconnect();
WiFi.begin(_ssid, _pass);
_status = WS_NET_DISCONNECTED;
}
}
/**************************************************************************/
/*!
@brief Disconnects from the wireless network.
*/
/**************************************************************************/
void _disconnect() {
WiFi.disconnect();
delay(500);
}
};
#endif // WIPPERSNAPPER_WIFININA_H

Some files were not shown because too many files have changed in this diff Show more