diff --git a/README.md b/README.md index a289bed..513b4e2 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,14 @@ itself — the header order below is only for orientation. | RX (UART) | **GPIO17** | P1 | | OUT | GPIO16 | P1, optional | -Header order, USB-C end at the top: +Header order. **Orientation matters: hold the board with the ESP32-S3-WROOM-1 +module and its antenna at the TOP, and both USB-C sockets at the BOTTOM.** +Pin 1 of each column is the end nearest the module, furthest from the USB +sockets. (Getting this upside down is an easy way to wire the sensor into the +PSRAM pins.) ``` + [ ESP32-S3-WROOM-1 module + antenna ] <- TOP P1 (left) P2 (right) 1 3V3 1 GND 2 3V3 2 GPIO43 U0TXD -> CH343 @@ -89,8 +94,13 @@ Header order, USB-C end at the top: 20 GPIO14 20 GPIO19 USB D- 21 5V 21 GND 22 GND 22 GND + [ USB-C: COM (CH343) | USB ] <- BOTTOM ``` +Reference pinout: https://mischianti.org/vcc-gnd-studio-yd-esp32-s3-devkitc-1-clone-high-resolution-pinout-and-specs/ +Note that board also has a plain built-in LED on **GPIO38**, separate from the +RGB WS2812 on GPIO48 that this firmware drives. + Do not use for I/O: **GPIO35/36/37** (octal PSRAM — the R8 in N16R8), **GPIO43/44** (UART0 to the CH343), **GPIO19/20** (native USB), GPIO0/45/46 (strapping), GPIO48 (RGB LED), GPIO26–32 (flash, not broken out). diff --git a/src/main.cpp b/src/main.cpp index 74184c6..03a4623 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,6 +104,24 @@ static bool i2cProbe(uint8_t addr) { // setup() before WiFi ever starts. Check the lines are actually high with // pull-ups on before handing them to Wire. static bool i2cBusIdle() { + // First, with the internal pull-ups OFF. A powered C4001 breakout has its + // own pull-ups, so the lines stay high. If they sag to 0 with nothing + // driving them, there is no powered module on these pins at all -- which + // separates "sensor wired but mute" from "sensor not actually connected". + pinMode(PIN_I2C_SDA, INPUT); + pinMode(PIN_I2C_SCL, INPUT); + delayMicroseconds(500); + int sdaHi = 0, sclHi = 0; + for (int i = 0; i < 8; i++) { + sdaHi += digitalRead(PIN_I2C_SDA); + sclHi += digitalRead(PIN_I2C_SCL); + delayMicroseconds(100); + } + sensor.detectLog += "I2C: external pull-ups sda=" + String(sdaHi) + "/8 scl=" + + String(sclHi) + "/8 " + + ((sdaHi == 8 && sclHi == 8) ? "(module present)" + : "(NO powered module on these pins)") + "\n"; + pinMode(PIN_I2C_SDA, INPUT_PULLUP); pinMode(PIN_I2C_SCL, INPUT_PULLUP); delayMicroseconds(200); @@ -135,7 +153,8 @@ static bool uartSensorPresent() { while (Serial1.available()) Serial1.read(); // flush boot noise // A running C4001 streams frames continuously; nudge it in case it's stopped. - Serial1.print("sensorStart\r\n"); + // No terminator -- DFRobot_C4001_UART::writeReg sends the bare string. + Serial1.print("sensorStart"); uint32_t t0 = millis(); while (millis() - t0 < 1500) { @@ -171,6 +190,18 @@ static void detectSensor() { sensor.detectLog += "I2C: no ACK at 0x" + String(a, HEX) + "\n"; } } + + // Neither expected address answered. Sweep the whole bus so the log can + // distinguish "sensor at an unexpected address" from "nothing on the bus + // at all" -- which usually means power, swapped SDA/SCL, or the module's + // mode switch is set to UART. + String found; + for (uint8_t a = 1; a < 127; a++) { + Wire.beginTransmission(a); + if (Wire.endTransmission() == 0) found += " 0x" + String(a, HEX); + } + sensor.detectLog += found.length() ? "I2C: bus scan ->" + found + "\n" + : "I2C: bus scan found no devices\n"; } // end if (i2cBusIdle()) Serial.println(" probing UART ...");