[{"data":1,"prerenderedAt":634},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fmodules\u002Fi2c-passthrough":3},{"id":4,"title":5,"body":6,"description":627,"extension":628,"meta":629,"navigation":81,"path":630,"seo":631,"stem":632,"__hash__":633},"content\u002Fdocs\u002Fmodules\u002Fi2c-passthrough.md","I2C Passthrough",{"type":7,"value":8,"toc":618},"minimark",[9,13,34,37,42,65,158,162,189,194,459,463,487,546,550,558,579,591,595,614],[10,11,5],"h1",{"id":12},"i2c-passthrough",[14,15,16,17,21,22,25,26,29,30,33],"p",{},"This isn't a real module — it's a capability marker. CONDUYT already exposes ",[18,19,20],"code",{},"I2C_WRITE"," and ",[18,23,24],{},"I2C_READ"," commands at the protocol level, so any peripheral that speaks I2C can be driven directly from the host without writing custom firmware. Enabling ",[18,27,28],{},"CONDUYT_MODULE_I2C_PASSTHROUGH"," registers a stub module so it appears in ",[18,31,32],{},"HELLO_RESP.modules"," — letting host code feature-detect \"yes, this firmware speaks raw I2C.\"",[14,35,36],{},"Use this when you want to drive a sensor or peripheral that doesn't have a dedicated module yet — temperature sensors, RTCs, expanders, EEPROMs, anything I2C — by sending register reads\u002Fwrites from the host SDK.",[38,39,41],"h2",{"id":40},"firmware-setup","Firmware setup",[43,44,49],"pre",{"className":45,"code":46,"language":47,"meta":48,"style":48},"language-ini shiki shiki-themes github-light github-dark","; platformio.ini\nbuild_flags = -DCONDUYT_MODULE_I2C_PASSTHROUGH\n","ini","",[18,50,51,59],{"__ignoreMap":48},[52,53,56],"span",{"class":54,"line":55},"line",1,[52,57,58],{},"; platformio.ini\n",[52,60,62],{"class":54,"line":61},2,[52,63,64],{},"build_flags = -DCONDUYT_MODULE_I2C_PASSTHROUGH\n",[43,66,70],{"className":67,"code":68,"language":69,"meta":48,"style":48},"language-cpp shiki shiki-themes github-light github-dark","#include \u003CConduyt.h>\n\nConduytSerial transport(Serial, 115200);\nConduytDevice device(\"I2CHub\", \"1.0.0\", transport);\n\nvoid setup() {\n  Serial.begin(115200);\n  Wire.begin();   \u002F\u002F initialize the bus\n  device.addModule(new ConduytModuleI2CPassthrough());\n  device.begin();\n}\n\nvoid loop() {\n  device.poll();\n}\n","cpp",[18,71,72,77,83,89,95,100,106,112,118,124,130,136,141,147,153],{"__ignoreMap":48},[52,73,74],{"class":54,"line":55},[52,75,76],{},"#include \u003CConduyt.h>\n",[52,78,79],{"class":54,"line":61},[52,80,82],{"emptyLinePlaceholder":81},true,"\n",[52,84,86],{"class":54,"line":85},3,[52,87,88],{},"ConduytSerial transport(Serial, 115200);\n",[52,90,92],{"class":54,"line":91},4,[52,93,94],{},"ConduytDevice device(\"I2CHub\", \"1.0.0\", transport);\n",[52,96,98],{"class":54,"line":97},5,[52,99,82],{"emptyLinePlaceholder":81},[52,101,103],{"class":54,"line":102},6,[52,104,105],{},"void setup() {\n",[52,107,109],{"class":54,"line":108},7,[52,110,111],{},"  Serial.begin(115200);\n",[52,113,115],{"class":54,"line":114},8,[52,116,117],{},"  Wire.begin();   \u002F\u002F initialize the bus\n",[52,119,121],{"class":54,"line":120},9,[52,122,123],{},"  device.addModule(new ConduytModuleI2CPassthrough());\n",[52,125,127],{"class":54,"line":126},10,[52,128,129],{},"  device.begin();\n",[52,131,133],{"class":54,"line":132},11,[52,134,135],{},"}\n",[52,137,139],{"class":54,"line":138},12,[52,140,82],{"emptyLinePlaceholder":81},[52,142,144],{"class":54,"line":143},13,[52,145,146],{},"void loop() {\n",[52,148,150],{"class":54,"line":149},14,[52,151,152],{},"  device.poll();\n",[52,154,156],{"class":54,"line":155},15,[52,157,135],{},[38,159,161],{"id":160},"host-usage","Host usage",[14,163,164,165,168,169,172,173,176,177,180,181,184,185,188],{},"The marker module itself has no commands. Every ",[18,166,167],{},"MOD_CMD"," to it returns ",[18,170,171],{},"NAK 0x09",". Drive I2C through the proxy returned by ",[18,174,175],{},"device.i2c()"," directly. The proxy exposes ",[18,178,179],{},"write",", ",[18,182,183],{},"read",", and ",[18,186,187],{},"readReg"," methods.",[190,191,193],"h3",{"id":192},"javascript","JavaScript",[43,195,198],{"className":196,"code":197,"language":192,"meta":48,"style":48},"language-javascript shiki shiki-themes github-light github-dark","import { ConduytDevice } from 'conduyt-js'\nimport { SerialTransport } from 'conduyt-js\u002Ftransports\u002Fserial'\n\nconst device = await ConduytDevice.connect(new SerialTransport({ path: '\u003CYOUR_PORT>' }))\nconst i2c = device.i2c()\n\n\u002F\u002F Read 1 byte from register 0x75 (WHO_AM_I) of an MPU-6050 (addr 0x68)\nconst data = await i2c.readReg(0x68, 0x75, 1)\nconsole.log('WHO_AM_I:', data[0].toString(16))\n\n\u002F\u002F Or write then read in two steps:\nawait i2c.write(0x68, new Uint8Array([0x75]))   \u002F\u002F point to register 0x75\nconst echoed = await i2c.read(0x68, 1)\nconsole.log('WHO_AM_I (manual):', echoed[0].toString(16))\n",[18,199,200,217,229,233,273,291,295,301,335,368,372,377,408,433],{"__ignoreMap":48},[52,201,202,206,210,213],{"class":54,"line":55},[52,203,205],{"class":204},"szBVR","import",[52,207,209],{"class":208},"sVt8B"," { ConduytDevice } ",[52,211,212],{"class":204},"from",[52,214,216],{"class":215},"sZZnC"," 'conduyt-js'\n",[52,218,219,221,224,226],{"class":54,"line":61},[52,220,205],{"class":204},[52,222,223],{"class":208}," { SerialTransport } ",[52,225,212],{"class":204},[52,227,228],{"class":215}," 'conduyt-js\u002Ftransports\u002Fserial'\n",[52,230,231],{"class":54,"line":85},[52,232,82],{"emptyLinePlaceholder":81},[52,234,235,238,242,245,248,251,255,258,261,264,267,270],{"class":54,"line":91},[52,236,237],{"class":204},"const",[52,239,241],{"class":240},"sj4cs"," device",[52,243,244],{"class":204}," =",[52,246,247],{"class":204}," await",[52,249,250],{"class":208}," ConduytDevice.",[52,252,254],{"class":253},"sScJk","connect",[52,256,257],{"class":208},"(",[52,259,260],{"class":204},"new",[52,262,263],{"class":253}," SerialTransport",[52,265,266],{"class":208},"({ path: ",[52,268,269],{"class":215},"'\u003CYOUR_PORT>'",[52,271,272],{"class":208}," }))\n",[52,274,275,277,280,282,285,288],{"class":54,"line":97},[52,276,237],{"class":204},[52,278,279],{"class":240}," i2c",[52,281,244],{"class":204},[52,283,284],{"class":208}," device.",[52,286,287],{"class":253},"i2c",[52,289,290],{"class":208},"()\n",[52,292,293],{"class":54,"line":102},[52,294,82],{"emptyLinePlaceholder":81},[52,296,297],{"class":54,"line":108},[52,298,300],{"class":299},"sJ8bj","\u002F\u002F Read 1 byte from register 0x75 (WHO_AM_I) of an MPU-6050 (addr 0x68)\n",[52,302,303,305,308,310,312,315,317,319,322,324,327,329,332],{"class":54,"line":114},[52,304,237],{"class":204},[52,306,307],{"class":240}," data",[52,309,244],{"class":204},[52,311,247],{"class":204},[52,313,314],{"class":208}," i2c.",[52,316,187],{"class":253},[52,318,257],{"class":208},[52,320,321],{"class":240},"0x68",[52,323,180],{"class":208},[52,325,326],{"class":240},"0x75",[52,328,180],{"class":208},[52,330,331],{"class":240},"1",[52,333,334],{"class":208},")\n",[52,336,337,340,343,345,348,351,354,357,360,362,365],{"class":54,"line":120},[52,338,339],{"class":208},"console.",[52,341,342],{"class":253},"log",[52,344,257],{"class":208},[52,346,347],{"class":215},"'WHO_AM_I:'",[52,349,350],{"class":208},", data[",[52,352,353],{"class":240},"0",[52,355,356],{"class":208},"].",[52,358,359],{"class":253},"toString",[52,361,257],{"class":208},[52,363,364],{"class":240},"16",[52,366,367],{"class":208},"))\n",[52,369,370],{"class":54,"line":126},[52,371,82],{"emptyLinePlaceholder":81},[52,373,374],{"class":54,"line":132},[52,375,376],{"class":299},"\u002F\u002F Or write then read in two steps:\n",[52,378,379,382,384,386,388,390,392,394,397,400,402,405],{"class":54,"line":138},[52,380,381],{"class":204},"await",[52,383,314],{"class":208},[52,385,179],{"class":253},[52,387,257],{"class":208},[52,389,321],{"class":240},[52,391,180],{"class":208},[52,393,260],{"class":204},[52,395,396],{"class":253}," Uint8Array",[52,398,399],{"class":208},"([",[52,401,326],{"class":240},[52,403,404],{"class":208},"]))   ",[52,406,407],{"class":299},"\u002F\u002F point to register 0x75\n",[52,409,410,412,415,417,419,421,423,425,427,429,431],{"class":54,"line":143},[52,411,237],{"class":204},[52,413,414],{"class":240}," echoed",[52,416,244],{"class":204},[52,418,247],{"class":204},[52,420,314],{"class":208},[52,422,183],{"class":253},[52,424,257],{"class":208},[52,426,321],{"class":240},[52,428,180],{"class":208},[52,430,331],{"class":240},[52,432,334],{"class":208},[52,434,435,437,439,441,444,447,449,451,453,455,457],{"class":54,"line":149},[52,436,339],{"class":208},[52,438,342],{"class":253},[52,440,257],{"class":208},[52,442,443],{"class":215},"'WHO_AM_I (manual):'",[52,445,446],{"class":208},", echoed[",[52,448,353],{"class":240},[52,450,356],{"class":208},[52,452,359],{"class":253},[52,454,257],{"class":208},[52,456,364],{"class":240},[52,458,367],{"class":208},[190,460,462],{"id":461},"python","Python",[14,464,465,466,468,469,472,473,475,476,479,480,482,483,486],{},"The Python SDK doesn't have a public I2C proxy (the JS SDK's ",[18,467,175],{}," has no Python equivalent today). Send raw protocol commands via ",[18,470,471],{},"_send_command",". Wire format: ",[18,474,20],{}," payload is ",[18,477,478],{},"bus(1) + addr(1) + data(N)","; ",[18,481,24],{}," is ",[18,484,485],{},"bus(1) + addr(1) + count(1)",".",[43,488,491],{"className":489,"code":490,"language":461,"meta":48,"style":48},"language-python shiki shiki-themes github-light github-dark","from conduyt import ConduytDevice\nfrom conduyt.transports.serial import SerialTransport\nfrom conduyt.core.constants import CMD\n\ndevice = ConduytDevice(SerialTransport('\u003CYOUR_PORT>'))\nawait device.connect()\n\n# Read 1 byte from register 0x75 (WHO_AM_I) of an MPU-6050 (addr 0x68) on bus 0\nawait device._send_command(CMD.I2C_WRITE, bytes([0, 0x68, 0x75]))\ndata = await device._send_command(CMD.I2C_READ, bytes([0, 0x68, 1]))\nprint('WHO_AM_I:', data.hex())\n",[18,492,493,498,503,508,512,517,522,526,531,536,541],{"__ignoreMap":48},[52,494,495],{"class":54,"line":55},[52,496,497],{},"from conduyt import ConduytDevice\n",[52,499,500],{"class":54,"line":61},[52,501,502],{},"from conduyt.transports.serial import SerialTransport\n",[52,504,505],{"class":54,"line":85},[52,506,507],{},"from conduyt.core.constants import CMD\n",[52,509,510],{"class":54,"line":91},[52,511,82],{"emptyLinePlaceholder":81},[52,513,514],{"class":54,"line":97},[52,515,516],{},"device = ConduytDevice(SerialTransport('\u003CYOUR_PORT>'))\n",[52,518,519],{"class":54,"line":102},[52,520,521],{},"await device.connect()\n",[52,523,524],{"class":54,"line":108},[52,525,82],{"emptyLinePlaceholder":81},[52,527,528],{"class":54,"line":114},[52,529,530],{},"# Read 1 byte from register 0x75 (WHO_AM_I) of an MPU-6050 (addr 0x68) on bus 0\n",[52,532,533],{"class":54,"line":120},[52,534,535],{},"await device._send_command(CMD.I2C_WRITE, bytes([0, 0x68, 0x75]))\n",[52,537,538],{"class":54,"line":126},[52,539,540],{},"data = await device._send_command(CMD.I2C_READ, bytes([0, 0x68, 1]))\n",[52,542,543],{"class":54,"line":132},[52,544,545],{},"print('WHO_AM_I:', data.hex())\n",[38,547,549],{"id":548},"why-this-exists-as-a-module","Why this exists as a module",[14,551,552,554,555,557],{},[18,553,20],{}," \u002F ",[18,556,24],{}," work whether or not this module is registered — they're core protocol commands, not module commands. The marker module exists so the host can:",[559,560,561,576],"ol",{},[562,563,564,565,568,569,571,572,575],"li",{},"Discover that the firmware has I2C wired up (",[18,566,567],{},"Wire.begin()"," was called) by checking ",[18,570,32],{}," for the ",[18,573,574],{},"i2c_pass"," entry.",[562,577,578],{},"Show \"I2C available\" in playgrounds and dashboards instead of probing blindly.",[14,580,581,582,554,585,554,588,486],{},"If you only need raw I2C access and don't care about advertising it, you can leave this module disabled and still call ",[18,583,584],{},"device.i2c().write()",[18,586,587],{},"device.i2c().read()",[18,589,590],{},"device.i2c().readReg()",[38,592,594],{"id":593},"notes","Notes",[596,597,598,608,611],"ul",{},[562,599,600,601,604,605,607],{},"Bus speed: defaults to 100 kHz. Call ",[18,602,603],{},"Wire.setClock(400000)"," after ",[18,606,567],{}," for fast-mode I2C if your peripherals support it.",[562,609,610],{},"Multiple buses: ESP32, RP2040, and Teensy boards have multiple I2C ports. CONDUYT's core I2C commands target the first bus. Custom firmware can extend this if needed.",[562,612,613],{},"For higher-level abstractions over I2C peripherals (DHT, OLED, etc.), use the dedicated modules — they're easier and more reliable than driving registers from the host every time.",[615,616,617],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":48,"searchDepth":61,"depth":61,"links":619},[620,621,625,626],{"id":40,"depth":61,"text":41},{"id":160,"depth":61,"text":161,"children":622},[623,624],{"id":192,"depth":85,"text":193},{"id":461,"depth":85,"text":462},{"id":548,"depth":61,"text":549},{"id":593,"depth":61,"text":594},"Talk to arbitrary I2C peripherals from the host using the core I2C commands.","md",{},"\u002Fdocs\u002Fmodules\u002Fi2c-passthrough",{"title":5,"description":627},"docs\u002Fmodules\u002Fi2c-passthrough","BPdkODtM9V_-PyxEzhvwKNge6TcjKI01qaX5iXkaCjw",1777412314787]