[{"data":1,"prerenderedAt":693},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fmodules\u002Fencoder":3},{"id":4,"title":5,"body":6,"description":686,"extension":687,"meta":688,"navigation":62,"path":689,"seo":690,"stem":691,"__hash__":692},"content\u002Fdocs\u002Fmodules\u002Fencoder.md","Encoder Module",{"type":7,"value":8,"toc":675},"minimark",[9,13,17,22,46,133,137,145,152,163,167,172,450,454,522,526,609,613,648,652,671],[10,11,5],"h1",{"id":12},"encoder-module",[14,15,16],"p",{},"Drive a 2-pin quadrature rotary encoder. The firmware polls the A\u002FB lines, accumulates a signed tick count, and emits unsolicited tick events whenever the count changes — so the host doesn't have to poll.",[18,19,21],"h2",{"id":20},"firmware-setup","Firmware setup",[23,24,29],"pre",{"className":25,"code":26,"language":27,"meta":28,"style":28},"language-ini shiki shiki-themes github-light github-dark","; platformio.ini\nbuild_flags = -DCONDUYT_MODULE_ENCODER\n","ini","",[30,31,32,40],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,39],{},"; platformio.ini\n",[33,41,43],{"class":35,"line":42},2,[33,44,45],{},"build_flags = -DCONDUYT_MODULE_ENCODER\n",[23,47,51],{"className":48,"code":49,"language":50,"meta":28,"style":28},"language-cpp shiki shiki-themes github-light github-dark","#include \u003CConduyt.h>\n\nConduytSerial transport(Serial, 115200);\nConduytDevice device(\"EncoderBot\", \"1.0.0\", transport);\n\nvoid setup() {\n  Serial.begin(115200);\n  device.addModule(new ConduytModuleEncoder());\n  device.begin();\n}\n\nvoid loop() {\n  device.poll();\n}\n","cpp",[30,52,53,58,64,70,76,81,87,93,99,105,111,116,122,128],{"__ignoreMap":28},[33,54,55],{"class":35,"line":36},[33,56,57],{},"#include \u003CConduyt.h>\n",[33,59,60],{"class":35,"line":42},[33,61,63],{"emptyLinePlaceholder":62},true,"\n",[33,65,67],{"class":35,"line":66},3,[33,68,69],{},"ConduytSerial transport(Serial, 115200);\n",[33,71,73],{"class":35,"line":72},4,[33,74,75],{},"ConduytDevice device(\"EncoderBot\", \"1.0.0\", transport);\n",[33,77,79],{"class":35,"line":78},5,[33,80,63],{"emptyLinePlaceholder":62},[33,82,84],{"class":35,"line":83},6,[33,85,86],{},"void setup() {\n",[33,88,90],{"class":35,"line":89},7,[33,91,92],{},"  Serial.begin(115200);\n",[33,94,96],{"class":35,"line":95},8,[33,97,98],{},"  device.addModule(new ConduytModuleEncoder());\n",[33,100,102],{"class":35,"line":101},9,[33,103,104],{},"  device.begin();\n",[33,106,108],{"class":35,"line":107},10,[33,109,110],{},"}\n",[33,112,114],{"class":35,"line":113},11,[33,115,63],{"emptyLinePlaceholder":62},[33,117,119],{"class":35,"line":118},12,[33,120,121],{},"void loop() {\n",[33,123,125],{"class":35,"line":124},13,[33,126,127],{},"  device.poll();\n",[33,129,131],{"class":35,"line":130},14,[33,132,110],{},[18,134,136],{"id":135},"wiring","Wiring",[23,138,143],{"className":139,"code":141,"language":142},[140],"language-text","Encoder         Board\n─────           ─────\nA           ──► any GPIO with INPUT_PULLUP support (e.g. 2)\nB           ──► any GPIO with INPUT_PULLUP support (e.g. 3)\nGND         ──► GND\n+ (if any)  ──► 3V3 \u002F 5V depending on encoder\n","text",[30,144,141],{"__ignoreMap":28},[14,146,147,148,151],{},"The firmware enables ",[30,149,150],{},"INPUT_PULLUP"," on both pins automatically, so external pull-ups are not required for most rotary encoders. For very long wire runs you may still want them.",[14,153,154,158,159,162],{},[155,156,157],"strong",{},"Pin choice tip:"," the encoder polls inside ",[30,160,161],{},"device.poll()",", so it doesn't depend on hardware interrupts. Any digital input pin works — but if you're spinning the encoder very fast and your loop is busy, consider routing A to an interrupt-capable pin and adding an attach-interrupt fork in your firmware.",[18,164,166],{"id":165},"host-usage","Host usage",[168,169,171],"h3",{"id":170},"javascript","JavaScript",[23,173,176],{"className":174,"code":175,"language":170,"meta":28,"style":28},"language-javascript shiki shiki-themes github-light github-dark","import { ConduytDevice } from 'conduyt-js'\nimport { SerialTransport } from 'conduyt-js\u002Ftransports\u002Fserial'\nimport { ConduytEncoder } from 'conduyt-js\u002Fmodules\u002Fencoder'\n\nconst device = await ConduytDevice.connect(new SerialTransport({ path: '\u003CYOUR_PORT>' }))\nconst enc = new ConduytEncoder(device)   \u002F\u002F resolves \"encoder\" by name from HELLO_RESP\n\nawait enc.attach(2, 3)                   \u002F\u002F pinA = 2, pinB = 3\nawait enc.reset()\n\nenc.onTick((count, delta) => {\n  console.log(`count=${count}  delta=${delta}`)\n})\n\nsetInterval(async () => {\n  console.log('current count:', await enc.read())\n}, 1000)\n",[30,177,178,195,207,219,223,263,285,289,317,329,333,362,388,393,397,415,439],{"__ignoreMap":28},[33,179,180,184,188,191],{"class":35,"line":36},[33,181,183],{"class":182},"szBVR","import",[33,185,187],{"class":186},"sVt8B"," { ConduytDevice } ",[33,189,190],{"class":182},"from",[33,192,194],{"class":193},"sZZnC"," 'conduyt-js'\n",[33,196,197,199,202,204],{"class":35,"line":42},[33,198,183],{"class":182},[33,200,201],{"class":186}," { SerialTransport } ",[33,203,190],{"class":182},[33,205,206],{"class":193}," 'conduyt-js\u002Ftransports\u002Fserial'\n",[33,208,209,211,214,216],{"class":35,"line":66},[33,210,183],{"class":182},[33,212,213],{"class":186}," { ConduytEncoder } ",[33,215,190],{"class":182},[33,217,218],{"class":193}," 'conduyt-js\u002Fmodules\u002Fencoder'\n",[33,220,221],{"class":35,"line":72},[33,222,63],{"emptyLinePlaceholder":62},[33,224,225,228,232,235,238,241,245,248,251,254,257,260],{"class":35,"line":78},[33,226,227],{"class":182},"const",[33,229,231],{"class":230},"sj4cs"," device",[33,233,234],{"class":182}," =",[33,236,237],{"class":182}," await",[33,239,240],{"class":186}," ConduytDevice.",[33,242,244],{"class":243},"sScJk","connect",[33,246,247],{"class":186},"(",[33,249,250],{"class":182},"new",[33,252,253],{"class":243}," SerialTransport",[33,255,256],{"class":186},"({ path: ",[33,258,259],{"class":193},"'\u003CYOUR_PORT>'",[33,261,262],{"class":186}," }))\n",[33,264,265,267,270,272,275,278,281],{"class":35,"line":83},[33,266,227],{"class":182},[33,268,269],{"class":230}," enc",[33,271,234],{"class":182},[33,273,274],{"class":182}," new",[33,276,277],{"class":243}," ConduytEncoder",[33,279,280],{"class":186},"(device)   ",[33,282,284],{"class":283},"sJ8bj","\u002F\u002F resolves \"encoder\" by name from HELLO_RESP\n",[33,286,287],{"class":35,"line":89},[33,288,63],{"emptyLinePlaceholder":62},[33,290,291,294,297,300,302,305,308,311,314],{"class":35,"line":95},[33,292,293],{"class":182},"await",[33,295,296],{"class":186}," enc.",[33,298,299],{"class":243},"attach",[33,301,247],{"class":186},[33,303,304],{"class":230},"2",[33,306,307],{"class":186},", ",[33,309,310],{"class":230},"3",[33,312,313],{"class":186},")                   ",[33,315,316],{"class":283},"\u002F\u002F pinA = 2, pinB = 3\n",[33,318,319,321,323,326],{"class":35,"line":101},[33,320,293],{"class":182},[33,322,296],{"class":186},[33,324,325],{"class":243},"reset",[33,327,328],{"class":186},"()\n",[33,330,331],{"class":35,"line":107},[33,332,63],{"emptyLinePlaceholder":62},[33,334,335,338,341,344,348,350,353,356,359],{"class":35,"line":113},[33,336,337],{"class":186},"enc.",[33,339,340],{"class":243},"onTick",[33,342,343],{"class":186},"((",[33,345,347],{"class":346},"s4XuR","count",[33,349,307],{"class":186},[33,351,352],{"class":346},"delta",[33,354,355],{"class":186},") ",[33,357,358],{"class":182},"=>",[33,360,361],{"class":186}," {\n",[33,363,364,367,370,372,375,377,380,382,385],{"class":35,"line":118},[33,365,366],{"class":186},"  console.",[33,368,369],{"class":243},"log",[33,371,247],{"class":186},[33,373,374],{"class":193},"`count=${",[33,376,347],{"class":186},[33,378,379],{"class":193},"}  delta=${",[33,381,352],{"class":186},[33,383,384],{"class":193},"}`",[33,386,387],{"class":186},")\n",[33,389,390],{"class":35,"line":124},[33,391,392],{"class":186},"})\n",[33,394,395],{"class":35,"line":130},[33,396,63],{"emptyLinePlaceholder":62},[33,398,400,403,405,408,411,413],{"class":35,"line":399},15,[33,401,402],{"class":243},"setInterval",[33,404,247],{"class":186},[33,406,407],{"class":182},"async",[33,409,410],{"class":186}," () ",[33,412,358],{"class":182},[33,414,361],{"class":186},[33,416,418,420,422,424,427,429,431,433,436],{"class":35,"line":417},16,[33,419,366],{"class":186},[33,421,369],{"class":243},[33,423,247],{"class":186},[33,425,426],{"class":193},"'current count:'",[33,428,307],{"class":186},[33,430,293],{"class":182},[33,432,296],{"class":186},[33,434,435],{"class":243},"read",[33,437,438],{"class":186},"())\n",[33,440,442,445,448],{"class":35,"line":441},17,[33,443,444],{"class":186},"}, ",[33,446,447],{"class":230},"1000",[33,449,387],{"class":186},[168,451,453],{"id":452},"python","Python",[23,455,458],{"className":456,"code":457,"language":452,"meta":28,"style":28},"language-python shiki shiki-themes github-light github-dark","from conduyt import ConduytDevice\nfrom conduyt.transports.serial import SerialTransport\nfrom conduyt.modules import ConduytEncoder\n\ndevice = ConduytDevice(SerialTransport('\u003CYOUR_PORT>'))\nawait device.connect()\n\nenc = ConduytEncoder(device, module_id=0)\nawait enc.attach(pin_a=2, pin_b=3)\nawait enc.reset()\n\ncount = await enc.read()\nprint(f\"count = {count}\")\n",[30,459,460,465,470,475,479,484,489,493,498,503,508,512,517],{"__ignoreMap":28},[33,461,462],{"class":35,"line":36},[33,463,464],{},"from conduyt import ConduytDevice\n",[33,466,467],{"class":35,"line":42},[33,468,469],{},"from conduyt.transports.serial import SerialTransport\n",[33,471,472],{"class":35,"line":66},[33,473,474],{},"from conduyt.modules import ConduytEncoder\n",[33,476,477],{"class":35,"line":72},[33,478,63],{"emptyLinePlaceholder":62},[33,480,481],{"class":35,"line":78},[33,482,483],{},"device = ConduytDevice(SerialTransport('\u003CYOUR_PORT>'))\n",[33,485,486],{"class":35,"line":83},[33,487,488],{},"await device.connect()\n",[33,490,491],{"class":35,"line":89},[33,492,63],{"emptyLinePlaceholder":62},[33,494,495],{"class":35,"line":95},[33,496,497],{},"enc = ConduytEncoder(device, module_id=0)\n",[33,499,500],{"class":35,"line":101},[33,501,502],{},"await enc.attach(pin_a=2, pin_b=3)\n",[33,504,505],{"class":35,"line":107},[33,506,507],{},"await enc.reset()\n",[33,509,510],{"class":35,"line":113},[33,511,63],{"emptyLinePlaceholder":62},[33,513,514],{"class":35,"line":118},[33,515,516],{},"count = await enc.read()\n",[33,518,519],{"class":35,"line":124},[33,520,521],{},"print(f\"count = {count}\")\n",[18,523,525],{"id":524},"command-reference","Command reference",[527,528,529,548],"table",{},[530,531,532],"thead",{},[533,534,535,539,542,545],"tr",{},[536,537,538],"th",{},"Command",[536,540,541],{},"ID",[536,543,544],{},"Payload",[536,546,547],{},"Description",[549,550,551,570,594],"tbody",{},[533,552,553,557,562,567],{},[554,555,556],"td",{},"Attach",[554,558,559],{},[30,560,561],{},"0x01",[554,563,564],{},[30,565,566],{},"pinA(1) + pinB(1)",[554,568,569],{},"Claim two pins as A\u002FB inputs",[533,571,572,575,580,583],{},[554,573,574],{},"Read",[554,576,577],{},[30,578,579],{},"0x02",[554,581,582],{},"(none)",[554,584,585,586,589,590,593],{},"→ ",[30,587,588],{},"MOD_RESP"," with ",[30,591,592],{},"int32"," count",[533,595,596,599,604,606],{},[554,597,598],{},"Reset",[554,600,601],{},[30,602,603],{},"0x03",[554,605,582],{},[554,607,608],{},"Zero the count",[18,610,612],{"id":611},"events","Events",[527,614,615,629],{},[530,616,617],{},[533,618,619,622,624,626],{},[536,620,621],{},"Event",[536,623,541],{},[536,625,544],{},[536,627,628],{},"When",[549,630,631],{},[533,632,633,636,640,645],{},[554,634,635],{},"Tick",[554,637,638],{},[30,639,561],{},[554,641,642],{},[30,643,644],{},"int32 count + int16 delta",[554,646,647],{},"Emitted automatically on each detent \u002F step change",[18,649,651],{"id":650},"notes","Notes",[653,654,655,662,665],"ul",{},[656,657,658,659,661],"li",{},"Counts are signed ",[30,660,592],{},". Direction depends on which physical wire you call A vs B — swap them or invert in software if it counts backwards.",[656,663,664],{},"Software polling means very fast turns can drop ticks. For 600+ PPR optical encoders at high RPM, you'll want a dedicated interrupt-driven sketch.",[656,666,667,670],{},[30,668,669],{},"reset()"," zeros the count immediately; in-flight tick events still report from the new zero.",[672,673,674],"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}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":28,"searchDepth":42,"depth":42,"links":676},[677,678,679,683,684,685],{"id":20,"depth":42,"text":21},{"id":135,"depth":42,"text":136},{"id":165,"depth":42,"text":166,"children":680},[681,682],{"id":170,"depth":66,"text":171},{"id":452,"depth":66,"text":453},{"id":524,"depth":42,"text":525},{"id":611,"depth":42,"text":612},{"id":650,"depth":42,"text":651},"Quadrature rotary encoder driver with tick events and absolute count.","md",{},"\u002Fdocs\u002Fmodules\u002Fencoder",{"title":5,"description":686},"docs\u002Fmodules\u002Fencoder","bc8PLvFUWi8oa-4XOdBCT7Nyf7rdLTYSzRzMLGe-dTQ",1777412314786]