PCB Net Routing Assistance
0:12
Thought for a moment
0:33
Thought for 4 sec
1/3 Check whether copper-zone net assignment is editable in the current layout controls
Thought for 6 sec
Thought for 4 sec
3/3 tasks completed.
Thought for a moment
connectedLayers, shape, stitching, and thermal-style rules exist, but net, Net Name, and effectiveNetId are not valid editable zone rules.Table
| Function | nRF52840 pin | Schematic net | Connected device | Notes |
|---|---|---|---|---|
| LF crystal XL1 | P0.00 | XL1_32K | Y1 OSC1, C15 12 pF | 32.768 kHz crystal |
| LF crystal XL2 | P0.01 | XL2_32K | Y1 OSC2, C16 12 pF | 32.768 kHz crystal |
| Battery ADC | P0.04 / AIN2 | AIN2_BAT_DIV | R10/R11 100k divider, C21 100 nF | ADC measures VSYS/2 |
| I2C SDA | P0.26 | I2C_SDA | BME280, SGP41, SPS30 connector, R7 4.7k | 3V0 pull-up |
| I2C SCL | P0.27 | I2C_SCL | BME280, SGP41, SPS30 connector, R8 4.7k | 3V0 pull-up |
| QSPI CS | P0.17 | QSPI_CS_FLASH | W25Q64JV /CS | External flash |
| QSPI CLK | P0.19 | QSPI_CLK | W25Q64JV CLK | External flash |
| QSPI IO0 | P0.21 | QSPI_IO0 | W25Q64JV DI/IO0 | External flash |
| QSPI IO1 | P0.22 | QSPI_IO1 | W25Q64JV DO/IO1 | External flash |
| QSPI IO2 | P0.23 | QSPI_IO2 | W25Q64JV WP#/IO2 | External flash |
| QSPI IO3 | P1.00 | QSPI_IO3 | W25Q64JV HOLD#/IO3 | External flash; SWO left unused |
| STATUS LED | P0.13 | LED_STATUS | R12 1k, D5 green | GPIO high turns LED on |
| Firmware ERR LED | P0.14 | LED_FW_ERR | R13 1k, D6 red | GPIO high turns LED on |
| User button | P0.15 | USER_BUTTON | SW1 to GND | Use internal pull-up; pressed = LOW |
| Reset/SWD reset | P0.18/nRESET | MCU_RESET | Tag-Connect pin 3 | Debug reset |
| SWDIO | SWDIO | SWDIO | Tag-Connect pin 2 | Debug |
| SWDCLK | SWDCLK | SWDCLK | Tag-Connect pin 4 | Debug |
| SWD VTref | 3V0 | 3V0 | Tag-Connect pin 1 | Target voltage reference |
| SWD GND | GND | GND | Tag-Connect pin 5 | Debug ground |
| SWO | — | NC | Tag-Connect pin 6 | Optional; not wired because P1.00 is QSPI IO3 |
Ini
[env:nrf52840_wearable] platform = nordicnrf52 board = adafruit_feather_nrf52840 framework = arduino monitor_speed = 115200 lib_deps = adafruit/Adafruit BME280 Library adafruit/Adafruit Unified Sensor sensirion/Sensirion I2C SGP4x sensirion/Sensirion Core
Cpp
#include <Arduino.h> #include <Wire.h> #include <Adafruit_BME280.h> #include <SensirionI2CSgp41.h> // Pin definitions from schematic static constexpr uint8_t PIN_I2C_SDA = 26; // P0.26 -> I2C_SDA static constexpr uint8_t PIN_I2C_SCL = 27; // P0.27 -> I2C_SCL static constexpr uint8_t PIN_AIN2_BAT = 4; // P0.04 / AIN2 -> battery divider midpoint static constexpr uint8_t PIN_LED_STATUS = 13; // P0.13 -> R12 -> D5 green static constexpr uint8_t PIN_LED_ERR = 14; // P0.14 -> R13 -> D6 red static constexpr uint8_t PIN_USER_BUTTON = 15; // P0.15 -> SW1 -> GND // QSPI flash pin mapping, for board-definition / Nordic SDK configuration static constexpr uint8_t PIN_QSPI_CS = 17; // P0.17 static constexpr uint8_t PIN_QSPI_CLK = 19; // P0.19 static constexpr uint8_t PIN_QSPI_IO0 = 21; // P0.21 static constexpr uint8_t PIN_QSPI_IO1 = 22; // P0.22 static constexpr uint8_t PIN_QSPI_IO2 = 23; // P0.23 static constexpr uint8_t PIN_QSPI_IO3 = 32; // P1.00 is encoded as 32 in many nRF52 Arduino cores static constexpr uint8_t BME280_ADDR = 0x76; static constexpr uint8_t SGP41_ADDR = 0x59; static constexpr uint8_t SPS30_ADDR = 0x69; Adafruit_BME280 bme; SensirionI2CSgp41 sgp41; uint16_t sgp41ConditioningTicks = 0; uint32_t lastSensorMs = 0; float readBatteryVolts() { // Divider is 100k / 100k, so VBAT/VSYS at ADC pin is half the rail. // analogRead() range depends on Arduino core ADC reference and resolution. // Use analogReadMilliVolts() if your selected core supports it. #if defined(ARDUINO_ARCH_NRF52) uint16_t raw = analogRead(PIN_AIN2_BAT); float adcVolts = (raw / 1023.0f) * 3.0f; // default approximation; calibrate in firmware #else uint16_t raw = analogRead(PIN_AIN2_BAT); float adcVolts = (raw / 1023.0f) * 3.3f; #endif return adcVolts * 2.0f; } bool probeI2C(uint8_t address) { Wire.beginTransmission(address); return Wire.endTransmission() == 0; } void setupGpio() { pinMode(PIN_LED_STATUS, OUTPUT); pinMode(PIN_LED_ERR, OUTPUT); pinMode(PIN_USER_BUTTON, INPUT_PULLUP); digitalWrite(PIN_LED_STATUS, LOW); digitalWrite(PIN_LED_ERR, LOW); } void setupI2C() { Wire.setPins(PIN_I2C_SDA, PIN_I2C_SCL); Wire.begin(); Wire.setClock(400000); } bool setupBME280() { if (!bme.begin(BME280_ADDR, &Wire)) { Serial.println("BME280 not found at 0x76"); return false; } bme.setSampling( Adafruit_BME280::MODE_NORMAL, Adafruit_BME280::SAMPLING_X2, Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::SAMPLING_X1, Adafruit_BME280::FILTER_X16, Adafruit_BME280::STANDBY_MS_1000 ); return true; } bool setupSGP41() { sgp41.begin(Wire); uint16_t serialNumber[3] = {0, 0, 0}; int16_t error = sgp41.getSerialNumber(serialNumber); if (error) { Serial.print("SGP41 serial read failed, error: "); Serial.println(error); return false; } Serial.print("SGP41 serial: "); Serial.print(serialNumber[0], HEX); Serial.print(serialNumber[1], HEX); Serial.println(serialNumber[2], HEX); return true; } void readSensors() { float tempC = bme.readTemperature(); float humidity = bme.readHumidity(); float pressurePa = bme.readPressure(); float batteryV = readBatteryVolts(); bool buttonPressed = (digitalRead(PIN_USER_BUTTON) == LOW); // SGP41 raw measurement. Use default compensation values initially: // relative humidity ticks = 0x8000, temperature ticks = 0x6666. uint16_t srawVoc = 0; uint16_t srawNox = 0; int16_t error = 0; if (sgp41ConditioningTicks < 10) { error = sgp41.executeConditioning(0x8000, 0x6666, srawVoc); sgp41ConditioningTicks++; } else { error = sgp41.measureRawSignals(0x8000, 0x6666, srawVoc, srawNox); } if (error) { digitalWrite(PIN_LED_ERR, HIGH); Serial.print("SGP41 read error: "); Serial.println(error); } else { digitalWrite(PIN_LED_ERR, LOW); } digitalWrite(PIN_LED_STATUS, !digitalRead(PIN_LED_STATUS)); Serial.print("T="); Serial.print(tempC, 2); Serial.print(" C, "); Serial.print("RH="); Serial.print(humidity, 1); Serial.print(" %, "); Serial.print("P="); Serial.print(pressurePa / 100.0f, 1); Serial.print(" hPa, "); Serial.print("VBAT/VSYS="); Serial.print(batteryV, 3); Serial.print(" V, "); Serial.print("SGP41 VOCraw="); Serial.print(srawVoc); Serial.print(", NOxraw="); Serial.print(srawNox); Serial.print(", "); Serial.print("button="); Serial.println(buttonPressed ? "pressed" : "released"); if (probeI2C(SPS30_ADDR)) { Serial.println("SPS30 present at 0x69"); } else { Serial.println("SPS30 not detected at 0x69"); } } void setup() { Serial.begin(115200); delay(500); Serial.println("MDBT50Q-P1MV2 wearable bring-up"); setupGpio(); setupI2C(); bool ok = true; ok &= setupBME280(); ok &= setupSGP41(); digitalWrite(PIN_LED_ERR, ok ? LOW : HIGH); digitalWrite(PIN_LED_STATUS, ok ? HIGH : LOW); } void loop() { const uint32_t now = millis(); if (now - lastSensorMs >= 1000) { lastSensorMs = now; readSensors(); } }
Welcome 👋
Flux helps you build PCBs faster with an AI teammate!
Create your account to collaborate, stay updated, fork your own version, and get instant answers from our AI agent.