Skip to content

Commit 351c156

Browse files
committed
GPS - I2c Refactor, put back missing autodetect from merge, crash on GPSEvent erroneous publish
1 parent 8800c78 commit 351c156

File tree

16 files changed

+249
-163
lines changed

16 files changed

+249
-163
lines changed

examples/Wippersnapper_demo_offline_netiface/Wippersnapper_demo_offline_netiface.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Adafruit IO WipperSnapper
2-
// USE ONLY WITH DEVICES WITHOUT A NETWORK ADAPTER LIKE RP2040 PICO
1+
// Adafruit IO WipperSnapper - Offline Mode with Network Interface
2+
// USE ONLY WITH DEVICES WITH A NETWORK ADAPTER LIKE ESP32-x
33
//
44
// Adafruit invests time and resources providing this open source code.
55
// Please support Adafruit and open source hardware by purchasing

examples/Wippersnapper_demo_offline_nonetiface/Wippersnapper_demo_offline_nonetiface.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// Adafruit IO WipperSnapper - Offline Mode
2-
// USE ONLY WITH DEVICES WITH A NETWORK ADAPTER LIKE ESP32-x
1+
// Adafruit IO WipperSnapper - Offline Mode without Network Interface
2+
// USE ONLY WITH DEVICES WITHOUT A NETWORK ADAPTER LIKE RP2040 PICO
33
//
44
// Adafruit invests time and resources providing this open source code.
55
// Please support Adafruit and open source hardware by purchasing

src/Wippersnapper_demo.ino

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,21 @@
11
// Adafruit IO WipperSnapper
2+
// USE ONLY WITH DEVICES WITHOUT A NETWORK ADAPTER LIKE RP2040 PICO
23
//
34
// Adafruit invests time and resources providing this open source code.
45
// Please support Adafruit and open source hardware by purchasing
56
// products from Adafruit!
67
//
7-
// Brent Rubell for Adafruit Industries, 2020-2025
8+
// Brent Rubell for Adafruit Industries, 2025
89
//
910
// All text above must be included in any redistribution.
1011

1112
#include "ws_adapters.h"
12-
#if defined(ARDUINO_RASPBERRY_PI_PICO_2) || \
13-
defined(ARDUINO_RASPBERRY_PI_PICO) || \
14-
defined(ARDUINO_ADAFRUIT_FEATHER_RP2040_ADALOGGER) || \
15-
defined(ARDUINO_ADAFRUIT_METRO_RP2350)
16-
ws_adapter_offline wipper;
17-
#else
1813
ws_adapter_wifi wipper;
19-
#endif
20-
2114
#define WS_DEBUG // Enable debug output!
2215

2316
void setup() {
2417
Serial.begin(115200);
18+
while (!Serial) delay(10);
2519
wipper.provision();
2620
wipper.connect();
2721
}

src/Wippersnapper_demo.ino.cpp

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/components/gps/controller.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,10 @@ bool GPSController::AddGPS(TwoWire *wire, uint32_t i2c_addr,
7272
* @param gps_config Pointer to the GPS configuration message.
7373
* @return True if the GPS was added successfully, false otherwise.
7474
*/
75-
bool GPSController::AddGPS(HardwareSerial *serial,
76-
wippersnapper_gps_GPSConfig *gps_config) {
75+
bool GPSController::AddGPS(HardwareSerial *serial, uint32_t baudrate, wippersnapper_gps_GPSConfig *gps_config) {
7776
GPSHardware *gps_hw = new GPSHardware();
7877

79-
if (!gps_hw->SetInterface(serial)) {
78+
if (!gps_hw->SetInterface(serial, baudrate)) {
8079
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to set GPS UART interface!");
8180
delete gps_hw;
8281
return false;

src/components/gps/controller.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class GPSController {
3131
public:
3232
GPSController();
3333
~GPSController();
34-
bool AddGPS(HardwareSerial *serial, wippersnapper_gps_GPSConfig *gps_config);
34+
bool AddGPS(HardwareSerial *serial, uint32_t baudrate, wippersnapper_gps_GPSConfig *gps_config);
3535
bool AddGPS(TwoWire *wire, uint32_t i2c_addr,
3636
wippersnapper_gps_GPSConfig *gps_config);
3737
void update();

src/components/gps/hardware.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,13 @@ bool GPSHardware::Handle_GPSConfig(wippersnapper_gps_GPSConfig *gps_config) {
177177
* Pointer to a HardwareSerial instance.
178178
* @returns True if the interface was set successfully, False otherwise.
179179
*/
180-
bool GPSHardware::SetInterface(HardwareSerial *serial) {
180+
bool GPSHardware::SetInterface(HardwareSerial *serial, uint32_t baudrate) {
181181
if (serial == nullptr)
182182
return false;
183183
// Configure the hardware serial interface
184184
_hw_serial = serial;
185185
_iface_type = GPS_IFACE_UART_HW;
186+
_baudrate = baudrate;
186187
return true;
187188
}
188189

@@ -357,7 +358,7 @@ bool GPSHardware::DetectMtkUart() {
357358

358359
// Attempt to use Adafruit_GPS
359360
_ada_gps = new Adafruit_GPS(_hw_serial);
360-
if (!_ada_gps->begin(_hw_serial->baudRate())) {
361+
if (!_ada_gps->begin(_baudrate)) {
361362
WS_DEBUG_PRINTLN("[gps] ERROR: Failed to initialize Mediatek!");
362363
return false;
363364
}

src/components/gps/hardware.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class GPSHardware {
6868
GPSHardware();
6969
~GPSHardware();
7070
bool begin();
71-
bool SetInterface(HardwareSerial *serial);
71+
bool SetInterface(HardwareSerial *serial, uint32_t baudrate);
7272
bool SetInterface(TwoWire *wire);
7373
void SetPollPeriod(ulong poll_period);
7474
void SetPollPeriodPrv(ulong poll_period_prv);
@@ -114,7 +114,6 @@ class GPSHardware {
114114
float GetSpeed();
115115
float GetAngle();
116116
float GetGeoidHeight();
117-
118117
private:
119118
bool QueryModuleType();
120119
bool DetectMtkUart();
@@ -132,14 +131,15 @@ class GPSHardware {
132131
nullptr; ///< Optional Adafruit UBlox DDC instance
133132
Adafruit_UBX *_ubx_gps = nullptr; ///< Optional Adafruit UBX instance
134133
uint32_t _addr; ///< Optional i2c address
135-
ulong _period; ///< Polling period for GPS data (Specified by IO), in ms
136-
ulong _period_prv; ///< Previous period for GPS data (Specified by IO), in ms
137-
ulong _kat_prv; ///< Last time the GPS hardware was polled, in ms
138-
int _nmea_update_rate; ///< NMEA update rate for GPS data, in Hz
139-
int _nmea_baud_rate; ///< NMEA baud rate for GPS data, in bits per second
134+
ulong _period; ///< Polling period for GPS data (Specified by IO), in ms
135+
ulong _period_prv; ///< Previous period for GPS data (Specified by IO), in ms
136+
ulong _kat_prv; ///< Last time the GPS hardware was polled, in ms
137+
uint32_t _baudrate; ///< Baud rate of UART bus
138+
int _nmea_update_rate; ///< NMEA update rate for GPS data, in Hz
139+
int _nmea_baud_rate; ///< NMEA baud rate for GPS data, in bits per second
140140
int NmeaBufPush(
141-
const char *new_sentence); ///< Push a sentence to the NMEA ring buffer
142-
nmea_buffer_t _nmea_buff; ///< NMEA ring buffer for storing sentences
141+
const char *new_sentence); ///< Push a sentence to the NMEA ring buffer
142+
nmea_buffer_t _nmea_buff; ///< NMEA ring buffer for storing sentences
143143
};
144144
extern Wippersnapper_V2 WsV2; ///< Wippersnapper V2 instance
145145
#endif // WS_GPS_HARDWARE_H

src/components/i2c/controller.cpp

Lines changed: 145 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,71 @@ static const std::map<std::string, FnCreateI2CSensorDriver> I2cFactorySensor = {
344344
return new drvVl6180x(i2c, addr, mux_channel, driver_name);
345345
}}}; ///< I2C driver factory
346346

347+
static const std::unordered_map<uint16_t, std::vector<const char *>>
348+
map_address_to_drivers = {
349+
{0x0B, {"lc709203f"}},
350+
{0x12, {"pmsa003i"}},
351+
{0x13, {"vncl4020"}},
352+
{0x18, {"ds2484", "mcp9808", "mprls"}},
353+
{0x19, {"mcp9808"}},
354+
{0x1A, {"mcp9808"}},
355+
{0x1B, {"mcp9808"}},
356+
{0x1C, {"mcp9808"}},
357+
{0x1D, {"mcp9808"}},
358+
{0x1E, {"mcp9808"}},
359+
{0x1F, {"mcp9808"}},
360+
{0x23, {"bh1750"}},
361+
{0x28, {"pct2075"}},
362+
{0x29,
363+
{"ltr303", "pct2075", "tsl2591", "veml7700", "vl53l1x", "vl53l4cd",
364+
"vl53l4cx", "vl6180x"}},
365+
{0x2A, {"nau7802"}},
366+
{0x38, {"aht20", "max17048"}},
367+
{0x39, {"tsl2591"}},
368+
{0x40,
369+
{"htu21d", "htu31d", "ina219", "ina260", "ms8607", "si7021",
370+
"stemma_soil"}},
371+
{0x41, {"htu31d", "ina219", "ina260"}},
372+
{0x44, {"hdc302x", "ina260", "sht3x", "sht4x"}},
373+
{0x45, {"hdc302x", "ina260", "sht3x"}},
374+
{0x46, {"hdc302x"}},
375+
{0x47, {"hdc302x"}},
376+
{0x48, {"adt7410", "pct2075", "tmp117"}},
377+
{0x49, {"adt7410", "pct2075", "tmp117", "tsl2591"}},
378+
{0x4A, {"adt7410", "pct2075", "tmp117"}},
379+
{0x4B, {"adt7410", "pct2075", "tmp117"}},
380+
{0x4C, {"pct2075"}},
381+
{0x4D, {"pct2075"}},
382+
{0x4E, {"pct2075"}},
383+
{0x4F, {"pct2075"}},
384+
{0x51, {"vcnl4200"}},
385+
{0x52, {"ens160"}},
386+
{0x53, {"ens160", "ltr390"}},
387+
{0x58, {"sgp30"}},
388+
{0x59, {"sgp40"}},
389+
{0x5C,
390+
{"bh1750", "lps22hb", "lps25hb", "lps28dfw", "lps33hw", "lps35hw"}},
391+
{0x5D, {"lps22hb", "lps25hb", "lps28dfw", "lps33hw", "lps35hw"}},
392+
{0x5F, {"hts2221"}},
393+
{0x60, {"mpl115a2", "vncl4040"}},
394+
{0x61, {"scd30"}},
395+
{0x62, {"scd40"}},
396+
{0x68, {"mcp3421"}},
397+
{0x69, {"sen55"}},
398+
{0x6B, {"sen66"}},
399+
{0x70, {"pct2075", "shtc3"}},
400+
{0x71, {"pct2075"}},
401+
{0x72, {"pct2075"}},
402+
{0x73, {"pct2075"}},
403+
{0x74, {"pct2075"}},
404+
{0x75, {"pct2075"}},
405+
{0x76,
406+
{"bme280", "bme680", "bmp280", "bmp388", "bmp390", "dps310", "ms8607",
407+
"pct2075"}},
408+
{0x77,
409+
{"bme280", "bme680", "bmp280", "bmp388", "bmp390", "dps310",
410+
"pct2075"}}}; ///< I2C address to driver map
411+
347412
/*!
348413
@brief Lambda function to create a drvOutputBase instance
349414
@param i2c
@@ -438,6 +503,26 @@ drvOutputBase *CreateI2cOutputDrv(const char *driver_name, TwoWire *i2c,
438503
return it->second(i2c, addr, i2c_mux_channel, driver_name);
439504
}
440505

506+
/***********************************************************************/
507+
/*!
508+
@brief Obtains possible candidate drivers for a given I2C address.
509+
@param addr
510+
The desired I2C address.
511+
@returns A vector of pointers to candidate drivers.
512+
*/
513+
/***********************************************************************/
514+
std::vector<const char *> GetDriversForAddress(uint16_t addr) {
515+
std::vector<const char *> candidates;
516+
std::unordered_map<uint16_t, std::vector<const char *>>::const_iterator
517+
candidate = map_address_to_drivers.find(addr);
518+
519+
if (candidate != map_address_to_drivers.end()) {
520+
candidates = candidate->second;
521+
}
522+
523+
return candidates;
524+
}
525+
441526
/*!
442527
@brief I2cController constructor
443528
*/
@@ -882,6 +967,12 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
882967

883968
// Is this a i2c GPS?
884969
bool is_gps = _i2c_model->GetI2cDeviceAddOrReplaceMsg()->is_gps;
970+
WS_DEBUG_PRINT("[i2c] Device name: ");
971+
WS_DEBUG_PRINTLN(device_name);
972+
WS_DEBUG_PRINT("[i2c] Device address: 0x");
973+
WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address, HEX);
974+
WS_DEBUG_PRINT("[i2c] Is GPS? ");
975+
WS_DEBUG_PRINTLN(is_gps ? "Yes" : "No");
885976

886977
// TODO [Online]: Handle Replace messages by implementing the Remove handler
887978
// first...then proceed to adding a new device
@@ -956,7 +1047,58 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
9561047
drvOutputBase *drv_out = nullptr;
9571048
GPSController *drv_uart_gps = nullptr;
9581049

959-
if (is_output) {
1050+
if (strcmp(device_name, "UNKNOWN_SCAN") == 0) {
1051+
WS_DEBUG_PRINTLN("Attempting to autoconfig device found in scan...");
1052+
if (device_descriptor.i2c_device_address == 0x68 ||
1053+
device_descriptor.i2c_device_address == 0x70) {
1054+
WS_DEBUG_PRINTLN("[i2c] Device address is shared with RTC/MUX, can not "
1055+
"auto-init, skipping!");
1056+
return true;
1057+
}
1058+
// Get all possible driver candidates for this address
1059+
WS_DEBUG_PRINT("[i2c] Obtaining driver candidates @ 0x");
1060+
WS_DEBUG_PRINTLN(device_descriptor.i2c_device_address, HEX);
1061+
1062+
// Probe each candidate to see if it communicates
1063+
bool did_find_driver = false;
1064+
for (const char *driverName :
1065+
GetDriversForAddress(device_descriptor.i2c_device_address)) {
1066+
WS_DEBUG_PRINT("[i2c] Attempting to initialize candidate: ");
1067+
WS_DEBUG_PRINTLN(driverName);
1068+
drv = CreateI2cSensorDrv(
1069+
driverName, bus, device_descriptor.i2c_device_address,
1070+
device_descriptor.i2c_mux_channel, device_status);
1071+
// Probe the driver to check if it communicates its init. sequence
1072+
if (!drv->begin()) {
1073+
WS_DEBUG_PRINTLN("[i2c] Failed to initialize candidate: ");
1074+
WS_DEBUG_PRINTLN(driverName);
1075+
delete drv;
1076+
drv = nullptr;
1077+
} else {
1078+
WS_DEBUG_PRINT("[i2c] Successfully initialized candidate: ");
1079+
WS_DEBUG_PRINTLN(driverName);
1080+
// set device_name to driverName
1081+
strcpy(device_name, driverName);
1082+
// Use the "default" types from the sensor driver
1083+
drv->EnableSensorReads(true);
1084+
drv->SetSensorPeriod(DEFAULT_SENSOR_PERIOD);
1085+
#ifndef OFFLINE_MODE_WOKWI
1086+
WsV2._fileSystemV2->AddI2cDeviceToFileConfig(
1087+
device_descriptor.i2c_device_address, driverName,
1088+
drv->GetSensorTypeStrings(), drv->GetNumSensorTypes());
1089+
#endif
1090+
did_find_driver = true;
1091+
_i2c_drivers.push_back(drv);
1092+
return true;
1093+
}
1094+
}
1095+
if (!did_find_driver) {
1096+
WS_DEBUG_PRINTLN("[i2c] ERROR - Candidates exhausted, driver not found!");
1097+
return true; // dont cause an error in the app
1098+
}
1099+
}
1100+
1101+
else if (is_output) {
9601102
WS_DEBUG_PRINT("[i2c] Creating an I2C output driver...");
9611103
drv_out = CreateI2cOutputDrv(
9621104
device_name, bus, device_descriptor.i2c_device_address,
@@ -1023,11 +1165,12 @@ bool I2cController::Handle_I2cDeviceAddOrReplace(pb_istream_t *stream) {
10231165
}
10241166
WS_DEBUG_PRINTLN("[i2c] Set driver to use Alt I2C bus");
10251167
}
1026-
// Configure the driver
10271168

1169+
// Configure the driver
10281170
if (!is_output) {
10291171
// Configure Input-driver settings
10301172
drv->EnableSensorReads(
1173+
false,
10311174
_i2c_model->GetI2cDeviceAddOrReplaceMsg()->i2c_device_sensor_types,
10321175
_i2c_model->GetI2cDeviceAddOrReplaceMsg()
10331176
->i2c_device_sensor_types_count);

src/components/i2c/drivers/drvBase.h

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,21 @@ class drvBase {
142142
@param sensor_types_count
143143
The number of active sensors to read from the device.
144144
*/
145-
void EnableSensorReads(bool use_default_types,
146-
wippersnapper_sensor_SensorType *sensor_types,
147-
size_t sensor_types_count) {
148-
_sensors_count = sensor_types_count;
145+
void
146+
EnableSensorReads(bool use_default_types = false,
147+
wippersnapper_sensor_SensorType *sensor_types = nullptr,
148+
size_t sensor_types_count = 0) {
149+
// Assign number of sensors
150+
if (use_default_types) {
151+
// Configure the driver with values from THE DRIVER
152+
ConfigureDefaultSensorTypes();
153+
_sensors_count = _default_sensor_types_count;
154+
} else {
155+
// Configure the driver with values from THE CONFIG FILE
156+
_sensors_count = sensor_types_count;
157+
}
158+
159+
// Fill sensor types with default values
149160
for (size_t i = 0; i < _sensors_count; i++) {
150161
if (use_default_types)
151162
_sensors[i] = _default_sensor_types[i];
@@ -219,21 +230,6 @@ class drvBase {
219230

220231
size_t GetNumSensorTypes() { return _sensors_count; }
221232

222-
/*!
223-
@brief Configures an i2c device's sensors.
224-
@param sensor_types
225-
Pointer to an array of SensorType objects.
226-
@param sensor_types_count
227-
The number of active sensors to read from the device.
228-
*/
229-
void EnableSensorReads(wippersnapper_sensor_SensorType *sensor_types,
230-
size_t sensor_types_count) {
231-
_sensors_count = sensor_types_count;
232-
for (size_t i = 0; i < _sensors_count; i++) {
233-
_sensors[i] = sensor_types[i];
234-
}
235-
}
236-
237233
/*******************************************************************************/
238234
/*!
239235
@brief Gets the sensor's previous period.

0 commit comments

Comments
 (0)