// Full bring-up test for the XIAO RP2040 test board // // Tests every part of the board: // 1. Status LED on D0 (active-low: LOW = on) // 2. Five WS2812B addressable LEDs on D2 (through JP3 -> R3) // 3. Infineon TLE493D-A2B6 3-axis hall sensor (U3) on I2C, D4 = SDA, D5 = SCL // 4. Button on D1 (to ground, internal pull-up) // // Libraries (Arduino Library Manager): // - Adafruit NeoPixel // - XENSIV 3D Magnetic Sensor TLx493D (Infineon) // // Board: Seeed XIAO RP2040. Open the Serial Monitor at 115200 baud, // or the Serial Plotter to see X, Y, Z as live graphs. // If the sensor acts up, unplug the USB for 10 seconds so it starts fresh. // // While running: // - Bring a magnet near the sensor: more LEDs light up as the field gets // stronger, red for one pole facing the sensor, blue for the other. // - Press the button: switches between magnet mode and rainbow mode. // The status LED lights while the button is held. // - Fast-blinking status LED = the hall sensor did not respond at startup. #include #include #include "TLx493D_inc.hpp" using namespace ifx::tlx493d; // ---------- Pins and settings ---------- #define STATUS_LED_PIN D0 // active-low #define BUTTON_PIN D1 // pressed = LOW #define LED_PIN D2 // WS2812B chain data #define LED_COUNT 5 #define MAX_BRIGHTNESS 64 // out of 255; keeps 5 LEDs at full white around 75 mA #define STEP_MS 250 #define MT_PER_LED 6.0 // one more LED lights for every 6 mT Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); TLx493D_A2B6 sensor(Wire, TLx493D_IIC_ADDR_A0_e); // address 0x35 bool sensorOk = false; bool rainbowMode = false; bool lastButton = HIGH; // ---------- Status LED ---------- void statusLed(bool on) { digitalWrite(STATUS_LED_PIN, on ? LOW : HIGH); } // ---------- Addressable LEDs ---------- // Light one LED at a time. If the walk stops at LED N, // check the solder joints between LED N-1 DOUT and LED N DIN. void walk(uint32_t color) { for (int i = 0; i < LED_COUNT; i++) { strip.clear(); strip.setPixelColor(i, color); strip.show(); delay(STEP_MS); } strip.clear(); strip.show(); } // More LEDs for a stronger field; red when Z is positive, blue when negative void showField(double x, double y, double z) { double magnitude = sqrt(x * x + y * y + z * z); int lit = constrain((int)(magnitude / MT_PER_LED), 0, LED_COUNT); uint32_t color = (z >= 0) ? strip.Color(255, 0, 0) : strip.Color(0, 0, 255); strip.clear(); for (int i = 0; i < lit; i++) strip.setPixelColor(i, color); strip.show(); } // ---------- I2C ---------- void i2cScan() { int found = 0; for (uint8_t addr = 1; addr < 127; addr++) { Wire.beginTransmission(addr); if (Wire.endTransmission() == 0) { Serial.print(" Found device at 0x"); if (addr < 16) Serial.print("0"); Serial.println(addr, HEX); found++; } } if (found == 0) { Serial.println(" No I2C devices found (check U3, R1/R5 pull-ups, JP4)"); } } // ---------- Hall sensor ---------- // Reads the field. Returns false if the data isn't real: a working sensor // reports roughly room temperature, and about -258 C means no real data. bool readField(double &x, double &y, double &z) { double t; sensor.getMagneticFieldAndTemperature(&x, &y, &z, &t); return (t > -40.0 && t < 125.0); } // ---------- Setup: one-time checks ---------- void setup() { pinMode(STATUS_LED_PIN, OUTPUT); statusLed(false); pinMode(BUTTON_PIN, INPUT_PULLUP); Serial.begin(115200); unsigned long start = millis(); while (!Serial && millis() - start < 3000) {} // wait up to 3 s for the Serial Monitor Serial.println(); Serial.println("=== Board bring-up test ==="); Serial.println("1. Status LED: blinking 3 times"); for (int i = 0; i < 3; i++) { statusLed(true); delay(200); statusLed(false); delay(200); } Serial.println("2. Addressable LEDs: walking red, green, blue through all 5"); strip.begin(); strip.setBrightness(MAX_BRIGHTNESS); strip.clear(); strip.show(); walk(strip.Color(255, 0, 0)); walk(strip.Color(0, 255, 0)); walk(strip.Color(0, 0, 255)); Serial.println("3. Hall sensor (TLE493D-A2B6)"); bool started = sensor.begin(); // also starts I2C on D4 / D5 Serial.println(" I2C scan (expect 0x35):"); i2cScan(); double x, y, z; sensorOk = started && readField(x, y, z); if (sensorOk) { Serial.print(" PASS: sensor sends real data (X:"); Serial.print(x, 1); Serial.print(" Y:"); Serial.print(y, 1); Serial.print(" Z:"); Serial.print(z, 1); Serial.println(" mT)"); } else { Serial.println(" FAIL: no valid data. Unplug the USB for 10 s and try again."); } // Flash all LEDs green for pass, red for fail strip.fill(sensorOk ? strip.Color(0, 255, 0) : strip.Color(255, 0, 0)); strip.show(); delay(800); strip.clear(); strip.show(); Serial.println("4. Running. Bring a magnet near the sensor; press the button to switch modes."); } // ---------- Loop: live test ---------- void loop() { // Button: each press switches mode; status LED lights while held bool button = digitalRead(BUTTON_PIN); if (lastButton == HIGH && button == LOW) { rainbowMode = !rainbowMode; Serial.println(rainbowMode ? "Button pressed: rainbow mode" : "Button pressed: magnet mode"); } lastButton = button; if (button == LOW) { statusLed(true); } else if (!sensorOk) { statusLed((millis() / 250) % 2); // fast blink = sensor problem } else { statusLed(false); } if (rainbowMode) { static uint16_t hue = 0; strip.rainbow(hue); strip.show(); hue += 512; } else if (sensorOk) { double x, y, z; if (readField(x, y, z)) { // Format works for both the Serial Monitor and the Serial Plotter Serial.print("X:"); Serial.print(x, 1); Serial.print(" Y:"); Serial.print(y, 1); Serial.print(" Z:"); Serial.println(z, 1); showField(x, y, z); } else { Serial.println("No valid data from the sensor"); } } else { strip.clear(); strip.show(); } delay(50); // about 20 updates per second; also debounces the button }