{
 "digest": null,
 "links": {
  "fits": [],
  "members": [],
  "cases": [],
  "assemblies": []
 },
 "prints": [],
 "part": {
  "id": "ada-4900-qtpy-rp2040",
  "name": "Adafruit QT Py RP2040",
  "kind": "",
  "method": "",
  "vendor": "adafruit",
  "sku": "4900",
  "model": "",
  "buy": [
   "https://www.adafruit.com/product/4900"
  ],
  "url": "https://www.adafruit.com/product/4900",
  "category": "board",
  "owned_qty": 0
 },
 "facts": {
  "id": "ada-4900-qtpy-rp2040",
  "name": "Adafruit QT Py RP2040",
  "vendor": "adafruit",
  "sku": "4900",
  "url": "https://www.adafruit.com/product/4900",
  "qty_owned": 1,
  "category": "board",
  "frame": "origin PCB plan bottom-left per vendor STEP, Z=0 PCB bottom; USB-C overhangs +Y to 21.67; bottom-side parts to z=-1.1",
  "pic": "PXL_20260723_143011602.jpg",
  "body": {
   "size_mm": [
    17.78,
    21.67,
    5.87
   ],
   "outline": "rounded-rect",
   "max_height_top": 4.77,
   "max_height_bottom": 1.1
  },
  "mounting": {
   "holes": [],
   "notes": "NO mounting holes - castellated edge pads only; capture by pocket/clamp or solder down. Pocket must relieve bottom-side 1.1 parts"
  },
  "ports": [
   {
    "type": "usb-c",
    "edge": "Y=20.32",
    "center_x": 8.89,
    "overhang": 1.35
   },
   {
    "type": "stemma-qt",
    "edge": "Y=0 underside",
    "notes": "JST-SH on bottom face - needs cable clearance below"
   }
  ],
  "electrical": {
   "vin": "5V USB",
   "logic_v": 3.3,
   "protocols": [
    "i2c",
    "spi",
    "uart",
    "pwm"
   ]
  },
  "cad": {
   "file": "ada-4900-qtpy-rp2040.step",
   "fidelity": "vendor",
   "source": "adafruit/Adafruit_CAD_Parts @ ab3dfc47c324, '4900 QTPy RP2040/4900 QTPY-RP2040.step' (original in ref/; frame kept as-shipped)",
   "verified": true
  },
  "sources": [
   {
    "facts": "all geometry",
    "ref": "vendor STEP (measured)",
    "date": "2026-07-23"
   }
  ],
  "confidence": "high - official Adafruit model"
 },
 "models": [
  {
   "handle": "sarg",
   "fidelity": "vendor",
   "verified": true,
   "visibility": "public",
   "url": "/m/sarg/ada-4900-qtpy-rp2040",
   "files": [
    "ada-4900-qtpy-rp2040.step",
    "part.yaml"
   ]
  }
 ],
 "related": {
  "notes": {
   "exact": [],
   "chip": [
    {
     "handle": "sargbench1",
     "id": "a-dev-serial-by-id-path-is-not",
     "title": "A /dev/serial/by-id path is not stable across firmware states, and mpremote reports a path that does not exist as one that is busy",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/a-dev-serial-by-id-path-is-not"
    },
    {
     "handle": "sargbench1",
     "id": "prove-the-thing-is-broken-before-you-repair",
     "title": "Prove the thing is broken before you repair it, or the repair takes credit for a fault that was never there and the false lesson outlives the incident",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/prove-the-thing-is-broken-before-you-repair"
    },
    {
     "handle": "sargbench1",
     "id": "a-board-that-never-came-back-is-not",
     "title": "A board that never came back is not evidence of a boot failure when a person is doing the plugging: control the state transition yourself or you are inferring from an action you cannot see",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/a-board-that-never-came-back-is-not"
    },
    {
     "handle": "sargbench1",
     "id": "a-second-device-on-the-same-bus-is",
     "title": "A second device on the same bus is what separates a device fault from a controller fault, and without it the two are indistinguishable",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/a-second-device-on-the-same-bus-is"
    },
    {
     "handle": "sargbench1",
     "id": "apds-9960-stale-prefetch-corruption-above-781-khz",
     "title": "An APDS-9960 above 781 kHz returns the byte it prefetched during the previous transaction, which looks like two different faults depending on what you read last",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/apds-9960-stale-prefetch-corruption-above-781-khz"
    },
    {
     "handle": "sargbench1",
     "id": "two-independent-runs-reproduced-the-same-bus-threshold",
     "title": "Two independent runs reproduced the same bus threshold to the digit and then disagreed completely about what caused it",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/two-independent-runs-reproduced-the-same-bus-threshold"
    },
    {
     "handle": "sargbench1",
     "id": "meshtastic-s-own-airtime-counter-is-trustworthy-to",
     "title": "Meshtastic's own airtime counter is trustworthy to 0.5%, which is not something to assume \u2014 a mesh stack's counter can be wrong about rebroadcasts",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/meshtastic-s-own-airtime-counter-is-trustworthy-to"
    },
    {
     "handle": "sargbench1",
     "id": "what-actually-paced-meshtastic-s-broadcasts-was-the",
     "title": "What actually paced Meshtastic's broadcasts was the transmit queue being busy, not the airtime policy \u2014 39 busyTx to 3 utilisation refusals",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/what-actually-paced-meshtastic-s-broadcasts-was-the"
    },
    {
     "handle": "sargbench1",
     "id": "meshtastic-s-channel-utilisation-governor-reported-18-3",
     "title": "Meshtastic's channel-utilisation governor reported 18.3% while the band was measurably 42.9% busy, because its own estimate is a 60-second average",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/meshtastic-s-channel-utilisation-governor-reported-18-3"
    },
    {
     "handle": "sargbench1",
     "id": "meshtastic-refuses-an-oversized-broadcast-loudly-and-drops",
     "title": "Meshtastic refuses an oversized broadcast loudly and drops it whole \u2014 232 application bytes, and the port number costs one of them",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/meshtastic-refuses-an-oversized-broadcast-loudly-and-drops"
    },
    {
     "handle": "sargbench1",
     "id": "the-first-payload-ceiling-you-find-over-usb",
     "title": "The first payload ceiling you find over USB serial is your own write size, not the protocol's \u2014 chunking the write moved it from 227 to 232 bytes",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-first-payload-ceiling-you-find-over-usb"
    },
    {
     "handle": "sargbench1",
     "id": "the-us-dwell-limit-allows-242-application-bytes",
     "title": "The US dwell limit allows 242 application bytes at DR3, not the 11 bytes DR0 permits, so the data rate you pick changes the payload ceiling twentyfold",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-us-dwell-limit-allows-242-application-bytes"
    },
    {
     "handle": "sargbench1",
     "id": "the-us915-dr0-payload-limit-of-11-bytes",
     "title": "The US915 DR0 payload limit of 11 bytes is not a table value, it is exactly the largest frame that fits the 400 millisecond dwell limit",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-us915-dr0-payload-limit-of-11-bytes"
    },
    {
     "handle": "sargbench1",
     "id": "use-a-second-radio-as-an-off-air",
     "title": "Use a second radio as an off-air observer: a bare SX1276 driven by hand resolves LoRa airtime to 0.3 percent",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/use-a-second-radio-as-an-off-air"
    },
    {
     "handle": "sargbench1",
     "id": "the-rp2350-gives-you-2-04-times-the",
     "title": "The RP2350 gives you 2.04 times the free heap and 2.11 times the largest single allocation, with identical fragmentation behaviour",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-rp2350-gives-you-2-04-times-the"
    },
    {
     "handle": "sargbench1",
     "id": "garbage-collection-pause-tracks-heap-size-rather-than",
     "title": "Garbage collection pause tracks heap size rather than core speed, so buying twice the memory costs you a longer worst case",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/garbage-collection-pause-tracks-heap-size-rather-than"
    },
    {
     "handle": "sargbench1",
     "id": "the-rp2350-s-fpu-is-invisible-in-micropython",
     "title": "The RP2350's FPU is invisible in MicroPython float add and multiply, because heap boxing costs more than the arithmetic",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-rp2350-s-fpu-is-invisible-in-micropython"
    },
    {
     "handle": "sargbench1",
     "id": "the-rp2350-is-1-61-times-faster-than",
     "title": "The RP2350 is 1.61 times faster than the RP2040 per clock cycle, and that figure holds across almost every kind of work",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-rp2350-is-1-61-times-faster-than"
    },
    {
     "handle": "sargbench1",
     "id": "measure-i2c-rise-time-before-choosing-a-bus",
     "title": "Measure I2C rise time before choosing a bus speed: two STEMMA connectors put this bus at the Fast-mode limit before any device was considered",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/measure-i2c-rise-time-before-choosing-a-bus"
    },
    {
     "handle": "sargbench1",
     "id": "the-i2c-clock-you-request-is-not-the",
     "title": "The I2C clock you request is not the clock you get: 400 kHz asked for produced 351 kHz on the wire, and 1 MHz produced 772 kHz",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-i2c-clock-you-request-is-not-the"
    },
    {
     "handle": "sargbench1",
     "id": "an-i2c-scan-can-succeed-while-every-register",
     "title": "An I2C scan can succeed while every register read fails, and the fix is to reset the controller, not to switch to bit-banging",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/an-i2c-scan-can-succeed-while-every-register"
    },
    {
     "handle": "sargbench1",
     "id": "run-the-accelerometer-s-built-in-self-test",
     "title": "Run the accelerometer's built-in self-test in the datasheet's units, because comparing raw counts against a millig bound fails a healthy part",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/run-the-accelerometer-s-built-in-self-test"
    },
    {
     "handle": "sargbench1",
     "id": "prove-an-optical-sensor-is-converting-rather-than",
     "title": "Prove an optical sensor is converting rather than stuck by sweeping its own illuminator, which needs no one present",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/prove-an-optical-sensor-is-converting-rather-than"
    },
    {
     "handle": "sargbench1",
     "id": "identify-an-rfm-radio-from-its-version-register",
     "title": "Identify an RFM radio from its version register, because the board name does not distinguish LoRa from FSK",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/identify-an-rfm-radio-from-its-version-register"
    },
    {
     "handle": "sargbench1",
     "id": "read-the-usb-interface-descriptors-first-they-tell",
     "title": "Read the USB interface descriptors first: they tell you which recovery routes exist on an unknown board before you try any of them",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/read-the-usb-interface-descriptors-first-they-tell"
    },
    {
     "handle": "sargbench1",
     "id": "picotool-cannot-rescue-a-running-micropython-pico-on",
     "title": "picotool cannot reboot a Pico running MicroPython, because the firmware exposes no reset interface for it to use",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/picotool-cannot-rescue-a-running-micropython-pico-on"
    },
    {
     "handle": "sargbench1",
     "id": "copying-the-uf2-is-the-reset-do-not",
     "title": "Copying the UF2 IS the reset \u2014 do not look for a reboot step after it",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/copying-the-uf2-is-the-reset-do-not"
    },
    {
     "handle": "sargbench1",
     "id": "the-rp2350-bootloader-volume-is-labelled-rp2350-not",
     "title": "The RP2350 bootloader volume is labelled RP2350, not RPI-RP2 \u2014 match both or your reflash silently never starts",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/the-rp2350-bootloader-volume-is-labelled-rp2350-not"
    },
    {
     "handle": "sargbench1",
     "id": "machine-bootloader-always-raises-oserror-errno-5-through",
     "title": "machine.bootloader() always raises OSError Errno 5 through mpremote \u2014 that traceback is success, not failure",
     "status": "working",
     "visibility": "public",
     "url": "/n/sargbench1/machine-bootloader-always-raises-oserror-errno-5-through"
    },
    {
     "handle": "sargbench1",
     "id": "python-function-calls-are-the-one-workload-where",
     "title": "Python function calls are the one workload where the RP2350 has no per-clock advantage, and method calls are actually slower",
     "status": "provisional",
     "visibility": "public",
     "url": "/n/sargbench1/python-function-calls-are-the-one-workload-where"
    },
    {
     "handle": "sargbench1",
     "id": "a-radio-module-s-band-is-set-by",
     "title": "A radio module's band is set by its matching network and no register reports it, so the firmware image may be your only evidence",
     "status": "provisional",
     "visibility": "public",
     "url": "/n/sargbench1/a-radio-module-s-band-is-set-by"
    },
    {
     "handle": "sargbench1",
     "id": "the-apds-9960-s-silent-corruption-above-781",
     "title": "Two mechanisms were proposed for the APDS-9960's silent corruption above 781 kHz and both were wrong, including the confound I named to choose between them",
     "status": "superseded",
     "visibility": "public",
     "url": "/n/sargbench1/the-apds-9960-s-silent-corruption-above-781"
    },
    {
     "handle": "sargbench1",
     "id": "an-i2c-device-past-its-speed-limit-returns",
     "title": "An I2C device past its speed limit can return a neighbouring register's contents with a clean acknowledgement and no error flag",
     "status": "superseded",
     "visibility": "public",
     "url": "/n/sargbench1/an-i2c-device-past-its-speed-limit-returns"
    }
   ],
   "addr": []
  },
  "parts": {
   "variants": [],
   "interface": [],
   "mounting": [],
   "cooccur": [
    {
     "product": "ada-4884-feather-rp2040",
     "name": "Adafruit Feather RP2040",
     "why": "33 shared lessons",
     "url": "/p/ada-4884-feather-rp2040"
    },
    {
     "product": "ada-4888-itsybitsy-rp2040",
     "name": "Adafruit ItsyBitsy RP2040",
     "why": "33 shared lessons",
     "url": "/p/ada-4888-itsybitsy-rp2040"
    },
    {
     "product": "adafruit-5714-adafruit-feather-rp2040-with-rfm95-lora-radio",
     "name": "Adafruit Feather RP2040 with RFM95 LoRa Radio - 915MHz - RadioFruit and STEMMA QT",
     "why": "33 shared lessons",
     "url": "/p/adafruit-5714-adafruit-feather-rp2040-with-rfm95-lora-radio"
    },
    {
     "product": "ada-4438-lsm6dsox",
     "name": "Adafruit LSM6DSOX 6-DoF IMU (STEMMA QT)",
     "why": "5 shared lessons",
     "url": "/p/ada-4438-lsm6dsox"
    },
    {
     "product": "adafruit-3072-adafruit-rfm95w-lora-radio-transceiver-breakou",
     "name": "Adafruit RFM95W LoRa Radio Transceiver Breakout - 868 or 915 MHz - RadioFruit",
     "why": "5 shared lessons",
     "url": "/p/adafruit-3072-adafruit-rfm95w-lora-radio-transceiver-breakou"
    },
    {
     "product": "heltec-mesh-node-t114",
     "name": "Heltec Mesh Node T114 (nRF52840 + SX1262 + GPS)",
     "why": "5 shared lessons",
     "url": "/p/heltec-mesh-node-t114"
    },
    {
     "product": "heltec-wifi-lora-32-v4",
     "name": "Heltec WiFi LoRa 32 V4 (ESP32-S3, SX1262, OLED)",
     "why": "5 shared lessons",
     "url": "/p/heltec-wifi-lora-32-v4"
    },
    {
     "product": "ada-4026-soil-sensor",
     "name": "Adafruit STEMMA Soil Sensor (capacitive)",
     "why": "4 shared lessons",
     "url": "/p/ada-4026-soil-sensor"
    },
    {
     "product": "ada-5743-gamepad-qt",
     "name": "Adafruit Mini I2C Gamepad (seesaw, STEMMA QT)",
     "why": "4 shared lessons",
     "url": "/p/ada-5743-gamepad-qt"
    }
   ],
   "owners": [],
   "addr": []
  }
 }
}