{"examples":[{"slug":"blink-and-count","title":"Blink + count","description":"Blink the on-board LED and print a running blink count over Serial.","english":"Blink the built-in LED, and count the blinks over the serial port.\n\nSet up the built-in LED pin as an output so we can turn it on and off.\nStart the serial connection at 9600 baud.\n\nKeep a counter for how many times we've blinked, starting at 0.\n\nThen, over and over, forever:\n  Turn the LED on.\n  Wait 500 milliseconds.\n  Turn the LED off.\n  Wait another 500 milliseconds.\n  Add 1 to the blink counter.\n  Print \"blink \" followed by the counter to the serial port.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup() {\n  pinMode(LED_BUILTIN, OUTPUT);\n  Serial.begin(9600);\n}\n\nint blinkCount = 0;\nvoid loop() {\n  digitalWrite(LED_BUILTIN, HIGH);\n  delay(500);\n  digitalWrite(LED_BUILTIN, LOW);\n  delay(500);\n  blinkCount++;\n  Serial.print(\"blink \");\n  Serial.println(blinkCount);\n}","links":[{"label":"setup_begin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"setup_led_output","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"setup_serial_begin","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"setup_end","code_end":4,"code_start":4,"english_end":4,"english_start":3},{"label":"global_counter","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"loop_begin","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"loop_led_on","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"loop_delay_on","code_end":9,"code_start":9,"english_end":10,"english_start":10},{"label":"loop_led_off","code_end":10,"code_start":10,"english_end":11,"english_start":11},{"label":"loop_delay_off","code_end":11,"code_start":11,"english_end":12,"english_start":12},{"label":"loop_increment","code_end":12,"code_start":12,"english_end":13,"english_start":13},{"label":"loop_print_label","code_end":13,"code_start":13,"english_end":14,"english_start":14},{"label":"loop_print_count","code_end":14,"code_start":14,"english_end":14,"english_start":14},{"label":"loop_end","code_end":15,"code_start":15,"english_end":14,"english_start":8}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":4,\"summary\":\"Configure the built-in LED as an output and start serial communication at 9600 baud.\",\"calls\":[{\"english_start\":3,\"english_end\":3},{\"english_start\":4,\"english_end\":4}]},{\"name\":\"loop\",\"params\":[],\"english_start\":8,\"english_end\":14,\"summary\":\"Blink the built-in LED forever, count each blink, and print the count over Serial.\",\"calls\":[{\"english_start\":9,\"english_end\":9},{\"english_start\":10,\"english_end\":10},{\"english_start\":11,\"english_end\":11},{\"english_start\":12,\"english_end\":12},{\"english_start\":13,\"english_end\":13},{\"english_start\":14,\"english_end\":14}]}]}"},"python":{"code":"# Built-in LED setup would be hardware-specific; this script simulates the blink.\n# Serial at 9600 baud would be configured here in hardware-specific code.\ncount = 0\nwhile True:\n    print(\"LED on\")\n    time.sleep(0.5)\n    print(\"LED off\")\n    time.sleep(0.5)\n    count += 1\n    print(f\"blink {count}\")\nimport time","links":[{"label":"comment","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"comment","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"statement","code_end":3,"code_start":3,"english_end":6,"english_start":6},{"label":"loop","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"loop_body","code_end":6,"code_start":5,"english_end":10,"english_start":9},{"label":"loop_body","code_end":8,"code_start":7,"english_end":12,"english_start":11},{"label":"statement","code_end":9,"code_start":9,"english_end":13,"english_start":13},{"label":"statement","code_end":10,"code_start":10,"english_end":14,"english_start":14},{"label":"import","code_end":11,"code_start":11,"english_end":1,"english_start":1}],"structure":"{\"functions\":[]}"},"ruby":{"code":"pinMode(LED_BUILTIN, OUTPUT)\nSerial.begin(9600)\nblink_count = 0\nloop do\n  digitalWrite(LED_BUILTIN, HIGH)\n  sleep(0.5)\n  digitalWrite(LED_BUILTIN, LOW)\n  sleep(0.5)\n  blink_count += 1\n  Serial.print(\"blink \")\n  Serial.println(blink_count)\nend","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"setup","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"setup","code_end":3,"code_start":3,"english_end":6,"english_start":6},{"label":"loop","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"loop","code_end":5,"code_start":5,"english_end":9,"english_start":9},{"label":"loop","code_end":6,"code_start":6,"english_end":10,"english_start":10},{"label":"loop","code_end":7,"code_start":7,"english_end":11,"english_start":11},{"label":"loop","code_end":8,"code_start":8,"english_end":12,"english_start":12},{"label":"loop","code_end":9,"code_start":9,"english_end":13,"english_start":13},{"label":"loop","code_end":10,"code_start":10,"english_end":14,"english_start":14},{"label":"loop","code_end":11,"code_start":11,"english_end":14,"english_start":14},{"label":"loop","code_end":12,"code_start":12,"english_end":14,"english_start":8}],"structure":"{\"functions\":[]}"},"javascript":{"code":"let blinkCount = 0;\nconst ledPin = 'built-in LED';\nconsole.log('Serial started at 9600 baud');\nconst blink = () => {\n  console.log('LED on');\n  setTimeout(() => {\n    console.log('LED off');\n    setTimeout(() => {\n      blinkCount += 1;\n      console.log(`blink ${blinkCount}`);\n      blink();\n    }, 500);\n  }, 500);\n};\n\nblink();","links":[{"label":"initialize counter","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"set up LED pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"start serial","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"begin loop","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"turn LED on","code_end":5,"code_start":5,"english_end":9,"english_start":9},{"label":"wait 500 ms","code_end":6,"code_start":6,"english_end":10,"english_start":10},{"label":"turn LED off","code_end":7,"code_start":7,"english_end":11,"english_start":11},{"label":"wait another 500 ms","code_end":8,"code_start":8,"english_end":12,"english_start":12},{"label":"increment counter","code_end":9,"code_start":9,"english_end":13,"english_start":13},{"label":"print count","code_end":10,"code_start":10,"english_end":14,"english_start":14},{"label":"repeat forever","code_end":11,"code_start":11,"english_end":14,"english_start":14},{"label":"end second wait","code_end":12,"code_start":12,"english_end":14,"english_start":14},{"label":"end first wait","code_end":13,"code_start":13,"english_end":14,"english_start":14},{"label":"end loop","code_end":14,"code_start":14,"english_end":8,"english_start":8},{"label":"start blinking","code_end":16,"code_start":16,"english_end":8,"english_start":8}],"structure":"{\"functions\":[{\"name\":\"blink\",\"params\":[],\"english_start\":8,\"english_end\":14,\"summary\":\"Runs the endless blink cycle with 500 ms delays and serial count output.\",\"calls\":[{\"english_start\":14,\"english_end\":14},{\"english_start\":10,\"english_end\":10},{\"english_start\":12,\"english_end\":12}]}]}"}}},{"slug":"distance-meter-guide","title":"Measure distance with the Uno","description":"","english":"Use an ultrasonic sensor with trigger on pin 7 and echo on pin 6.\nStart Serial at 115200 baud and use the built-in LED as an output.\nSend a ten-microsecond trigger pulse and wait up to 30 milliseconds for the echo.\nConvert the echo time into centimetres.\nAccept readings from 2 to 400 centimetres; otherwise print that the target is out of range.\nTurn on the built-in LED when a valid reading is below 15 centimetres.\nPrint each distance to Serial Monitor and wait 80 milliseconds before repeating.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"// Ultrasonic distance meter — matches the Circuit Studio example.\n// HC-SR04: VCC -> Uno 5V rail, GND -> GND rail, TRIG -> D7, ECHO -> D6.\n// Open Serial Monitor at 115200 baud. No external LED or resistor is needed.\n// Timing reference: https://littlebirdelectronics.com.au/products/ultrasonic-distance-sensor-hc-sr04\nconstexpr byte TRIG_PIN = 7;\nconstexpr byte ECHO_PIN = 6;\n\nfloat distanceCm() {\n  digitalWrite(TRIG_PIN, LOW);\n  delayMicroseconds(2);\n  digitalWrite(TRIG_PIN, HIGH);\n  delayMicroseconds(10);\n  digitalWrite(TRIG_PIN, LOW);\n  const unsigned long echo = pulseIn(ECHO_PIN, HIGH, 30000UL);\n  const float cm = echo / 58.0f;\n  return echo > 0 && cm >= 2.0f && cm <= 400.0f ? cm : -1.0f;\n}\n\nvoid setup() {\n  pinMode(TRIG_PIN, OUTPUT);\n  pinMode(ECHO_PIN, INPUT);\n  pinMode(LED_BUILTIN, OUTPUT);\n  Serial.begin(115200);\n  Serial.println(F(\"Distance in cm; built-in LED lights below 15 cm.\"));\n}\n\nvoid loop() {\n  const float cm = distanceCm();\n  digitalWrite(LED_BUILTIN, cm > 0 && cm < 15 ? HIGH : LOW);\n  if (cm < 0) Serial.println(F(\"No valid echo\"));\n  else { Serial.print(cm, 1); Serial.println(F(\" cm\")); }\n  delay(80); // More than 60 ms between measurements; avoid stale echoes.\n}\n","links":[],"structure":null}}},{"slug":"continuous-servo-control","title":"Control a continuous servo","description":"Hold-to-run control for a continuous servo, with shared serial telemetry.","english":"Use an Arduino Uno. Connect the continuous servo signal to D9, power to the USB-powered Uno 5V pin for this unloaded demonstration and ground to Uno ground. Start stopped at a 1500 microsecond neutral pulse. Read newline commands at 115200 baud: speed:-100..100, neutral:1450..1550, mode:manual, run and stop. Only run while receiving run heartbeats; stop after one second without one. Print labelled speed, pulse and ready values every 100 milliseconds. The App sends commands while Run is held.","app_html":"<style>\n:root{color-scheme:dark}*{box-sizing:border-box}body{margin:0;background:#111918;color:#e5efed;font:14px/1.5 -apple-system,BlinkMacSystemFont,system-ui,sans-serif}.panel{max-width:880px;margin:auto;padding:24px;display:grid;grid-template-columns:200px minmax(0,1fr);gap:28px}.visual{display:flex;flex-direction:column;align-items:center;justify-content:center}.visual svg{width:180px;height:180px}.muted{color:#9bafaa;font-size:12px}.visual p{text-align:center;margin:4px 0}h1{font-size:21px;letter-spacing:-.5px;margin:0 0 4px;font-weight:650}p{margin:0 0 18px}.status{font-size:12px;color:#9bafaa;margin-bottom:20px}.status.live{color:#7bdac6}.field{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:14px 0 6px}.value{font-variant-numeric:tabular-nums;font-size:24px;letter-spacing:-.6px}input[type=range]{width:100%;accent-color:#53c9b0;height:24px}.ends{display:flex;justify-content:space-between;font-size:11px;color:#93aaa3}.actions{display:flex;gap:10px;margin:20px 0 16px}button,select,input{font:inherit}button{border:1px solid #475a53;background:#283c34;color:#e8f5ef;border-radius:8px;padding:10px 16px;cursor:pointer;font-weight:600}button:disabled,input:disabled,select:disabled{opacity:.4;cursor:default}button:focus-visible,select:focus-visible,input:focus-visible,summary:focus-visible{outline:2px solid #76d7c2;outline-offset:3px}#run{flex:1;background:#a1ead7;color:#13261f;border-color:#a1ead7;user-select:none;touch-action:none}#run[aria-pressed=true]{background:#54c5a5}#stop{color:#ffb2a7;background:#452923;border-color:#805045}select,input[type=number]{background:#1c2823;color:#e3eee8;border:1px solid #40534a;border-radius:6px;padding:5px 8px}dl{display:flex;gap:24px;margin:16px 0;border-top:1px solid #2c3e35;padding-top:12px}dt{font-size:11px;color:#93aaa3}dd{margin:0;font-variant-numeric:tabular-nums}details{border-top:1px solid #2c3e35;padding-top:12px}summary{font-size:12px;color:#bad0c6;cursor:pointer}details p{font-size:12px;color:#9bafaa;margin:10px 0}#horn{transform-origin:100px 83px}.caption{font-size:10px!important;color:#7f978c}@media(max-width:580px){.panel{grid-template-columns:1fr;gap:12px;padding:18px}.visual{display:none}h1{font-size:19px}}[hidden]{display:none!important}\n</style>\n<div class=\"panel\">\n  <div class=\"visual\" aria-hidden=\"true\">\n    <svg viewBox=\"0 0 200 200\"><rect x=\"47\" y=\"72\" width=\"106\" height=\"100\" rx=\"12\" fill=\"#295daa\"/><rect x=\"32\" y=\"113\" width=\"136\" height=\"14\" rx=\"5\" fill=\"#3976c5\"/><circle cx=\"40\" cy=\"120\" r=\"3\" fill=\"#142824\"/><circle cx=\"160\" cy=\"120\" r=\"3\" fill=\"#142824\"/><circle cx=\"100\" cy=\"83\" r=\"28\" fill=\"#3c7ad0\"/><g id=\"horn\"><rect x=\"90\" y=\"32\" width=\"20\" height=\"80\" rx=\"10\" fill=\"#edf0e8\"/><circle cx=\"100\" cy=\"44\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"57\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"70\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"83\" r=\"4\" fill=\"#63777a\"/></g><text x=\"100\" y=\"152\" text-anchor=\"middle\" font-family=\"system-ui\" font-size=\"10\" fill=\"#cde2ff\">CONTINUOUS · 9g</text></svg>\n    <p id=\"motion\">Stopped</p><p class=\"caption\">Commanded rotation · not angle feedback</p>\n  </div>\n  <main>\n    <h1>Servo control</h1><p class=\"muted\">Control speed and direction. Release to stop.</p>\n    <div id=\"status\" class=\"status\" role=\"status\">Connect the Arduino using the IDE controls.</div>\n    <div id=\"mode-field\" class=\"field\" hidden><label for=\"mode\">Control</label><select id=\"mode\"><option value=\"manual\">Manual</option><option value=\"auto\">Distance sensor</option></select></div>\n    <div class=\"field\"><label for=\"speed\">Speed &amp; direction</label><output id=\"requested\" for=\"speed\" class=\"value\">0%</output></div>\n    <input id=\"speed\" type=\"range\" min=\"-100\" max=\"100\" value=\"0\" step=\"5\" disabled>\n    <div class=\"ends\"><span>Reverse</span><span>Stop</span><span>Forward</span></div>\n    <p id=\"auto-help\" class=\"muted\" hidden>Stops at 15 cm or closer. Speeds up between 15 and 60 cm. No valid echo stops rotation.</p>\n    <div class=\"actions\"><button id=\"run\" type=\"button\" aria-pressed=\"false\" disabled>Hold to run</button><button id=\"stop\" type=\"button\" disabled>Stop</button></div>\n    <dl><div><dt>Reported speed</dt><dd id=\"reported\">—</dd></div><div><dt>Pulse</dt><dd id=\"pulse\">—</dd></div><div id=\"distance-field\" hidden><dt>Distance</dt><dd id=\"distance\">—</dd></div></dl>\n    <details><summary>Neutral calibration</summary><p>With the horn unloaded, select zero speed and hold Run. If it creeps, release Run, adjust the neutral pulse slightly, then test again. Continuous servos cannot hold an exact angle.</p><label for=\"neutral\">Neutral pulse (µs)</label> <input id=\"neutral\" type=\"number\" min=\"1450\" max=\"1550\" step=\"1\" value=\"1500\" disabled></details>\n  </main>\n</div>\n<script>\n(() => {\n  const $=id=>document.getElementById(id),bridge=window.serial;\n  let ready=false,holding=false,timer=0,lastData=0,feedback=0,angle=0,raf=0,previous=0;\n  const available=()=>!!bridge?.connected&&bridge.visible!==false&&!document.hidden;\n  const send=text=>{if(bridge?.connected)bridge.send(text);};\n  function draw(now){raf=0;if(!available()||!feedback||now-lastData>1500){previous=0;return;}if(previous)angle+=(now-previous)/1000*feedback*2.4;previous=now;$('horn').style.transform=`rotate(${angle}deg)`;raf=requestAnimationFrame(draw);}\n  function resetMotion(){feedback=0;previous=0;cancelAnimationFrame(raf);raf=0;$('motion').textContent='Stopped';}\n  function stop(){holding=false;clearInterval(timer);timer=0;send('stop');$('run').setAttribute('aria-pressed','false');resetMotion();}\n  function configure(){send('mode:'+$('mode').value);send('neutral:'+$('neutral').value);send('speed:'+$('speed').value);}\n  function start(){if(holding||!ready||!available()||performance.now()-lastData>1500)return;holding=true;configure();send('run');$('run').setAttribute('aria-pressed','true');timer=setInterval(()=>{if(!available()||performance.now()-lastData>1500){stop();return;}send('run');},250);}\n  function status(){stop();ready=false;for(const id of ['run','stop','speed','neutral','mode'])$(id).disabled=true;$('status').classList.remove('live');$('status').textContent=bridge?.connected?'Waiting for the matching servo sketch…':'Connect the Arduino using the IDE controls.';}\n  $('speed').addEventListener('input',()=>{$('requested').textContent=$('speed').value+'%';if(holding)send('speed:'+$('speed').value);});\n  $('mode').addEventListener('change',()=>{stop();$('speed').disabled=$('mode').value==='auto';$('auto-help').hidden=$('mode').value!=='auto';});\n  $('neutral').addEventListener('change',()=>{stop();if(!$('neutral').checkValidity())$('neutral').value=1500;});\n  $('run').addEventListener('pointerdown',e=>{if(e.button!==0)return;e.preventDefault();e.currentTarget.setPointerCapture(e.pointerId);start();});\n  for(const event of ['pointerup','pointercancel','lostpointercapture'])$('run').addEventListener(event,stop);\n  $('run').addEventListener('keydown',e=>{if(e.code==='Space'||e.code==='Enter'){e.preventDefault();if(!e.repeat)start();}});\n  $('run').addEventListener('keyup',e=>{if(e.code==='Space'||e.code==='Enter'){e.preventDefault();stop();}});\n  $('stop').addEventListener('click',stop);addEventListener('blur',stop);addEventListener('pagehide',stop);\n  document.addEventListener('visibilitychange',()=>{if(document.hidden)stop();});\n  if(!bridge){$('status').textContent='Load this HTML in English → App → Edit HTML.';return;}\n  bridge.onStatus(status);bridge.onVisible(vis=>{if(!vis)stop();});\n  bridge.onValues(message=>{\n    const v=message.vals;if(v.ready!==1||!Number.isFinite(v.speed)||!Number.isFinite(v.pulse))return;\n    lastData=performance.now();ready=available();\n    for(const id of ['run','stop','neutral','mode'])$(id).disabled=!ready;$('speed').disabled=!ready||$('mode').value==='auto';\n    $('status').textContent=ready?'Ready · hold Run to move the servo':'Controls paused';$('status').classList.toggle('live',ready);\n    $('reported').textContent=v.speed+'%';$('pulse').textContent=v.pulse+' µs';\n    $('mode-field').hidden=$('distance-field').hidden=v.sensor!==1;$('distance').textContent=v.distance>=2?v.distance.toFixed(1)+' cm':'No echo';\n    feedback=ready?Math.max(-100,Math.min(100,v.speed)):0;$('motion').textContent=feedback>0?'Forward':feedback<0?'Reverse':'Stopped';\n    if(feedback&&!raf)raf=requestAnimationFrame(draw);if(!feedback)resetMotion();\n  });\n  status();\n})();\n</script>\n","settings":{},"by_lang":{"cpp":{"code":"// Little Bird continuous servo controller for the English IDE App.\n// Servo signal D9; red to Uno 5V (USB-powered, unloaded demonstration); brown to common GND.\n// HC-SR04 (distance version): TRIG D7, ECHO D6, VCC Uno 5V, GND common.\n// The servo is continuous rotation: speed/direction, not a position angle.\n// Neutral is unit-specific. Calibrate with an unloaded horn.\n#include <Servo.h>\n#include <stdlib.h>\n#include <string.h>\n#define HAS_DISTANCE 0\nServo drive;\nconstexpr byte SERVO_PIN=9, TRIG_PIN=7, ECHO_PIN=6;\nint neutralUs=1500, requestedSpeed=0, actualSpeed=0;\nbool automatic=false, armed=false;\nunsigned long lastKeepAlive=0, lastReading=0;\nfloat distance=-1;\nchar line[40]; byte used=0; bool overflow=false;\n\nvoid stopServo() {armed=false;actualSpeed=0;drive.writeMicroseconds(neutralUs);}\nbool number(const char* text, int lo, int hi, int& result) {\n  char* end;const long n=strtol(text,&end,10);\n  if(end==text||*end!='\\0'||n<lo||n>hi)return false;\n  result=int(n);return true;\n}\nvoid command(char* text) {\n  int value;\n  if(strcmp(text,\"stop\")==0){stopServo();return;}\n  if(strcmp(text,\"mode:manual\")==0){stopServo();automatic=false;return;}\n  if(strcmp(text,\"mode:auto\")==0&&HAS_DISTANCE){stopServo();automatic=true;return;}\n  if(strncmp(text,\"neutral:\",8)==0&&number(text+8,1450,1550,value)) {stopServo();neutralUs=value;drive.writeMicroseconds(neutralUs);return;}\n  if(strncmp(text,\"speed:\",6)==0&&number(text+6,-100,100,value)){requestedSpeed=value;return;}\n  if(strcmp(text,\"run\")==0){armed=true;lastKeepAlive=millis();}\n}\nfloat readDistance() {\n  digitalWrite(TRIG_PIN,LOW);delayMicroseconds(2);digitalWrite(TRIG_PIN,HIGH);\n  delayMicroseconds(10);digitalWrite(TRIG_PIN,LOW);\n  const unsigned long echo=pulseIn(ECHO_PIN,HIGH,30000UL);\n  const float cm=echo/58.0f;return echo&&cm>=2&&cm<=400?cm:-1;\n}\nvoid setup() {\n  drive.writeMicroseconds(neutralUs);drive.attach(SERVO_PIN);stopServo();\n  pinMode(LED_BUILTIN,OUTPUT);\n  if(HAS_DISTANCE){pinMode(TRIG_PIN,OUTPUT);pinMode(ECHO_PIN,INPUT);}\n  Serial.begin(115200);\n}\nvoid loop() {\n  while(Serial.available()) {\n    const char c=Serial.read();\n    if(c=='\\n') {if(!overflow){line[used]='\\0';command(line);}used=0;overflow=false;}\n    else if(c!='\\r'){if(used<sizeof(line)-1&&!overflow)line[used++]=c;else overflow=true;}\n  }\n  if(armed&&millis()-lastKeepAlive>1000UL)stopServo();\n  if(millis()-lastReading<100UL)return;\n  lastReading=millis();\n  if(HAS_DISTANCE)distance=readDistance();\n  actualSpeed=0;\n  if(armed)actualSpeed=automatic?(distance<=15?0:constrain(int((distance-15)*100/45),0,100)):requestedSpeed;\n  const int pulse=neutralUs+actualSpeed*250/100;drive.writeMicroseconds(pulse);\n  digitalWrite(LED_BUILTIN,actualSpeed==0?HIGH:LOW);\n  Serial.print(F(\"ready:1,speed:\"));Serial.print(actualSpeed);\n  Serial.print(F(\",pulse:\"));Serial.print(pulse);\n  Serial.print(F(\",distance:\"));Serial.print(distance,1);\n  Serial.print(F(\",sensor:\"));Serial.print(HAS_DISTANCE);\n  Serial.print(F(\",auto:\"));Serial.print(automatic?1:0);\n  Serial.print(F(\",armed:\"));Serial.println(armed?1:0);\n}\n","links":[],"structure":null}}},{"slug":"distance-controlled-servo","title":"Control a servo with distance","description":"Hold-to-run control for a continuous servo, with shared serial telemetry.","english":"Use an Arduino Uno. Connect the continuous servo signal to D9, power to the USB-powered Uno 5V pin for this unloaded demonstration and ground to Uno ground. Connect an HC-SR04: VCC to Uno 5V, GND to ground, TRIG to D7 and ECHO to D6. Start stopped at a 1500 microsecond neutral pulse. Read newline commands at 115200 baud: speed:-100..100, neutral:1450..1550, mode:manual or mode:auto, run and stop. Only run while receiving run heartbeats; stop after one second without one. Print labelled speed, pulse, distance and ready values every 100 milliseconds. The App sends commands while Run is held.","app_html":"<style>\n:root{color-scheme:dark}*{box-sizing:border-box}body{margin:0;background:#111918;color:#e5efed;font:14px/1.5 -apple-system,BlinkMacSystemFont,system-ui,sans-serif}.panel{max-width:880px;margin:auto;padding:24px;display:grid;grid-template-columns:200px minmax(0,1fr);gap:28px}.visual{display:flex;flex-direction:column;align-items:center;justify-content:center}.visual svg{width:180px;height:180px}.muted{color:#9bafaa;font-size:12px}.visual p{text-align:center;margin:4px 0}h1{font-size:21px;letter-spacing:-.5px;margin:0 0 4px;font-weight:650}p{margin:0 0 18px}.status{font-size:12px;color:#9bafaa;margin-bottom:20px}.status.live{color:#7bdac6}.field{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:14px 0 6px}.value{font-variant-numeric:tabular-nums;font-size:24px;letter-spacing:-.6px}input[type=range]{width:100%;accent-color:#53c9b0;height:24px}.ends{display:flex;justify-content:space-between;font-size:11px;color:#93aaa3}.actions{display:flex;gap:10px;margin:20px 0 16px}button,select,input{font:inherit}button{border:1px solid #475a53;background:#283c34;color:#e8f5ef;border-radius:8px;padding:10px 16px;cursor:pointer;font-weight:600}button:disabled,input:disabled,select:disabled{opacity:.4;cursor:default}button:focus-visible,select:focus-visible,input:focus-visible,summary:focus-visible{outline:2px solid #76d7c2;outline-offset:3px}#run{flex:1;background:#a1ead7;color:#13261f;border-color:#a1ead7;user-select:none;touch-action:none}#run[aria-pressed=true]{background:#54c5a5}#stop{color:#ffb2a7;background:#452923;border-color:#805045}select,input[type=number]{background:#1c2823;color:#e3eee8;border:1px solid #40534a;border-radius:6px;padding:5px 8px}dl{display:flex;gap:24px;margin:16px 0;border-top:1px solid #2c3e35;padding-top:12px}dt{font-size:11px;color:#93aaa3}dd{margin:0;font-variant-numeric:tabular-nums}details{border-top:1px solid #2c3e35;padding-top:12px}summary{font-size:12px;color:#bad0c6;cursor:pointer}details p{font-size:12px;color:#9bafaa;margin:10px 0}#horn{transform-origin:100px 83px}.caption{font-size:10px!important;color:#7f978c}@media(max-width:580px){.panel{grid-template-columns:1fr;gap:12px;padding:18px}.visual{display:none}h1{font-size:19px}}[hidden]{display:none!important}\n</style>\n<div class=\"panel\">\n  <div class=\"visual\" aria-hidden=\"true\">\n    <svg viewBox=\"0 0 200 200\"><rect x=\"47\" y=\"72\" width=\"106\" height=\"100\" rx=\"12\" fill=\"#295daa\"/><rect x=\"32\" y=\"113\" width=\"136\" height=\"14\" rx=\"5\" fill=\"#3976c5\"/><circle cx=\"40\" cy=\"120\" r=\"3\" fill=\"#142824\"/><circle cx=\"160\" cy=\"120\" r=\"3\" fill=\"#142824\"/><circle cx=\"100\" cy=\"83\" r=\"28\" fill=\"#3c7ad0\"/><g id=\"horn\"><rect x=\"90\" y=\"32\" width=\"20\" height=\"80\" rx=\"10\" fill=\"#edf0e8\"/><circle cx=\"100\" cy=\"44\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"57\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"70\" r=\"2.5\" fill=\"#687976\"/><circle cx=\"100\" cy=\"83\" r=\"4\" fill=\"#63777a\"/></g><text x=\"100\" y=\"152\" text-anchor=\"middle\" font-family=\"system-ui\" font-size=\"10\" fill=\"#cde2ff\">CONTINUOUS · 9g</text></svg>\n    <p id=\"motion\">Stopped</p><p class=\"caption\">Commanded rotation · not angle feedback</p>\n  </div>\n  <main>\n    <h1>Servo control</h1><p class=\"muted\">Control speed and direction. Release to stop.</p>\n    <div id=\"status\" class=\"status\" role=\"status\">Connect the Arduino using the IDE controls.</div>\n    <div id=\"mode-field\" class=\"field\" hidden><label for=\"mode\">Control</label><select id=\"mode\"><option value=\"manual\">Manual</option><option value=\"auto\">Distance sensor</option></select></div>\n    <div class=\"field\"><label for=\"speed\">Speed &amp; direction</label><output id=\"requested\" for=\"speed\" class=\"value\">0%</output></div>\n    <input id=\"speed\" type=\"range\" min=\"-100\" max=\"100\" value=\"0\" step=\"5\" disabled>\n    <div class=\"ends\"><span>Reverse</span><span>Stop</span><span>Forward</span></div>\n    <p id=\"auto-help\" class=\"muted\" hidden>Stops at 15 cm or closer. Speeds up between 15 and 60 cm. No valid echo stops rotation.</p>\n    <div class=\"actions\"><button id=\"run\" type=\"button\" aria-pressed=\"false\" disabled>Hold to run</button><button id=\"stop\" type=\"button\" disabled>Stop</button></div>\n    <dl><div><dt>Reported speed</dt><dd id=\"reported\">—</dd></div><div><dt>Pulse</dt><dd id=\"pulse\">—</dd></div><div id=\"distance-field\" hidden><dt>Distance</dt><dd id=\"distance\">—</dd></div></dl>\n    <details><summary>Neutral calibration</summary><p>With the horn unloaded, select zero speed and hold Run. If it creeps, release Run, adjust the neutral pulse slightly, then test again. Continuous servos cannot hold an exact angle.</p><label for=\"neutral\">Neutral pulse (µs)</label> <input id=\"neutral\" type=\"number\" min=\"1450\" max=\"1550\" step=\"1\" value=\"1500\" disabled></details>\n  </main>\n</div>\n<script>\n(() => {\n  const $=id=>document.getElementById(id),bridge=window.serial;\n  let ready=false,holding=false,timer=0,lastData=0,feedback=0,angle=0,raf=0,previous=0;\n  const available=()=>!!bridge?.connected&&bridge.visible!==false&&!document.hidden;\n  const send=text=>{if(bridge?.connected)bridge.send(text);};\n  function draw(now){raf=0;if(!available()||!feedback||now-lastData>1500){previous=0;return;}if(previous)angle+=(now-previous)/1000*feedback*2.4;previous=now;$('horn').style.transform=`rotate(${angle}deg)`;raf=requestAnimationFrame(draw);}\n  function resetMotion(){feedback=0;previous=0;cancelAnimationFrame(raf);raf=0;$('motion').textContent='Stopped';}\n  function stop(){holding=false;clearInterval(timer);timer=0;send('stop');$('run').setAttribute('aria-pressed','false');resetMotion();}\n  function configure(){send('mode:'+$('mode').value);send('neutral:'+$('neutral').value);send('speed:'+$('speed').value);}\n  function start(){if(holding||!ready||!available()||performance.now()-lastData>1500)return;holding=true;configure();send('run');$('run').setAttribute('aria-pressed','true');timer=setInterval(()=>{if(!available()||performance.now()-lastData>1500){stop();return;}send('run');},250);}\n  function status(){stop();ready=false;for(const id of ['run','stop','speed','neutral','mode'])$(id).disabled=true;$('status').classList.remove('live');$('status').textContent=bridge?.connected?'Waiting for the matching servo sketch…':'Connect the Arduino using the IDE controls.';}\n  $('speed').addEventListener('input',()=>{$('requested').textContent=$('speed').value+'%';if(holding)send('speed:'+$('speed').value);});\n  $('mode').addEventListener('change',()=>{stop();$('speed').disabled=$('mode').value==='auto';$('auto-help').hidden=$('mode').value!=='auto';});\n  $('neutral').addEventListener('change',()=>{stop();if(!$('neutral').checkValidity())$('neutral').value=1500;});\n  $('run').addEventListener('pointerdown',e=>{if(e.button!==0)return;e.preventDefault();e.currentTarget.setPointerCapture(e.pointerId);start();});\n  for(const event of ['pointerup','pointercancel','lostpointercapture'])$('run').addEventListener(event,stop);\n  $('run').addEventListener('keydown',e=>{if(e.code==='Space'||e.code==='Enter'){e.preventDefault();if(!e.repeat)start();}});\n  $('run').addEventListener('keyup',e=>{if(e.code==='Space'||e.code==='Enter'){e.preventDefault();stop();}});\n  $('stop').addEventListener('click',stop);addEventListener('blur',stop);addEventListener('pagehide',stop);\n  document.addEventListener('visibilitychange',()=>{if(document.hidden)stop();});\n  if(!bridge){$('status').textContent='Load this HTML in English → App → Edit HTML.';return;}\n  bridge.onStatus(status);bridge.onVisible(vis=>{if(!vis)stop();});\n  bridge.onValues(message=>{\n    const v=message.vals;if(v.ready!==1||!Number.isFinite(v.speed)||!Number.isFinite(v.pulse))return;\n    lastData=performance.now();ready=available();\n    for(const id of ['run','stop','neutral','mode'])$(id).disabled=!ready;$('speed').disabled=!ready||$('mode').value==='auto';\n    $('status').textContent=ready?'Ready · hold Run to move the servo':'Controls paused';$('status').classList.toggle('live',ready);\n    $('reported').textContent=v.speed+'%';$('pulse').textContent=v.pulse+' µs';\n    $('mode-field').hidden=$('distance-field').hidden=v.sensor!==1;$('distance').textContent=v.distance>=2?v.distance.toFixed(1)+' cm':'No echo';\n    feedback=ready?Math.max(-100,Math.min(100,v.speed)):0;$('motion').textContent=feedback>0?'Forward':feedback<0?'Reverse':'Stopped';\n    if(feedback&&!raf)raf=requestAnimationFrame(draw);if(!feedback)resetMotion();\n  });\n  status();\n})();\n</script>\n","settings":{},"by_lang":{"cpp":{"code":"// Little Bird continuous servo controller for the English IDE App.\n// Servo signal D9; red to Uno 5V (USB-powered, unloaded demonstration); brown to common GND.\n// HC-SR04 (distance version): TRIG D7, ECHO D6, VCC Uno 5V, GND common.\n// The servo is continuous rotation: speed/direction, not a position angle.\n// Neutral is unit-specific. Calibrate with an unloaded horn.\n#include <Servo.h>\n#include <stdlib.h>\n#include <string.h>\n#define HAS_DISTANCE 1\nServo drive;\nconstexpr byte SERVO_PIN=9, TRIG_PIN=7, ECHO_PIN=6;\nint neutralUs=1500, requestedSpeed=0, actualSpeed=0;\nbool automatic=false, armed=false;\nunsigned long lastKeepAlive=0, lastReading=0;\nfloat distance=-1;\nchar line[40]; byte used=0; bool overflow=false;\n\nvoid stopServo() {armed=false;actualSpeed=0;drive.writeMicroseconds(neutralUs);}\nbool number(const char* text, int lo, int hi, int& result) {\n  char* end;const long n=strtol(text,&end,10);\n  if(end==text||*end!='\\0'||n<lo||n>hi)return false;\n  result=int(n);return true;\n}\nvoid command(char* text) {\n  int value;\n  if(strcmp(text,\"stop\")==0){stopServo();return;}\n  if(strcmp(text,\"mode:manual\")==0){stopServo();automatic=false;return;}\n  if(strcmp(text,\"mode:auto\")==0&&HAS_DISTANCE){stopServo();automatic=true;return;}\n  if(strncmp(text,\"neutral:\",8)==0&&number(text+8,1450,1550,value)) {stopServo();neutralUs=value;drive.writeMicroseconds(neutralUs);return;}\n  if(strncmp(text,\"speed:\",6)==0&&number(text+6,-100,100,value)){requestedSpeed=value;return;}\n  if(strcmp(text,\"run\")==0){armed=true;lastKeepAlive=millis();}\n}\nfloat readDistance() {\n  digitalWrite(TRIG_PIN,LOW);delayMicroseconds(2);digitalWrite(TRIG_PIN,HIGH);\n  delayMicroseconds(10);digitalWrite(TRIG_PIN,LOW);\n  const unsigned long echo=pulseIn(ECHO_PIN,HIGH,30000UL);\n  const float cm=echo/58.0f;return echo&&cm>=2&&cm<=400?cm:-1;\n}\nvoid setup() {\n  drive.writeMicroseconds(neutralUs);drive.attach(SERVO_PIN);stopServo();\n  pinMode(LED_BUILTIN,OUTPUT);\n  if(HAS_DISTANCE){pinMode(TRIG_PIN,OUTPUT);pinMode(ECHO_PIN,INPUT);}\n  Serial.begin(115200);\n}\nvoid loop() {\n  while(Serial.available()) {\n    const char c=Serial.read();\n    if(c=='\\n') {if(!overflow){line[used]='\\0';command(line);}used=0;overflow=false;}\n    else if(c!='\\r'){if(used<sizeof(line)-1&&!overflow)line[used++]=c;else overflow=true;}\n  }\n  if(armed&&millis()-lastKeepAlive>1000UL)stopServo();\n  if(millis()-lastReading<100UL)return;\n  lastReading=millis();\n  if(HAS_DISTANCE)distance=readDistance();\n  actualSpeed=0;\n  if(armed)actualSpeed=automatic?(distance<=15?0:constrain(int((distance-15)*100/45),0,100)):requestedSpeed;\n  const int pulse=neutralUs+actualSpeed*250/100;drive.writeMicroseconds(pulse);\n  digitalWrite(LED_BUILTIN,actualSpeed==0?HIGH:LOW);\n  Serial.print(F(\"ready:1,speed:\"));Serial.print(actualSpeed);\n  Serial.print(F(\",pulse:\"));Serial.print(pulse);\n  Serial.print(F(\",distance:\"));Serial.print(distance,1);\n  Serial.print(F(\",sensor:\"));Serial.print(HAS_DISTANCE);\n  Serial.print(F(\",auto:\"));Serial.print(automatic?1:0);\n  Serial.print(F(\",armed:\"));Serial.println(armed?1:0);\n}\n","links":[],"structure":null}}},{"slug":"ctc-shield-live-monitor","title":"Mirror your Crack the Code shield","description":"Send the real knob, light sensor, buttons and output states to the shield viewer.","english":"Use the Crack the Code shield on an Arduino Uno. Leave the traffic-light module disconnected. Set D6 and D7 as inputs and D8 through D13 as LED outputs. Read the knob on A5 and the light sensor on A4. On startup, light each LED in turn for six seconds and play one brief beep on D3. Then use the knob to choose how many LEDs are lit. Every quarter of a second, report the input readings, the actual LED bit mask and buzzer frequency over serial at 9600 baud. Include ctc:1 in every report so the viewer recognises this program.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"// Crack the Code hardware acceptance check, Arduino Uno.\n// Disconnect the traffic-light module: D6 must be an input for this check.\nconst byte leds[] = {8, 9, 10, 11, 12, 13};\nunsigned long started, lastReport;\nbyte ledMask=0;\nunsigned int toneHz=0;\nvoid setup() {\n  Serial.begin(9600);\n  pinMode(6, INPUT); pinMode(7, INPUT);\n  for (byte i=0; i<6; ++i) pinMode(leds[i], OUTPUT);\n  pinMode(3, OUTPUT);\n  started=millis(); lastReport=0;\n  Serial.println(F(\"CTC_DIAGNOSTIC_V1: A5 knob, A4 light, D6/D7 buttons\"));\n}\nvoid loop() {\n  const unsigned long elapsed=millis()-started;\n  ledMask=0;\n  if (elapsed<6000) {\n    const byte index=(elapsed/500)%6;\n    for (byte i=0;i<6;++i) {\n      const bool lit=i==index; digitalWrite(leds[i],lit);\n      if(lit) ledMask |= (1 << i);\n    }\n  } else {\n    const int count=map(analogRead(A5),0,1023,0,6);\n    for (byte i=0;i<6;++i) {\n      const bool lit=i<count; digitalWrite(leds[i],lit);\n      if(lit) ledMask |= (1 << i);\n    }\n  }\n  const unsigned int nextTone=elapsed>=6000 && elapsed<6150 ? 880 : 0;\n  if(nextTone!=toneHz) {\n    toneHz=nextTone;\n    if(toneHz) tone(3,toneHz); else noTone(3);\n  }\n  if(millis()-lastReport>=250) {\n    lastReport=millis();\n    Serial.print(F(\"ctc:1,ms:\"));Serial.print(elapsed);\n    Serial.print(F(\",A5:\"));Serial.print(analogRead(A5));\n    Serial.print(F(\",A4:\"));Serial.print(analogRead(A4));\n    Serial.print(F(\",D7:\"));Serial.print(digitalRead(7));\n    Serial.print(F(\",D6:\"));Serial.print(digitalRead(6));\n    Serial.print(F(\",LEDmask:\"));Serial.print(ledMask);\n    Serial.print(F(\",toneHz:\"));Serial.println(toneHz);\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-first-blink","title":"Your first blink","description":"","english":"Use the Crack the Code LED on digital pin 13. Set it as an output. Forever: turn it on, wait 1000 milliseconds, turn it off, and wait another 1000 milliseconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte ledPin = 13;\nvoid setup() {\n  pinMode(ledPin, OUTPUT);\n}\nvoid loop() {\n  digitalWrite(ledPin, HIGH);\n  delay(1000);\n  digitalWrite(ledPin, LOW);\n  delay(1000);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-getting-flashy","title":"Make your own light rhythm","description":"","english":"Set the LED on digital pin 12 as an output. Forever: turn it on for 150 milliseconds, then off for 850 milliseconds. Keep the two times named so they are easy to change.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte ledPin = 12;\nconst unsigned int onTime = 150;\nconst unsigned int offTime = 850;\nvoid setup() { pinMode(ledPin, OUTPUT); }\nvoid loop() {\n  digitalWrite(ledPin, HIGH);\n  delay(onTime);\n  digitalWrite(ledPin, LOW);\n  delay(offTime);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-alternating-lights","title":"Two lights, one sequence","description":"","english":"Make digital pins 13 and 8 outputs. Forever: turn 13 on and 8 off; wait half a second. Turn 13 off and 8 on; wait half a second.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte firstLed = 13;\nconst byte secondLed = 8;\nvoid setup() {\n  pinMode(firstLed, OUTPUT);\n  pinMode(secondLed, OUTPUT);\n}\nvoid loop() {\n  digitalWrite(firstLed, HIGH);\n  digitalWrite(secondLed, LOW);\n  delay(500);\n  digitalWrite(firstLed, LOW);\n  digitalWrite(secondLed, HIGH);\n  delay(500);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-read-the-knob","title":"Read the knob","description":"","english":"Start serial at 9600 baud. Every 50 milliseconds read the knob on A5. Estimate its voltage by multiplying the reading by 5.0 and dividing by 1023. Print labelled knob and volts values.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte potPin = A5;\nvoid setup() { Serial.begin(9600); }\nvoid loop() {\n  int reading = analogRead(potPin);\n  float volts = reading * 5.0 / 1023.0;\n  Serial.print(\"knob:\");\n  Serial.print(reading);\n  Serial.print(\",volts:\");\n  Serial.println(volts, 2);\n  delay(50);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-light-dimmer","title":"Turn the knob, dim the light","description":"","english":"Set digital pin 9 as an output and start serial at 9600 baud. Repeatedly read A5, map its 0–1023 reading to brightness 0–255, write that brightness to pin 9, print both numbers, and wait 25 milliseconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte potPin = A5;\nconst byte ledPin = 9;\nvoid setup() {\n  pinMode(ledPin, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  int reading = analogRead(potPin);\n  int brightness = map(reading, 0, 1023, 0, 255);\n  analogWrite(ledPin, brightness);\n  Serial.print(\"knob:\"); Serial.print(reading);\n  Serial.print(\",brightness:\"); Serial.println(brightness);\n  delay(25);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-knob-led-bouncer","title":"Bounce between two lights","description":"","english":"Make pins 8 and 13 outputs; start serial at 9600 baud. Begin with the low-end LED selected. Read A5 repeatedly. At 50 or below select pin 8; at 973 or above select pin 13. Between those thresholds keep the previous selection. Light only the selected LED, print the reading, and wait 25 milliseconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte potPin = A5;\nconst byte lowLed = 8;\nconst byte highLed = 13;\nbool highSelected = false;\nvoid setup() {\n  pinMode(lowLed, OUTPUT);\n  pinMode(highLed, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  int reading = analogRead(potPin);\n  if (reading <= 50) highSelected = false;\n  else if (reading >= 973) highSelected = true;\n  digitalWrite(lowLed, highSelected ? LOW : HIGH);\n  digitalWrite(highLed, highSelected ? HIGH : LOW);\n  Serial.print(\"knob:\"); Serial.println(reading);\n  delay(25);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-read-light","title":"Measure changing light","description":"","english":"Start serial at 9600 baud. Repeatedly read the light sensor on A4, print the number with label light, and wait 100 milliseconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte lightPin = A4;\nvoid setup() { Serial.begin(9600); }\nvoid loop() {\n  int reading = analogRead(lightPin);\n  Serial.print(\"light:\"); Serial.println(reading);\n  delay(100);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-automatic-night-light","title":"Build an automatic night light","description":"","english":"Use the light sensor on A4 and LED on digital pin 10. Replace darkReading and brightReading with your measured covered and bright values. Start serial at 9600 baud and make pin 10 an output. Repeatedly map the sensor reading between those endpoints to 0–100 and clamp it. Below 40 turn the light on; above 60 turn it off; otherwise keep its state. Print raw, level and lamp, then wait 50 milliseconds. If calibration endpoints are equal, leave the light off and print a correction message.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte lightPin = A4;\nconst byte ledPin = 10;\n// Replace both values with your covered and bright readings from Read changing light.\nconst int darkReading = 150;\nconst int brightReading = 800;\nbool lightOn = false;\nvoid setup() {\n  pinMode(ledPin, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  int reading = analogRead(lightPin);\n  if (darkReading == brightReading) {\n    digitalWrite(ledPin, LOW);\n    Serial.println(\"Choose two different calibration readings.\");\n    delay(500);\n    return;\n  }\n  int level = constrain(map(reading, darkReading, brightReading, 0, 100), 0, 100);\n  if (level < 40) lightOn = true;\n  else if (level > 60) lightOn = false;\n  digitalWrite(ledPin, lightOn ? HIGH : LOW);\n  Serial.print(\"raw:\"); Serial.print(reading);\n  Serial.print(\",level:\"); Serial.print(level);\n  Serial.print(\",lamp:\"); Serial.println(lightOn ? 100 : 0);\n  delay(50);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-button-basics","title":"Press to light","description":"","english":"Set button pin 7 as an input and LED pin 12 as an output. Start serial at 9600 baud. Repeatedly read whether pin 7 is HIGH. Light pin 12 while pressed and turn it off otherwise. Print pressed as 1 or 0, then wait 20 milliseconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte buttonPin = 7;\nconst byte ledPin = 12;\nvoid setup() {\n  pinMode(buttonPin, INPUT);\n  pinMode(ledPin, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  bool pressed = digitalRead(buttonPin) == HIGH;\n  digitalWrite(ledPin, pressed ? HIGH : LOW);\n  Serial.print(\"pressed:\"); Serial.println(pressed ? 1 : 0);\n  delay(20);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-toggle-button","title":"Make a button remember","description":"","english":"Use the Crack the Code Shield's button on pin 7 and LED on pin 12.\n Set pin 7 to INPUT: this board reads HIGH when its button is pressed. Set pin 12 to OUTPUT and start with its LED off. Start serial at 9600 baud.\n Keep a raw button reading, a stable button reading, the time the raw reading last changed, and an LED state.\n Repeatedly read the button. Whenever the raw reading changes, restart a 25 millisecond stability timer.\n Accept the new stable state only after it has stayed unchanged for 25 milliseconds.\n On an accepted change from released to pressed, invert the LED state, update pin 12, and print whether it is on or off.\n A held button and an accepted release must not toggle the LED. Do not block the loop with a long delay.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 7;\nconst unsigned long DEBOUNCE_MS = 25;\nbool rawButton = false;\nbool stableButton = false;\nunsigned long rawChangedAt = 0;\n\nbool newPress(unsigned long now) {\n  const bool reading = digitalRead(BUTTON_PIN) == HIGH;\n  if (reading != rawButton) {\n    rawButton = reading;\n    rawChangedAt = now;\n  }\n  if (now - rawChangedAt >= DEBOUNCE_MS && stableButton != rawButton) {\n    stableButton = rawButton;\n    return stableButton;\n  }\n  return false;\n}\n\nconst byte LED_PIN = 12;\nbool ledOn = false;\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  pinMode(LED_PIN, OUTPUT);\n  digitalWrite(LED_PIN, LOW);\n  Serial.begin(9600);\n}\nvoid loop() {\n  if (newPress(millis())) {\n    ledOn = !ledOn;\n    digitalWrite(LED_PIN, ledOn ? HIGH : LOW);\n    Serial.println(ledOn ? F(\"LED on\") : F(\"LED off\"));\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-buzzer-basics","title":"Give the shield a voice","description":"","english":"Use the Crack the Code Shield's piezo buzzer on digital pin 3 and its LED on pin 12.\n Configure both pins as outputs.\n Define a beep function that lights the LED, starts a tone at its supplied frequency for 120 milliseconds, waits for that note to finish, stops the tone, turns the LED off, and waits silently for 80 milliseconds.\n Forever, play one beep at 440 hertz and one beep at 660 hertz. Then wait silently for 800 milliseconds before the next pair.\n The note duration and silent gap are separate settings. The LED shows exactly when each note sounds.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUZZER_PIN = 3;\nconst byte LED_PIN = 12;\nconst unsigned int NOTE_MS = 120;\nconst unsigned int GAP_MS = 80;\nvoid beep(unsigned int frequency) {\n  digitalWrite(LED_PIN, HIGH);\n  tone(BUZZER_PIN, frequency, NOTE_MS);\n  delay(NOTE_MS);\n  noTone(BUZZER_PIN);\n  digitalWrite(LED_PIN, LOW);\n  delay(GAP_MS);\n}\nvoid setup() {\n  pinMode(BUZZER_PIN, OUTPUT);\n  pinMode(LED_PIN, OUTPUT);\n}\nvoid loop() {\n  beep(440);\n  beep(660);\n  delay(800);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-pitch-changer","title":"Turn the dial to bend a note","description":"","english":"Read the Crack the Code Shield potentiometer on A5. Its button is pin 7, active HIGH with INPUT mode, and its buzzer is pin 3.\n Start serial at 9600 baud. Map each analog reading from 0–1023 into a tone frequency from 200–2000 hertz.\n While the D7 button is held, sound the selected frequency. Change the running tone only when its frequency changes.\n On release, stop the tone immediately.\n Every 100 milliseconds print the raw dial reading, selected frequency, and whether the sound is playing. Keep checking the inputs between reports.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte POT_PIN = A5;\nconst byte BUTTON_PIN = 7;\nconst byte BUZZER_PIN = 3;\nint playingHz = 0;\nunsigned long lastReport = 0;\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  pinMode(BUZZER_PIN, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  const int raw = analogRead(POT_PIN);\n  const int selectedHz = map(raw, 0, 1023, 200, 2000);\n  const bool pressed = digitalRead(BUTTON_PIN) == HIGH;\n  if (pressed && selectedHz != playingHz) {\n    tone(BUZZER_PIN, selectedHz);\n    playingHz = selectedHz;\n  } else if (!pressed && playingHz != 0) {\n    noTone(BUZZER_PIN);\n    playingHz = 0;\n  }\n  const unsigned long now = millis();\n  if (now - lastReport >= 100) {\n    lastReport = now;\n    Serial.print(F(\"dial:\")); Serial.print(raw);\n    Serial.print(F(\",frequency:\")); Serial.print(selectedHz);\n    Serial.print(F(\",playing:\")); Serial.println(pressed ? 1 : 0);\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-play-a-song","title":"Compose a tiny tune","description":"","english":"Use D3 for the Crack the Code buzzer and D7 as an active-high INPUT button. Debounce the button for 25 milliseconds.\n Store this original melody as frequencies: 262, 330, 392, 440, 0, 392, 330, 294, 262. Zero means a rest.\n Store matching note lengths in milliseconds: 180, 180, 240, 120, 120, 180, 180, 180, 420.\n On a new press, if no tune is playing, start at the first note.\n Play each nonzero note for 85 percent of its allotted time, leaving a short articulation gap. A rest remains silent for its whole time.\n Use elapsed time to advance through the matching lists without freezing button checks. Stop after the final note. Ignore new presses during a tune and require another fresh press to replay it.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 7;\nconst unsigned long DEBOUNCE_MS = 25;\nbool rawButton = false;\nbool stableButton = false;\nunsigned long rawChangedAt = 0;\n\nbool newPress(unsigned long now) {\n  const bool reading = digitalRead(BUTTON_PIN) == HIGH;\n  if (reading != rawButton) {\n    rawButton = reading;\n    rawChangedAt = now;\n  }\n  if (now - rawChangedAt >= DEBOUNCE_MS && stableButton != rawButton) {\n    stableButton = rawButton;\n    return stableButton;\n  }\n  return false;\n}\n\nconst byte BUZZER_PIN = 3;\nconst unsigned int notes[] = {262, 330, 392, 440, 0, 392, 330, 294, 262};\nconst unsigned int lengths[] = {180, 180, 240, 120, 120, 180, 180, 180, 420};\nconst byte NOTE_COUNT = sizeof(notes) / sizeof(notes[0]);\nstatic_assert(NOTE_COUNT == sizeof(lengths) / sizeof(lengths[0]), \"Match every note with a length\");\nbool playing = false;\nbyte noteIndex = 0;\nunsigned long noteStartedAt = 0;\nvoid startNote(unsigned long now) {\n  noteStartedAt = now;\n  noTone(BUZZER_PIN);\n  if (notes[noteIndex] != 0) {\n    tone(BUZZER_PIN, notes[noteIndex], lengths[noteIndex] * 85UL / 100);\n  }\n}\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  pinMode(BUZZER_PIN, OUTPUT);\n}\nvoid loop() {\n  const unsigned long now = millis();\n  const bool pressed = newPress(now);\n  if (pressed && !playing) {\n    playing = true;\n    noteIndex = 0;\n    startNote(now);\n  }\n  if (playing && now - noteStartedAt >= lengths[noteIndex]) {\n    ++noteIndex;\n    if (noteIndex >= NOTE_COUNT) {\n      playing = false;\n      noTone(BUZZER_PIN);\n    } else {\n      startNote(now);\n    }\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-electronic-dice","title":"Roll an electronic die","description":"","english":"Use the six Crack the Code LEDs on pins 8 through 13, its active-high button on D7, dial on A5 and buzzer on D3.\n Debounce D7 for 25 milliseconds. A new press starts a roll only when no roll is in progress.\n On the first accepted press, seed the pseudo-random generator with the user's press timing and dial reading.\n At the start of each roll, map the dial reading to a roll duration of 600–2400 milliseconds and remember it until that roll ends.\n Chase one lit LED through pins 8–13. Slow the chase gradually during the roll and make a short click-like beep at each change.\n At the end choose a pseudo-random integer from 1 through 6. Keep only its corresponding LED lit: D8 means one, D9 two, through D13 six. Sound a final beep and print the result at 9600 baud.\n Ignore presses during a roll. A held button must not start repeated rolls.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 7;\nconst unsigned long DEBOUNCE_MS = 25;\nbool rawButton = false;\nbool stableButton = false;\nunsigned long rawChangedAt = 0;\n\nbool newPress(unsigned long now) {\n  const bool reading = digitalRead(BUTTON_PIN) == HIGH;\n  if (reading != rawButton) {\n    rawButton = reading;\n    rawChangedAt = now;\n  }\n  if (now - rawChangedAt >= DEBOUNCE_MS && stableButton != rawButton) {\n    stableButton = rawButton;\n    return stableButton;\n  }\n  return false;\n}\n\nconst byte LED_PINS[] = {8, 9, 10, 11, 12, 13};\nconst byte BUZZER_PIN = 3;\nconst byte POT_PIN = A5;\nbool seeded = false;\nbool rolling = false;\nbyte chaseIndex = 0;\nunsigned long rollStartedAt = 0;\nunsigned long lastFrameAt = 0;\nunsigned long rollDuration = 0;\nvoid showOne(byte index) {\n  for (byte i = 0; i < 6; ++i) digitalWrite(LED_PINS[i], i == index ? HIGH : LOW);\n}\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  pinMode(BUZZER_PIN, OUTPUT);\n  for (byte i = 0; i < 6; ++i) pinMode(LED_PINS[i], OUTPUT);\n  Serial.begin(9600);\n  Serial.println(F(\"Press D7 to roll. D8=1 through D13=6.\"));\n}\nvoid loop() {\n  const unsigned long now = millis();\n  if (newPress(now) && !rolling) {\n    if (!seeded) {\n      randomSeed(micros() ^ (static_cast<unsigned long>(analogRead(POT_PIN)) << 10));\n      seeded = true;\n    }\n    rollDuration = map(analogRead(POT_PIN), 0, 1023, 600, 2400);\n    rollStartedAt = lastFrameAt = now;\n    chaseIndex = 0;\n    rolling = true;\n    showOne(chaseIndex);\n    tone(BUZZER_PIN, 700, 18);\n  }\n  if (!rolling) return;\n  const unsigned long elapsed = now - rollStartedAt;\n  if (elapsed >= rollDuration) {\n    const byte result = random(1, 7);\n    rolling = false;\n    showOne(result - 1);\n    tone(BUZZER_PIN, 800 + result * 70, 110);\n    Serial.print(F(\"Roll:\")); Serial.println(result);\n    return;\n  }\n  const unsigned long frameInterval = 35 + elapsed * 110UL / rollDuration;\n  if (now - lastFrameAt >= frameInterval) {\n    lastFrameAt = now;\n    chaseIndex = (chaseIndex + 1) % 6;\n    showOne(chaseIndex);\n    tone(BUZZER_PIN, 700, 18);\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-buzzing-light-meter","title":"Hear and see the light level","description":"","english":"Use the Crack the Code light sensor on A4, six LEDs on D8–D13, buzzer on D3 and active-high INPUT button on D7.\n Start serial at 9600 baud and debounce D7 for 25 milliseconds.\n At startup flash D8 and ask the learner to cover the sensor, then press D7. Average 16 readings to save the dark endpoint.\n Next flash D13 and ask the learner to uncover the sensor under ordinary room light, then press D7. Average 16 readings to save the bright endpoint. If the endpoints differ by fewer than 30 ADC counts, stay in this stage and ask for a clearer contrast.\n Scale readings between the measured dark and bright endpoints to 0–100 percent, even if the raw direction is reversed, and clamp outside that range.\n Light zero to six LEDs as a bar. Keep them steady while measuring. Use short 650 hertz beeps with an interval from 900 milliseconds in darkness to 120 milliseconds at the bright endpoint.\n Report raw reading, relative light percent and lit LED count. Press Reset to calibrate again. This is a relative meter, not a measurement in lux.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 7;\nconst unsigned long DEBOUNCE_MS = 25;\nbool rawButton = false;\nbool stableButton = false;\nunsigned long rawChangedAt = 0;\n\nbool newPress(unsigned long now) {\n  const bool reading = digitalRead(BUTTON_PIN) == HIGH;\n  if (reading != rawButton) {\n    rawButton = reading;\n    rawChangedAt = now;\n  }\n  if (now - rawChangedAt >= DEBOUNCE_MS && stableButton != rawButton) {\n    stableButton = rawButton;\n    return stableButton;\n  }\n  return false;\n}\n\nconst byte LDR_PIN = A4;\nconst byte BUZZER_PIN = 3;\nconst byte LED_PINS[] = {8, 9, 10, 11, 12, 13};\nbyte stage = 0; // 0: capture dark; 1: capture bright; 2: measure\nint darkReading = 0;\nint brightReading = 1023;\nunsigned long lastSampleAt = 0;\nunsigned long lastBeepAt = 0;\nunsigned long lastReportAt = 0;\nint averagedLight() {\n  long total = 0;\n  for (byte i = 0; i < 16; ++i) total += analogRead(LDR_PIN);\n  return total / 16;\n}\nvoid showBar(byte count) {\n  for (byte i = 0; i < 6; ++i) digitalWrite(LED_PINS[i], i < count ? HIGH : LOW);\n}\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  pinMode(BUZZER_PIN, OUTPUT);\n  for (byte i = 0; i < 6; ++i) pinMode(LED_PINS[i], OUTPUT);\n  Serial.begin(9600);\n  Serial.println(F(\"Cover A4 light sensor, then press D7 to save dark.\"));\n}\nvoid loop() {\n  const unsigned long now = millis();\n  const bool pressed = newPress(now);\n  if (stage < 2) {\n    showBar(0);\n    digitalWrite(LED_PINS[stage == 0 ? 0 : 5], (now / 250) % 2 ? HIGH : LOW);\n    if (!pressed) return;\n    if (stage == 0) {\n      darkReading = averagedLight();\n      stage = 1;\n      Serial.print(F(\"Dark:\")); Serial.println(darkReading);\n      Serial.println(F(\"Uncover in room light, then press D7 to save bright.\"));\n    } else {\n      brightReading = averagedLight();\n      if (abs(brightReading - darkReading) < 30) {\n        Serial.println(F(\"Too little contrast. Change the light and press D7 again.\"));\n        return;\n      }\n      stage = 2;\n      Serial.print(F(\"Bright:\")); Serial.println(brightReading);\n      Serial.println(F(\"Measuring relative light. Reset to recalibrate.\"));\n    }\n    return;\n  }\n  if (now - lastSampleAt < 40) return;\n  lastSampleAt = now;\n  const int raw = averagedLight();\n  const int percent = constrain(map(raw, darkReading, brightReading, 0, 100), 0, 100);\n  const byte count = map(percent, 0, 100, 0, 6);\n  showBar(count);\n  const unsigned long interval = map(percent, 0, 100, 900, 120);\n  if (now - lastBeepAt >= interval) {\n    lastBeepAt = now;\n    tone(BUZZER_PIN, 650, 35);\n  }\n  if (now - lastReportAt >= 120) {\n    lastReportAt = now;\n    Serial.print(F(\"raw:\")); Serial.print(raw);\n    Serial.print(F(\",light:\")); Serial.print(percent);\n    Serial.print(F(\",leds:\")); Serial.println(count);\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-led-magic-sign","title":"Paint a message with moving light","description":"","english":"Use the six Crack the Code LEDs as six rows, top to bottom D8 through D13. Set all six pins to OUTPUT and D7 to active-high INPUT.\n Store the original two-letter message HI as eleven six-bit columns: 63,4,4,4,63,0,33,33,63,33,33. Bit zero controls the top LED, D8, and bit five controls D13.\n While D7 is held, display each column for exactly 2200 microseconds, switching each LED according to that column's bits. Blank all LEDs after the word and wait 25 milliseconds before repeating.\n When D7 is released, blank the LEDs.\n A sideways sweep of the held shield spreads these time-separated columns across space. Keep column timing an integer number of microseconds.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 7;\nconst byte LED_PINS[] = {8, 9, 10, 11, 12, 13};\n// Columns of H, a blank column, then I. Bit 0 is the top LED (D8).\nconst byte columns[] = {63, 4, 4, 4, 63, 0, 33, 33, 63, 33, 33};\nconst byte COLUMN_COUNT = sizeof(columns) / sizeof(columns[0]);\nconst unsigned int COLUMN_US = 2200;\nvoid showColumn(byte bits) {\n  for (byte row = 0; row < 6; ++row) {\n    digitalWrite(LED_PINS[row], (bits & (1 << row)) ? HIGH : LOW);\n  }\n}\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT);\n  for (byte row = 0; row < 6; ++row) pinMode(LED_PINS[row], OUTPUT);\n}\nvoid loop() {\n  if (digitalRead(BUTTON_PIN) == HIGH) {\n    for (byte column = 0; column < COLUMN_COUNT; ++column) {\n      if (digitalRead(BUTTON_PIN) != HIGH) break;\n      showColumn(columns[column]);\n      delayMicroseconds(COLUMN_US);\n    }\n    showColumn(0);\n    delay(25);\n  } else {\n    showColumn(0);\n  }\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-connect-an-led","title":"Connect and blink an external LED","description":"","english":"Use a separate LED on the Crack the Code Shield's digital pin 5 with a 220 ohm series resistor and a return to ground.\n The hardware path is D5 to resistor, resistor to LED anode, and LED cathode to ground. Never connect the LED directly across power without its resistor.\n Set pin 5 to OUTPUT and start low.\n Forever, drive pin 5 HIGH for 500 milliseconds and LOW for 500 milliseconds. No other shield outputs are used.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte LED_PIN = 5;\nconst unsigned int ON_MS = 500;\nconst unsigned int OFF_MS = 500;\nvoid setup() {\n  pinMode(LED_PIN, OUTPUT);\n  digitalWrite(LED_PIN, LOW);\n}\nvoid loop() {\n  digitalWrite(LED_PIN, HIGH);\n  delay(ON_MS);\n  digitalWrite(LED_PIN, LOW);\n  delay(OFF_MS);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-traffic-lights","title":"Build a pedestrian crossing","description":"","english":"REQUEST BUTTON AND BUZZER\nUse D7 as an active-high pedestrian request button.\nUse D3 for the buzzer.\n\nVEHICLE LIGHTS\nUse D4 for the red vehicle light.\nUse D5 for the yellow vehicle light.\nUse D6 for the green vehicle light.\nNever press the shared D6 button while this program runs.\n\nPEDESTRIAN INDICATORS\nUse shield D8 for WALK.\nUse shield D13 for WAIT.\nUse shield D12 for request accepted.\n\nSTART AND ACCEPT A REQUEST\nStart in READY with vehicle green and pedestrian WAIT.\nDebounce D7 for 25 milliseconds.\nAccept a fresh press only while READY.\nIgnore extra presses during the sequence; a held button is not a new press.\n\nCROSSING SEQUENCE\nREQUESTED: Keep vehicle green and show request accepted for 3 seconds.\n\nYELLOW: Show vehicle yellow and pedestrian WAIT for 2 seconds.\n\nALL_RED: Show vehicle red and pedestrian WAIT for 1 second.\n\nWALK: Keep vehicles red and show pedestrian WALK for 5 seconds.\n\nCLEARANCE: Keep vehicles red and flash WAIT for 3 seconds.\n\nRETURN_RED: Keep vehicle red and pedestrian WAIT for 1 more second.\n\nReturn to READY with vehicle green and pedestrian WAIT.\n\nTIMING AND SAFETY\nUse millis to check elapsed time without blocking delays.\nStart a new elapsed timer whenever the phase changes.\nKeep vehicle green off throughout WALK and clearance.\n\nSOUND CUES\nMake slow locator ticks while pedestrians wait.\nMake a descending chirp at the start of WALK, then rapid pulses during WALK.\n\nSERIAL FEEDBACK\nPrint each phase change at 9600 baud.\n\nUse these short timings for the tabletop crossing.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"// Tabletop Australian-style crossing. Short teaching timings.\n// Traffic module: D4 red, D5 yellow, D6 green. Never press D6.\n// Shield LEDs: D8 walk, D13 wait, D12 request accepted.\nconst byte BUTTON = 7, BUZZER = 3;\nenum Phase { READY, REQUESTED, YELLOW, ALL_RED, WALK, CLEARANCE, RETURN_RED };\nPhase phase = READY;\nunsigned long started = 0, changedAt = 0;\nbool rawLast = false, pressed = false;\nvoid enter(Phase next, unsigned long now) {\n  phase = next; started = now;\n  const char* names[] = {\"Vehicles go / wait\", \"Request accepted\", \"Vehicles stopping\", \"All red\", \"Walk\", \"Finish crossing / do not start\", \"All red\"};\n  Serial.println(names[phase]);\n}\nvoid setup() {\n  for (byte pin = 3; pin <= 6; pin++) pinMode(pin, OUTPUT);\n  for (byte pin = 8; pin <= 13; pin++) pinMode(pin, OUTPUT);\n  pinMode(BUTTON, INPUT); // This shield has an active-HIGH button.\n  Serial.begin(9600);\n  enter(READY, millis());\n}\nvoid loop() {\n  unsigned long now = millis();\n  bool raw = digitalRead(BUTTON) == HIGH;\n  if (raw != rawLast) { rawLast = raw; changedAt = now; }\n  if (now - changedAt >= 25 && pressed != raw) {\n    pressed = raw;\n    if (pressed && phase == READY) enter(REQUESTED, now);\n  }\n  unsigned long elapsed = now - started;\n  if (phase == REQUESTED && elapsed >= 3000) enter(YELLOW, now);\n  else if (phase == YELLOW && elapsed >= 2000) enter(ALL_RED, now);\n  else if (phase == ALL_RED && elapsed >= 1000) enter(WALK, now);\n  else if (phase == WALK && elapsed >= 5000) enter(CLEARANCE, now);\n  else if (phase == CLEARANCE && elapsed >= 3000) enter(RETURN_RED, now);\n  else if (phase == RETURN_RED && elapsed >= 1000) enter(READY, now);\n  elapsed = now - started;\n  for (byte pin = 4; pin <= 6; pin++) digitalWrite(pin, LOW);\n  digitalWrite(phase <= REQUESTED ? 6 : phase == YELLOW ? 5 : 4, HIGH);\n  digitalWrite(8, phase == WALK);\n  digitalWrite(12, phase == REQUESTED || phase == YELLOW || phase == ALL_RED);\n  digitalWrite(13, phase == CLEARANCE ? (elapsed / 250) % 2 == 0 : phase != WALK);\n  // Slow locator ticks, a descending walk-start chirp, then fast walk pulses.\n  unsigned int hz = 0;\n  if (phase == WALK) {\n    if (elapsed < 250) hz = 2000 - elapsed * 6;\n    else if ((elapsed - 250) % 125 < 60) hz = 1000;\n  } else if (now % 1000 < 35) hz = 880;\n  if (hz) tone(BUZZER, hz); else noTone(BUZZER);\n}\n","links":[],"structure":null}}},{"slug":"ctc-lab-spoon-piano","title":"Build a seven-key spoon piano","description":"","english":"Use seven Crack the Code edge pads as keys, in order A0, A1, A2, A3, D2, D4 and D5. Do not use D6, which shares the onboard button pull-down circuit. Configure every key as INPUT_PULLUP.\n Pair the keys with frequencies 262, 294, 330, 349, 392, 440 and 494 hertz.\n Use the onboard buzzer at D3 and potentiometer at A5. Start serial at 9600 baud.\n Repeatedly scan the keys in order. An untouched key reads HIGH; a key touched by a grounded spoon reads LOW. Select the first touched key only.\n Map the dial reading from 0–1023 to an offset of minus 80 through plus 80 hertz and add it to the selected note.\n Start or update the tone only when its frequency changes. Stop the buzzer when no key is touched.\n Every 100 milliseconds report the key number, zero for none, and the played frequency, zero for silence.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte KEY_PINS[] = {A0, A1, A2, A3, 2, 4, 5};\nconst unsigned int NOTES[] = {262, 294, 330, 349, 392, 440, 494};\nconst byte KEY_COUNT = sizeof(KEY_PINS) / sizeof(KEY_PINS[0]);\nstatic_assert(KEY_COUNT == sizeof(NOTES) / sizeof(NOTES[0]), \"Match every key with a note\");\nconst byte BUZZER_PIN = 3;\nconst byte POT_PIN = A5;\nint playingHz = 0;\nunsigned long lastReportAt = 0;\nvoid setup() {\n  for (byte i = 0; i < KEY_COUNT; ++i) pinMode(KEY_PINS[i], INPUT_PULLUP);\n  pinMode(BUZZER_PIN, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  int selected = -1;\n  for (byte i = 0; i < KEY_COUNT; ++i) {\n    if (digitalRead(KEY_PINS[i]) == LOW) {\n      selected = i;\n      break;\n    }\n  }\n  const int bend = map(analogRead(POT_PIN), 0, 1023, -80, 80);\n  const int frequency = selected < 0 ? 0 : static_cast<int>(NOTES[selected]) + bend;\n  if (frequency != playingHz) {\n    if (frequency == 0) noTone(BUZZER_PIN);\n    else tone(BUZZER_PIN, frequency);\n    playingHz = frequency;\n  }\n  const unsigned long now = millis();\n  if (now - lastReportAt >= 100) {\n    lastReportAt = now;\n    Serial.print(F(\"key:\")); Serial.print(selected + 1);\n    Serial.print(F(\",frequency:\")); Serial.println(frequency);\n  }\n}\n","links":[],"structure":null}}},{"slug":"uno-kit-first-upload","title":"Your first Uno upload","description":"Uno R3 Learning Kit tutorial","english":"Blink the built-in LED every half second.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){pinMode(LED_BUILTIN,OUTPUT);}\nvoid loop(){digitalWrite(LED_BUILTIN,HIGH);delay(500);digitalWrite(LED_BUILTIN,LOW);delay(500);}\n","links":[],"structure":null}}},{"slug":"uno-kit-five-colour-leds","title":"Light and fade five LED colours","description":"Uno R3 Learning Kit tutorial","english":"Fade red, yellow, green, blue and white LEDs together using PWM on D3, D5, D6, D9 and D10. Each LED has its own 330 ohm resistor.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte leds[]={3,5,6,9,10};\nvoid setup(){for(byte p:leds)pinMode(p,OUTPUT);}\nvoid loop(){for(int v=0;v<=255;v++){for(byte p:leds)analogWrite(p,v);delay(8);}for(int v=255;v>=0;v--){for(byte p:leds)analogWrite(p,v);delay(8);}}\n","links":[],"structure":null}}},{"slug":"uno-kit-pushbutton","title":"Press a button to light an LED","description":"Uno R3 Learning Kit tutorial","english":"Read the pushbutton on D2 with an internal pull-up. Light the D9 LED while pressed and report pressed as 1 or 0 at 115200 baud.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){pinMode(2,INPUT_PULLUP);pinMode(9,OUTPUT);Serial.begin(115200);}\nvoid loop(){bool pressed=digitalRead(2)==LOW;digitalWrite(9,pressed);Serial.print(\"pressed:\");Serial.println(pressed);delay(20);}\n","links":[],"structure":null}}},{"slug":"uno-kit-rgb-colour","title":"Mix colour with the RGB LED","description":"Uno R3 Learning Kit tutorial","english":"Cycle red, green and blue, then mix all three using PWM on D9, D10 and D11.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte pins[]={9,10,11};\nvoid setup(){for(byte p:pins)pinMode(p,OUTPUT);}\nvoid loop(){for(byte colour=0;colour<3;colour++){for(byte i=0;i<3;i++)analogWrite(pins[i],i==colour?150:0);delay(800);}for(byte p:pins)analogWrite(p,100);delay(1200);}\n","links":[],"structure":null}}},{"slug":"uno-kit-potentiometer","title":"Read a rotary potentiometer","description":"Uno R3 Learning Kit tutorial","english":"Read analog input A0 and print position from 0 to 1023 at 115200 baud. On this USB-powered Uno, ground is near 0 and the 5V supply is near 1023; a centred linear potentiometer gives roughly 512.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);}\nvoid loop(){int raw=analogRead(A0);Serial.print(\"position:\");Serial.println(raw);delay(30);}\n","links":[],"structure":null}}},{"slug":"uno-kit-light-sensor","title":"Measure light with an LDR","description":"Uno R3 Learning Kit tutorial","english":"Read the sensor voltage divider on A0, average eight samples and print reading at 115200 baud.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);}\nvoid loop(){long sum=0;for(byte i=0;i<8;i++)sum+=analogRead(A0);Serial.print(\"reading:\");Serial.println(sum/8);delay(50);}\n","links":[],"structure":null}}},{"slug":"uno-kit-thermistor","title":"Watch temperature change with a thermistor","description":"Uno R3 Learning Kit tutorial","english":"Read the sensor voltage divider on A0, average eight samples and print reading at 115200 baud.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);}\nvoid loop(){long sum=0;for(byte i=0;i<8;i++)sum+=analogRead(A0);Serial.print(\"reading:\");Serial.println(sum/8);delay(50);}\n","links":[],"structure":null}}},{"slug":"uno-kit-piezo-melody","title":"Play a melody on the piezo","description":"Uno R3 Learning Kit tutorial","english":"Play the notes of a scale on a passive piezo connected through 100 ohms to D8.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const int notes[]={262,294,330,349,392,440,494,523};\nvoid setup(){}\nvoid loop(){for(int hz:notes){tone(8,hz,180);delay(240);}noTone(8);delay(1000);}\n","links":[],"structure":null}}},{"slug":"uno-kit-joystick","title":"Read the joystick and its button","description":"Uno R3 Learning Kit tutorial","english":"Read joystick X on A0 and Y on A1. Read its active-low push switch on D2. Print x, y and pressed values.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);pinMode(2,INPUT_PULLUP);}\nvoid loop(){Serial.print(\"x:\");Serial.print(analogRead(A0));Serial.print(\",y:\");Serial.print(analogRead(A1));Serial.print(\",pressed:\");Serial.println(digitalRead(2)==LOW);delay(30);}\n","links":[],"structure":null}}},{"slug":"uno-kit-distance-meter","title":"Measure distance with ultrasound","description":"Uno R3 Learning Kit tutorial","english":"Trigger the HC-SR04 on D7 and time ECHO on D6. Convert the round-trip time to centimetres and print cm at 115200 baud.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);pinMode(7,OUTPUT);pinMode(6,INPUT);}\nvoid loop(){digitalWrite(7,LOW);delayMicroseconds(3);digitalWrite(7,HIGH);delayMicroseconds(10);digitalWrite(7,LOW);unsigned long us=pulseIn(6,HIGH,30000UL);if(us){Serial.print(\"cm:\");Serial.println(us*0.0343/2.0,1);}else Serial.println(\"No echo\");delay(80);}\n","links":[],"structure":null}}},{"slug":"uno-kit-servo-position","title":"Set the SG90 servo angle","description":"Uno R3 Learning Kit tutorial","english":"Attach a positional servo on D9 and start at 90 degrees. Accept serial commands angle:30 through angle:150 and report the commanded angle every 100 milliseconds.","app_html":"<!doctype html><html lang=\"en\"><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Servo position</title>\n<style>:root{color-scheme:dark;font:16px -apple-system,BlinkMacSystemFont,\"Segoe UI\",sans-serif;color:#e8f1f1;background:#101d20}*{box-sizing:border-box}body{margin:0;padding:28px}main{max-width:620px;margin:auto}.head{display:flex;justify-content:space-between;align-items:center;gap:16px}h1{font-size:20px;margin:0}#status{font-size:13px;color:#9baeb1}#dial{display:block;width:100%;height:180px;margin:20px 0}#horn{transform-origin:160px 140px;transition:transform .12s ease-out}.readout{display:flex;justify-content:space-between;align-items:baseline}output{font-size:38px;font-weight:600;font-variant-numeric:tabular-nums}.caption,p{color:#a6babd;font-size:13px;line-height:1.6}input{width:100%;accent-color:#23c4b5;margin:20px 0}.presets{display:flex;gap:10px}button{flex:1;border:1px solid #3c555a;border-radius:8px;background:#20373c;color:#e5f4f2;padding:12px;font:inherit;cursor:pointer}button:hover{background:#2e4c52}button:disabled,input:disabled{opacity:.4;cursor:default}button:focus-visible,input:focus-visible{outline:2px solid #39d2c2;outline-offset:3px}</style>\n<main><div class=\"head\"><h1>Servo position</h1><span id=\"status\" role=\"status\">Connect your Uno above</span></div>\n<svg id=\"dial\" viewBox=\"0 0 320 170\" aria-hidden=\"true\"><path d=\"M56 80 A120 120 0 0 1 264 80\" fill=\"none\" stroke=\"#29464b\" stroke-width=\"9\" stroke-linecap=\"round\"/><path d=\"M82 95 A90 90 0 0 1 238 95\" fill=\"none\" stroke=\"#41636a\" stroke-width=\"1\"/><g id=\"horn\"><path d=\"M151 140 L155 36 Q160 26 165 36 L169 140 Z\" fill=\"#36c9b8\"/><circle cx=\"160\" cy=\"140\" r=\"17\" fill=\"#cadcd8\"/><circle cx=\"160\" cy=\"140\" r=\"6\" fill=\"#142a30\"/></g><text x=\"32\" y=\"110\" fill=\"#9eb7bb\" font-size=\"12\">30°</text><text x=\"145\" y=\"14\" fill=\"#9eb7bb\" font-size=\"12\">90°</text><text x=\"264\" y=\"110\" fill=\"#9eb7bb\" font-size=\"12\">150°</text></svg>\n<div class=\"readout\"><label for=\"angle\">Commanded angle</label><output id=\"value\" for=\"angle\">90°</output></div><input id=\"angle\" type=\"range\" min=\"30\" max=\"150\" value=\"90\" step=\"1\" disabled>\n<div class=\"presets\"><button data-angle=\"60\" disabled>60°</button><button data-angle=\"90\" disabled>Centre</button><button data-angle=\"120\" disabled>120°</button></div><p>Upload this guide’s sketch, then connect at 115200 baud. Use a separate regulated 5V servo supply with a shared ground. The display shows the command; the servo has no angle feedback.</p></main>\n<script>\nconst slider=document.querySelector('#angle'),value=document.querySelector('#value'),horn=document.querySelector('#horn'),status=document.querySelector('#status'),buttons=[...document.querySelectorAll('button')];\nlet ready=false,timer=0,last=0;\nfunction render(n){value.value=n+'°';horn.style.transform=`rotate(${n-90}deg)`;}\nfunction send(){timer=0;if(ready&&serial.connected&&serial.visible){serial.send('angle:'+slider.value);last=Date.now();}}\nslider.addEventListener('input',()=>{render(Number(slider.value));if(!timer)timer=setTimeout(send,Math.max(0,60-(Date.now()-last)));});\nbuttons.forEach(b=>b.addEventListener('click',()=>{slider.value=b.dataset.angle;render(Number(slider.value));send();}));\nfunction controls(){slider.disabled=!ready;buttons.forEach(b=>b.disabled=!ready);}\nserial.onStatus(connected=>{ready=false;controls();status.textContent=connected?'Waiting for servo sketch…':'Connect your Uno above';});\nserial.onValues(packet=>{const n=packet.get('angle',NaN);if(!Number.isFinite(n))return;ready=serial.connected;controls();status.textContent='Uno connected';if(document.activeElement!==slider){slider.value=Math.min(150,Math.max(30,n));render(Number(slider.value));}});\nserial.onVisible(visible=>{if(!visible){clearTimeout(timer);timer=0;}});\n</script></html>\n","settings":{},"by_lang":{"cpp":{"code":"#include <Servo.h>\nServo servo;\nint angle=90,target=90; unsigned long nextMove=0,lastReport=0; char command[20];byte used=0;\nvoid setup(){Serial.begin(115200);servo.attach(9);servo.write(angle);}\nvoid loop(){while(Serial.available()){char c=Serial.read();if(c=='\\n'){command[used]=0;if(strncmp(command,\"angle:\",6)==0)target=constrain(atoi(command+6),30,150);used=0;}else if(c!=13&&used<sizeof(command)-1)command[used++]=c;}unsigned long now=millis();if(now-nextMove>=15){nextMove=now;if(angle<target)angle++;else if(angle>target)angle--;servo.write(angle);}if(now-lastReport>=100){lastReport=now;Serial.print(\"angle:\");Serial.println(target);}}\n","links":[],"structure":null}}},{"slug":"uno-kit-transistor-switches","title":"Switch LEDs with NPN transistors","description":"Uno R3 Learning Kit tutorial","english":"Alternate two LEDs using low-side NPN switches. Drive the PN2222 base from D8 and BC547 base from D9 through separate one kilohm resistors.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){pinMode(8,OUTPUT);pinMode(9,OUTPUT);}\nvoid loop(){digitalWrite(8,HIGH);digitalWrite(9,LOW);delay(700);digitalWrite(8,LOW);digitalWrite(9,HIGH);delay(700);}\n","links":[],"structure":null}}},{"slug":"uno-kit-pnp-switch","title":"Build a high-side PNP switch","description":"Uno R3 Learning Kit tutorial","english":"Use D8 to control a BC557 high-side LED switch. LOW turns it on; HIGH turns it off.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){digitalWrite(8,HIGH);pinMode(8,OUTPUT);}\nvoid loop(){digitalWrite(8,LOW);delay(800);digitalWrite(8,HIGH);delay(800);}\n","links":[],"structure":null}}},{"slug":"uno-kit-diode-direction","title":"See how a diode controls current direction","description":"Uno R3 Learning Kit tutorial","english":"Blink a resistor-limited red LED through a forward-biased 1N4001 diode on D8.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){pinMode(8,OUTPUT);}\nvoid loop(){digitalWrite(8,HIGH);delay(1000);digitalWrite(8,LOW);delay(1000);}\n","links":[],"structure":null}}},{"slug":"uno-kit-capacitor-timing","title":"Watch a capacitor charge and discharge","description":"Uno R3 Learning Kit tutorial","english":"Switch D8 every five seconds. Charge and discharge 10 microfarads through 100 kilohms and plot its A0 voltage.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"unsigned long changeAt=0;bool charging=false;\nvoid setup(){Serial.begin(115200);pinMode(8,OUTPUT);}\nvoid loop(){if(millis()-changeAt>=5000){changeAt=millis();charging=!charging;digitalWrite(8,charging);}Serial.print(\"capacitor:\");Serial.println(analogRead(A0));delay(20);}\n","links":[],"structure":null}}},{"slug":"uno-kit-resistor-divider","title":"Explore the resistor assortment","description":"Uno R3 Learning Kit tutorial","english":"Measure a divider with a fixed 10 kilohm resistor to 5V and a test resistor to ground. Print the ADC count and approximate test resistance.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){Serial.begin(115200);}\nvoid loop(){analogRead(A0);delay(5);long total=0;for(byte i=0;i<16;i++){total+=analogRead(A0);delay(1);}float raw=total/16.0;Serial.print(\"adc:\");Serial.print(raw,1);if(raw>2&&raw<1021){Serial.print(\",ohms:\");Serial.print(10000.0*raw/(1023.0-raw),0);}Serial.println();delay(100);}\n","links":[],"structure":null}}},{"slug":"uno-kit-dc-motor","title":"Reverse a DC motor with the L293D","description":"Uno R3 Learning Kit tutorial","english":"Drive one DC motor through the L293D. Enable on D9 controls PWM; D7 and D8 select direction. Stop before changing direction.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void stopMotor(){analogWrite(9,0);digitalWrite(7,LOW);digitalWrite(8,LOW);}\nvoid setup(){pinMode(7,OUTPUT);pinMode(8,OUTPUT);pinMode(9,OUTPUT);stopMotor();Serial.begin(115200);}\nvoid loop(){digitalWrite(7,HIGH);digitalWrite(8,LOW);analogWrite(9,150);Serial.println(\"direction:1\");delay(1500);stopMotor();delay(700);digitalWrite(7,LOW);digitalWrite(8,HIGH);analogWrite(9,150);Serial.println(\"direction:-1\");delay(1500);stopMotor();delay(1000);}\n","links":[],"structure":null}}},{"slug":"uno-kit-stepper-motor","title":"Turn a stepper with the ULN2003 board","description":"Uno R3 Learning Kit tutorial","english":"Half-step a 5V 28BYJ-48 through a ULN2003 board. Use D8–D11 for IN1–IN4. Move 512 half-steps each way and release the coils at rest.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte pins[]={8,9,10,11};const byte seq[8]={1,3,2,6,4,12,8,9};byte phase=0;\nvoid turn(int steps,int direction){for(int i=0;i<steps;i++){phase=(phase+direction+8)%8;for(byte p=0;p<4;p++)digitalWrite(pins[p],(seq[phase]>>p)&1);delay(3);}for(byte p:pins)digitalWrite(p,LOW);}\nvoid setup(){for(byte p:pins)pinMode(p,OUTPUT);}\nvoid loop(){turn(512,1);delay(700);turn(512,-1);delay(1200);}\n","links":[],"structure":null}}},{"slug":"uno-kit-relay-led","title":"Switch a low-voltage LED with a relay","description":"Uno R3 Learning Kit tutorial","english":"Toggle a relay module on D7 every 1.5 seconds. Its normally open contact switches a resistor-limited 5V LED. Set ACTIVE_LOW to match the supplied module.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const bool ACTIVE_LOW=true;const byte RELAY=7;\nvoid setRelay(bool on){digitalWrite(RELAY,on?(ACTIVE_LOW?LOW:HIGH):(ACTIVE_LOW?HIGH:LOW));}\nvoid setup(){setRelay(false);pinMode(RELAY,OUTPUT);}\nvoid loop(){setRelay(true);delay(1500);setRelay(false);delay(1500);}\n","links":[],"structure":null}}},{"slug":"uno-kit-shift-register","title":"Control eight LEDs with a 74HC595","description":"Uno R3 Learning Kit tutorial","english":"Shift a walking bit and alternating patterns into a 74HC595 using D11 data, D12 clock and D8 latch.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte DATA=11,CLOCK=12,LATCH=8;\nvoid show(byte value){digitalWrite(LATCH,LOW);shiftOut(DATA,CLOCK,MSBFIRST,value);digitalWrite(LATCH,HIGH);}\nvoid setup(){pinMode(DATA,OUTPUT);pinMode(CLOCK,OUTPUT);pinMode(LATCH,OUTPUT);show(0);}\nvoid loop(){for(byte i=0;i<8;i++){show(1<<i);delay(250);}show(0x55);delay(700);show(0xaa);delay(700);}\n","links":[],"structure":null}}},{"slug":"uno-kit-seven-segment","title":"Count on a single seven-segment display","description":"Uno R3 Learning Kit tutorial","english":"Drive segments A, B, C, D, E, F, G and DP from D2 through D9 using separate one-kilohm resistors. Count from zero to nine on a common-cathode display.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const byte pins[]={2,3,4,5,6,7,8,9};\nconst byte digits[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};\nvoid setup(){for(byte p:pins)pinMode(p,OUTPUT);}\nvoid loop(){for(byte n=0;n<10;n++){for(byte s=0;s<8;s++)digitalWrite(pins[s],(digits[n]>>s)&1);delay(700);}}\n","links":[],"structure":null}}},{"slug":"uno-kit-four-digit-display","title":"Drive a four-digit display with MAX7219","description":"Uno R3 Learning Kit tutorial","english":"Use a MAX7219 to multiplex a four-digit common-cathode display. Connect DIN to D11, CLK to D13 and LOAD to D10, and count from 0 to 9999.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"#include <SPI.h>\nconst byte LOAD=10;\nvoid reg(byte address,byte value){digitalWrite(LOAD,LOW);SPI.transfer(address);SPI.transfer(value);digitalWrite(LOAD,HIGH);}\nvoid initDisplay(byte digits,byte decode){pinMode(LOAD,OUTPUT);digitalWrite(LOAD,HIGH);SPI.begin();SPI.beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE0));reg(0x0f,0);reg(0x0c,0);reg(0x0b,digits-1);reg(0x09,decode);reg(0x0a,1);for(byte n=1;n<=8;n++)reg(n,0);reg(0x0c,1);}\nvoid setup(){initDisplay(4,0x0f);}\nvoid loop(){static unsigned int count=0;unsigned int value=count++;for(byte d=1;d<=4;d++){reg(d,value%10);value/=10;}if(count>9999)count=0;delay(300);}\n","links":[],"structure":null}}},{"slug":"uno-kit-led-matrix","title":"Draw patterns on the 8 × 8 matrix","description":"Uno R3 Learning Kit tutorial","english":"Drive a row-anode, column-cathode 8×8 matrix with a MAX7219 in no-decode mode. Alternate a smile pattern and a diagonal.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"#include <SPI.h>\nconst byte LOAD=10;\nvoid reg(byte address,byte value){digitalWrite(LOAD,LOW);SPI.transfer(address);SPI.transfer(value);digitalWrite(LOAD,HIGH);}\nvoid initDisplay(byte digits,byte decode){pinMode(LOAD,OUTPUT);digitalWrite(LOAD,HIGH);SPI.begin();SPI.beginTransaction(SPISettings(1000000,MSBFIRST,SPI_MODE0));reg(0x0f,0);reg(0x0c,0);reg(0x0b,digits-1);reg(0x09,decode);reg(0x0a,1);for(byte n=1;n<=8;n++)reg(n,0);reg(0x0c,1);}\nconst byte smile[8]={0x3c,0x42,0xa5,0x81,0xa5,0x99,0x42,0x3c};\nvoid setup(){initDisplay(8,0);}\nvoid loop(){for(byte c=0;c<8;c++)reg(c+1,smile[c]);delay(1800);for(byte c=0;c<8;c++)reg(c+1,1<<c);delay(1000);}\n","links":[],"structure":null}}},{"slug":"uno-kit-lcd-screen","title":"Write to the LCD1602","description":"Uno R3 Learning Kit tutorial","english":"Use the LiquidCrystal library in 4-bit mode. RS=D12, E=D11 and data D4–D7=D5,D4,D3,D2. Print a greeting and elapsed seconds.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"#include <LiquidCrystal.h>\nLiquidCrystal lcd(12,11,5,4,3,2);\nvoid setup(){lcd.begin(16,2);lcd.print(\"Hi, Little Bird!\");}\nvoid loop(){lcd.setCursor(0,1);lcd.print(\"Seconds: \");lcd.print(millis()/1000);delay(200);}\n","links":[],"structure":null}}},{"slug":"uno-kit-motion-sensor","title":"Measure motion with the MPU6050","description":"Uno R3 Learning Kit tutorial","english":"Read the MPU6050 over I2C at address 0x68 using A4 SDA and A5 SCL. Disable the Uno internal pull-ups, wake the chip, choose the ±2g accelerometer range and print ax, ay and az in g.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"#include <Wire.h>\nconst byte ADDRESS=0x68;\nvoid writeReg(byte reg,byte value){Wire.beginTransmission(ADDRESS);Wire.write(reg);Wire.write(value);Wire.endTransmission();}\nbool readRegs(byte reg,byte n){Wire.beginTransmission(ADDRESS);Wire.write(reg);if(Wire.endTransmission(false))return false;return Wire.requestFrom(ADDRESS,n)==n;}\nint16_t word(){byte hi=Wire.read(),lo=Wire.read();return (int16_t)((uint16_t(hi)<<8)|lo);}\nvoid setup(){Serial.begin(115200);Wire.begin();digitalWrite(A4,LOW);digitalWrite(A5,LOW);Wire.setClock(100000);if(!readRegs(0x75,1)||Wire.read()!=0x68){Serial.println(\"MPU6050 not found\");while(true)delay(100);}writeReg(0x6b,0);writeReg(0x1b,0);writeReg(0x1c,0);delay(100);}\nvoid loop(){if(readRegs(0x3b,14)){int16_t ax=word(),ay=word(),az=word(),temp=word(),gx=word(),gy=word(),gz=word();Serial.print(\"ax:\");Serial.print(ax/16384.0,3);Serial.print(\",ay:\");Serial.print(ay/16384.0,3);Serial.print(\",az:\");Serial.println(az/16384.0,3);}else Serial.println(\"I2C read error\");delay(50);}\n","links":[],"structure":null}}},{"slug":"uno-kit-workbench-accessories","title":"Use the shield, headers and workbench accessories","description":"Uno R3 Learning Kit tutorial","english":"Blink the Uno built-in LED after inspecting the kit accessories. The battery snap remains disconnected.","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup(){pinMode(LED_BUILTIN,OUTPUT);}\nvoid loop(){digitalWrite(LED_BUILTIN,HIGH);delay(500);digitalWrite(LED_BUILTIN,LOW);delay(500);}\n","links":[],"structure":null}}},{"slug":"lorikeet-arduino-3d","title":"Five Lorikeet colours with Arduino","description":"Five LEDs on D3, a 330 ohm data resistor and low-brightness colour frames.","english":"Connect a five-LED Little Bird Lorikeet WS2812B board to an Arduino Uno.\nUse digital pin D3 for data through a 330 ohm resistor, 5V for power, and a shared ground.\n\nUse the Adafruit NeoPixel library with five pixels, GRB colour order and 800 kHz signalling.\nSet the active colour channel to 24 out of 255 so this first USB-powered test stays dim.\n\nOn startup, initialise the pixels and send an all-off frame.\n\nRepeat forever:\nSet all five LEDs to red (24, 0, 0), send the frame and wait one second.\nSet all five LEDs to green (0, 24, 0), send the frame and wait one second.\nSet all five LEDs to blue (0, 0, 24), send the frame and wait one second.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"#include <Adafruit_NeoPixel.h>\n\nconst byte DATA_PIN = 3;\nconst byte LED_COUNT = 5;\nconst byte LEVEL = 24;                 // Keep this first USB-powered test dim.\nconst unsigned long HOLD_MS = 1000;\nAdafruit_NeoPixel pixels(LED_COUNT, DATA_PIN, NEO_GRB + NEO_KHZ800);\n\nvoid setup() {\n  pixels.begin();\n  pixels.clear();\n  pixels.show();\n}\n\nvoid showColour(byte red, byte green, byte blue) {\n  pixels.fill(pixels.Color(red, green, blue));\n  pixels.show();                       // Send the buffered colours to all five LEDs.\n  delay(HOLD_MS);\n}\n\nvoid loop() {\n  showColour(LEVEL, 0, 0);\n  showColour(0, LEVEL, 0);\n  showColour(0, 0, LEVEL);\n}\n","links":[],"structure":null}}},{"slug":"eagled-blink-3d","title":"Blink an eye with EagLED","description":"Make the right eye blink, then investigate how on-time and off-time shape a repeating signal.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nSet D10, the right eye, as an output.\n\nTurn it on for 500 milliseconds. Turn it off for 500 milliseconds. Repeat continuously. Keep the buzzer switch off.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte EYE_PIN = 10;\nconst unsigned long ON_MS = 500;\nconst unsigned long OFF_MS = 500;\nvoid setup() { pinMode(EYE_PIN, OUTPUT); }\nvoid loop() {\n  digitalWrite(EYE_PIN, HIGH);\n  delay(ON_MS);\n  digitalWrite(EYE_PIN, LOW);\n  delay(OFF_MS);\n}\n","links":[],"structure":null}}},{"slug":"eagled-sequence-3d","title":"Sequence all seven EagLED LEDs","description":"Follow an array through the six shaped LEDs and the small user indicator.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nUse LEDs on D7, D3, D10, D0, D1, D12 and D6, in that order. Set all seven pins as outputs.\n\nLight one LED for 250 milliseconds, then turn it off before lighting the next. Repeat the sequence. Keep the buzzer switch off.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte LED_PINS[] = {7, 3, 10, 0, 1, 12, 6};\nconst byte LED_COUNT = sizeof(LED_PINS) / sizeof(LED_PINS[0]);\nconst unsigned long STEP_MS = 250;\nvoid setup() {\n  for (byte i = 0; i < LED_COUNT; i++) pinMode(LED_PINS[i], OUTPUT);\n}\nvoid loop() {\n  for (byte i = 0; i < LED_COUNT; i++) {\n    digitalWrite(LED_PINS[i], HIGH);\n    delay(STEP_MS);\n    digitalWrite(LED_PINS[i], LOW);\n  }\n}\n","links":[],"structure":null}}},{"slug":"eagled-fade-3d","title":"Fade the EagLED eyes","description":"Use PWM to change the average brightness of the two red eye LEDs.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nUse the left eye D3 and right eye D10 as PWM outputs.\n\nIncrease both brightness commands from 0 to 255, waiting 4 milliseconds at each level. Decrease from 254 to 1 at the same rate, then repeat. Keep the buzzer switch off.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte LEFT_EYE = 3;\nconst byte RIGHT_EYE = 10;\nconst unsigned long STEP_MS = 4;\nvoid setup() {\n  pinMode(LEFT_EYE, OUTPUT);\n  pinMode(RIGHT_EYE, OUTPUT);\n}\nvoid loop() {\n  for (int brightness = 0; brightness <= 255; brightness++) {\n    analogWrite(LEFT_EYE, brightness);\n    analogWrite(RIGHT_EYE, brightness);\n    delay(STEP_MS);\n  }\n  for (int brightness = 254; brightness >= 1; brightness--) {\n    analogWrite(LEFT_EYE, brightness);\n    analogWrite(RIGHT_EYE, brightness);\n    delay(STEP_MS);\n  }\n}\n","links":[],"structure":null}}},{"slug":"eagled-button-3d","title":"Press to light with EagLED","description":"Read an active-low button and make the left eye follow your finger.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nUse the triangular button on D2 with INPUT_PULLUP and the left eye on D3 as an output.\n\nWhen the button reads LOW, light the eye. Otherwise turn it off. Report button and eye as 1 for active and 0 for inactive over USB Serial at 9600 baud, every 20 milliseconds.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 2;\nconst byte EYE_PIN = 3;\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT_PULLUP);\n  pinMode(EYE_PIN, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  bool pressed = digitalRead(BUTTON_PIN) == LOW;\n  digitalWrite(EYE_PIN, pressed ? HIGH : LOW);\n  Serial.print(\"button:\"); Serial.print(pressed ? 1 : 0);\n  Serial.print(\",eye:\"); Serial.println(pressed ? 1 : 0);\n  delay(20);\n}\n","links":[],"structure":null}}},{"slug":"eagled-toggle-3d","title":"Make an EagLED button remember","description":"Turn a momentary press into a debounced, persistent on/off choice.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nUse D2 with INPUT_PULLUP and the right star on D6. Start with the star off.\n\nAccept a button change only after the raw reading has stayed unchanged for 25 milliseconds. Toggle the star only when the accepted reading changes to LOW. Holding or releasing must not toggle it again.\n\nUse millis without blocking delays. Report accepted button state and star state over USB Serial at 9600 baud every 50 milliseconds.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte BUTTON_PIN = 2;\nconst byte STAR_PIN = 6;\nconst unsigned long DEBOUNCE_MS = 25;\nbool rawLast = HIGH;\nbool stable = HIGH;\nbool starOn = false;\nunsigned long changedAt = 0;\nunsigned long reportedAt = 0;\nvoid setup() {\n  pinMode(BUTTON_PIN, INPUT_PULLUP);\n  pinMode(STAR_PIN, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  unsigned long now = millis();\n  bool raw = digitalRead(BUTTON_PIN);\n  if (raw != rawLast) { rawLast = raw; changedAt = now; }\n  if (now - changedAt >= DEBOUNCE_MS && raw != stable) {\n    stable = raw;\n    if (stable == LOW) starOn = !starOn;\n  }\n  digitalWrite(STAR_PIN, starOn ? HIGH : LOW);\n  if (now - reportedAt >= 50) {\n    reportedAt = now;\n    Serial.print(\"button:\"); Serial.print(stable == LOW ? 1 : 0);\n    Serial.print(\",star:\"); Serial.println(starOn ? 1 : 0);\n  }\n}\n","links":[],"structure":null}}},{"slug":"eagled-light-3d","title":"Measure light with EagLED","description":"Read the on-board phototransistor and compare ADC counts with approximate voltage.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nRead the intact EagLED light sensor on A9 every 100 milliseconds.\n\nCalculate approximate voltage as reading times 3.3 divided by 1023. Print labelled light and volts readings over USB Serial at 9600 baud. Do not call the reading lux.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte LIGHT_PIN = A9;\nconst float REFERENCE_V = 3.3;\nvoid setup() { Serial.begin(9600); }\nvoid loop() {\n  int light = analogRead(LIGHT_PIN);\n  float volts = light * (REFERENCE_V / 1023.0);\n  Serial.print(\"light:\"); Serial.print(light);\n  Serial.print(\",volts:\"); Serial.println(volts, 3);\n  delay(100);\n}\n","links":[],"structure":null}}},{"slug":"eagled-night-3d","title":"Build an automatic EagLED night light","description":"Use two thresholds and remembered state to keep a light stable near the switching point.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nRead the EagLED light sensor on A9. Control both eye LEDs on D3 and D10. Start with the eyes off.\n\nIf the reading is below 300, turn both eyes on. If it is above 450, turn them off. Otherwise retain their previous state.\n\nReport light and eyes over USB Serial at 9600 baud every 50 milliseconds. Keep the buzzer switch off.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte LIGHT_PIN = A9;\nconst byte LEFT_EYE = 3;\nconst byte RIGHT_EYE = 10;\nconst int DARK_BELOW = 300;\nconst int BRIGHT_ABOVE = 450;\nbool eyesOn = false;\nvoid setup() {\n  pinMode(LEFT_EYE, OUTPUT);\n  pinMode(RIGHT_EYE, OUTPUT);\n  Serial.begin(9600);\n}\nvoid loop() {\n  int light = analogRead(LIGHT_PIN);\n  if (light < DARK_BELOW) eyesOn = true;\n  else if (light > BRIGHT_ABOVE) eyesOn = false;\n  digitalWrite(LEFT_EYE, eyesOn ? HIGH : LOW);\n  digitalWrite(RIGHT_EYE, eyesOn ? HIGH : LOW);\n  Serial.print(\"light:\"); Serial.print(light);\n  Serial.print(\",eyes:\"); Serial.println(eyesOn ? 1 : 0);\n  delay(50);\n}\n","links":[],"structure":null}}},{"slug":"eagled-buzzer-3d","title":"Play notes on the EagLED buzzer","description":"Drive the built-in piezo and explain the relationship between frequency, duration and its shared LED pin.","english":"Use a Little Bird EagLED, 3.3 V, ATmega32U4 at 8 MHz. Keep the board intact.\n\nUse the intact EagLED buzzer on D12 and turn its separate switch on. D12 also drives the right heart LED.\n\nPlay 523 Hz, 659 Hz and 784 Hz in order. Each note lasts 300 milliseconds, followed by silence for 200 milliseconds. After the third gap, wait another 500 milliseconds, then repeat. Drive D12 LOW during silence.","app_html":"","settings":{"baud":9600,"board":"eagled"},"by_lang":{"cpp":{"code":"const byte BUZZER_PIN = 12;\nconst unsigned int NOTES[] = {523, 659, 784};\nconst unsigned long NOTE_MS = 300;\nconst unsigned long GAP_MS = 200;\nvoid setup() { pinMode(BUZZER_PIN, OUTPUT); }\nvoid loop() {\n  for (byte i = 0; i < 3; i++) {\n    tone(BUZZER_PIN, NOTES[i]);\n    delay(NOTE_MS);\n    noTone(BUZZER_PIN);\n    digitalWrite(BUZZER_PIN, LOW);\n    delay(GAP_MS);\n  }\n  delay(500);\n}\n","links":[],"structure":null}}},{"slug":"blink-without-delay","title":"Blink without delay","description":"Same blink, but using a timer (millis) so the loop never blocks.","english":"Blink the built-in LED roughly twice a second, but never use delay() — the loop should stay free to do other things.\n\nSet up the built-in LED pin as an output.\nRemember the last time we toggled the LED, and whether it's currently on.\n\nEvery time through the loop:\n  Look at how long it's been since we last toggled the LED.\n  If it's been at least 500 milliseconds, flip the LED (on if it was off, off if it was on) and remember this as the new toggle time.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"bool ledState = false;\nunsigned long lastToggleTime = 0;\n\nvoid setup() {\n  pinMode(LED_BUILTIN, OUTPUT);\n}\n\nvoid loop() {\n  unsigned long elapsed = millis() - lastToggleTime;\n  if (elapsed >= 500) {\n    ledState = !ledState;\n    digitalWrite(LED_BUILTIN, ledState ? HIGH : LOW);\n    lastToggleTime = millis();\n  }\n}","links":[{"label":"state","code_end":1,"code_start":1,"english_end":4,"english_start":4},{"label":"state","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"function","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"function_end","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"function","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"loop","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"loop","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"loop","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"loop","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"loop","code_end":13,"code_start":13,"english_end":8,"english_start":8},{"label":"loop","code_end":14,"code_start":14,"english_end":8,"english_start":8},{"label":"function_end","code_end":15,"code_start":15,"english_end":6,"english_start":6}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Set the built-in LED pin as an output.\",\"calls\":[{\"english_start\":3,\"english_end\":3}]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":8,\"summary\":\"Toggle the built-in LED about every 500 ms without blocking.\",\"calls\":[{\"english_start\":7,\"english_end\":7},{\"english_start\":8,\"english_end\":8}]}]}"},"ruby":{"code":"LED_PIN = :LED_BUILTIN\ndef setup\n  pin_mode(LED_PIN, :output)\nend\n@led_on = false\n@last_toggle_time = millis\ndef loop\n  now = millis\n  if now - @last_toggle_time >= 500\n    @led_on = !@led_on\n    digital_write(LED_PIN, @led_on ? :high : :low)\n    @last_toggle_time = now\n  end\nend\n\nsetup\nloop do\n  loop\n  sleep 0.001\nend","links":[{"label":"constant","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"function_start","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"statement","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"function_end","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"state","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"state","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"function_start","code_end":7,"code_start":7,"english_end":8,"english_start":6},{"label":"statement","code_end":8,"code_start":8,"english_end":8,"english_start":7},{"label":"conditional","code_end":9,"code_start":9,"english_end":8,"english_start":7},{"label":"statement","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"statement","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"conditional_end","code_end":13,"code_start":13,"english_end":8,"english_start":7},{"label":"function_end","code_end":14,"code_start":14,"english_end":8,"english_start":6},{"label":"call","code_end":16,"code_start":16,"english_end":8,"english_start":6},{"label":"loop_start","code_end":17,"code_start":17,"english_end":8,"english_start":6},{"label":"call","code_end":18,"code_start":18,"english_end":8,"english_start":6},{"label":"yield","code_end":19,"code_start":19,"english_end":8,"english_start":6},{"label":"loop_end","code_end":20,"code_start":20,"english_end":8,"english_start":6}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Set the built-in LED pin as an output.\",\"calls\":[{\"english_start\":3,\"english_end\":3}]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":8,\"summary\":\"Check elapsed time and toggle the LED every 500 milliseconds without blocking.\",\"calls\":[{\"english_start\":7,\"english_end\":8},{\"english_start\":8,\"english_end\":8}]}]}"},"python":{"code":"LED_PIN = \"BUILTIN_LED\"\nled_is_on = False\nlast_toggle_time = time.monotonic()\nimport time\n\nif __name__ == \"__main__\":\n    while True:\n        now = time.monotonic()\n        if now - last_toggle_time >= 0.5:\n            led_is_on = not led_is_on\n            last_toggle_time = now\n            print(f\"LED {'ON' if led_is_on else 'OFF'}\")\n        time.sleep(0.01)","links":[{"label":"set_up_pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"remember_state","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"remember_toggle_time","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"import_time","code_end":4,"code_start":4,"english_end":1,"english_start":1},{"label":"main_loop","code_end":13,"code_start":6,"english_end":8,"english_start":6}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const ledPin = LED_BUILTIN;\nlet ledOn = false;\nlet lastToggle = 0;\n\nfunction setup() {\n  pinMode(ledPin, OUTPUT);\n}\n\nfunction loop() {\n  const now = millis();\n  if (now - lastToggle >= 500) {\n    ledOn = !ledOn;\n    digitalWrite(ledPin, ledOn ? HIGH : LOW);\n    lastToggle = now;\n  }\n}","links":[{"label":"declare LED pin","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"track LED state","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"track last toggle time","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"setup function start","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"configure LED pin output","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"setup function end","code_end":7,"code_start":7,"english_end":3,"english_start":3},{"label":"loop function start","code_end":9,"code_start":9,"english_end":8,"english_start":6},{"label":"read current time","code_end":10,"code_start":10,"english_end":8,"english_start":7},{"label":"check half-second elapsed","code_end":11,"code_start":11,"english_end":8,"english_start":7},{"label":"flip LED state","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"write LED state","code_end":13,"code_start":13,"english_end":8,"english_start":8},{"label":"store new toggle time","code_end":14,"code_start":14,"english_end":8,"english_start":8},{"label":"end if","code_end":15,"code_start":15,"english_end":8,"english_start":8},{"label":"loop function end","code_end":16,"code_start":16,"english_end":8,"english_start":8}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Configure the built-in LED pin as an output.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":8,\"summary\":\"Check elapsed time and toggle the LED about twice per second without blocking.\",\"calls\":[{\"english_start\":7,\"english_end\":8}]}]}"}}},{"slug":"fade-an-led","title":"Fade an LED","description":"Smoothly fade an LED up and down with PWM (analogWrite).","english":"Smoothly fade an LED up and down, over and over.\n\nThe LED is on a PWM-capable pin.\nSet that pin as an output.\nKeep a brightness value (0 to 255) and a step amount.\n\nForever:\n  Write the current brightness to the LED pin.\n  Add the step to the brightness.\n  If the brightness has reached 0 or 255, reverse the direction of the step.\n  Wait about 20 milliseconds so the fade is visible.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const int ledPin = 9;\nint brightness = 0;\nint stepAmount = 5;\nvoid setup() {\n  pinMode(ledPin, OUTPUT);\n}\n\nvoid loop() {\n  analogWrite(ledPin, brightness);\n  brightness += stepAmount;\n  if (brightness <= 0 || brightness >= 255) {\n    stepAmount = -stepAmount;\n  }\n  delay(20);\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"declaration","code_end":2,"code_start":2,"english_end":5,"english_start":5},{"label":"declaration","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"function_start","code_end":4,"code_start":4,"english_end":4,"english_start":3},{"label":"statement","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"function_end","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"function_start","code_end":8,"code_start":8,"english_end":11,"english_start":7},{"label":"statement","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"statement","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"if_start","code_end":11,"code_start":11,"english_end":10,"english_start":10},{"label":"statement","code_end":12,"code_start":12,"english_end":10,"english_start":10},{"label":"if_end","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"statement","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"function_end","code_end":15,"code_start":15,"english_end":11,"english_start":11}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":4,\"summary\":\"Set the LED pin as an output.\",\"calls\":[{\"english_start\":4,\"english_end\":4}]},{\"name\":\"loop\",\"params\":[],\"english_start\":7,\"english_end\":11,\"summary\":\"Continuously fade the LED up and down with a short delay.\",\"calls\":[{\"english_start\":8,\"english_end\":8},{\"english_start\":9,\"english_end\":9},{\"english_start\":10,\"english_end\":10},{\"english_start\":11,\"english_end\":11}]}]}"},"python":{"code":"from machine import Pin, PWM\n\nled = PWM(Pin(0))\nled.freq(1000)\nbrightness = 0\nstep = 5\nif __name__ == \"__main__\":\n    while True:\n        led.duty_u16(brightness * 257)\n        brightness += step\n        if brightness <= 0 or brightness >= 255:\n            step = -step\n        import time\n        time.sleep(0.02)","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":4,"english_start":3},{"label":"setup","code_end":3,"code_start":3,"english_end":4,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":4,"english_start":3},{"label":"state","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"state","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"entry","code_end":7,"code_start":7,"english_end":11,"english_start":7},{"label":"loop","code_end":8,"code_start":8,"english_end":11,"english_start":7},{"label":"output","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"update","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"check","code_end":11,"code_start":11,"english_end":10,"english_start":10},{"label":"reverse","code_end":12,"code_start":12,"english_end":10,"english_start":10},{"label":"sleep_import","code_end":13,"code_start":13,"english_end":11,"english_start":11},{"label":"delay","code_end":14,"code_start":14,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"ruby":{"code":"LED_PIN = 9\n\nbrightness_pin = LED_PIN\n# Set that pin as an output.\nbrightness = 0\nstep = 1\nloop do\n  puts \"PWM #{brightness_pin}: #{brightness}\"\n  brightness += step\n  if brightness <= 0 || brightness >= 255\n    step = -step\n  end\n  sleep 0.02\nend","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":3,"code_start":3,"english_end":4,"english_start":3},{"label":"comment","code_end":4,"code_start":4,"english_end":4,"english_start":4},{"label":"state","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"state","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"loop","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"write","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"update","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"condition","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"reverse","code_end":11,"code_start":11,"english_end":10,"english_start":10},{"label":"end","code_end":12,"code_start":12,"english_end":10,"english_start":10},{"label":"delay","code_end":13,"code_start":13,"english_end":11,"english_start":11},{"label":"end","code_end":14,"code_start":14,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const five = require('johnny-five');\nconst board = new five.Board();\n\nboard.on('ready', () => {\n  const led = new five.Led(9);\n  let brightness = 0;\n  let step = 5;\n  const fade = () => {\n    led.brightness(brightness);\n    brightness += step;\n    if (brightness <= 0 || brightness >= 255) {\n      step = -step;\n    }\n    setTimeout(fade, 20);\n  };\n  fade();\n});","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":2,"code_start":2,"english_end":4,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":5,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":5,"english_start":3},{"label":"state","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"state","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"loop","code_end":8,"code_start":8,"english_end":11,"english_start":7},{"label":"loop","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"loop","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"loop","code_end":11,"code_start":11,"english_end":10,"english_start":10},{"label":"loop","code_end":12,"code_start":12,"english_end":10,"english_start":10},{"label":"loop","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"loop","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"loop","code_end":15,"code_start":15,"english_end":11,"english_start":7},{"label":"loop","code_end":16,"code_start":16,"english_end":11,"english_start":7},{"label":"setup","code_end":17,"code_start":17,"english_end":5,"english_start":3}],"structure":"{\"functions\":[{\"name\":\"fade\",\"params\":[],\"english_start\":7,\"english_end\":11,\"summary\":\"Continuously write the LED brightness, update it, reverse direction at the endpoints, and schedule the next update.\",\"calls\":[{\"english_start\":11,\"english_end\":11}]}]}"}}},{"slug":"button-to-led","title":"Button → LED","description":"Mirror a pushbutton (using the internal pull-up) onto the LED.","english":"Light the built-in LED while a pushbutton is held down, and turn it off when the button is released.\n\nThe button connects a pin to ground when pressed, so use the internal pull-up resistor — the pin reads HIGH when the button is up and LOW when it's pressed.\nSet the button pin as an input with pull-up, and the LED pin as an output.\n\nForever:\n  Read the button.\n  If the button is pressed, turn the LED on; otherwise turn it off.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const int buttonPin = 2;\nconst int ledPin = LED_BUILTIN;\nvoid setup() {\n  pinMode(buttonPin, INPUT_PULLUP);\n  pinMode(ledPin, OUTPUT);\n}\nvoid loop() {\n  int buttonState = digitalRead(buttonPin);\n  if (buttonState == LOW) {\n    digitalWrite(ledPin, HIGH);\n  } else {\n    digitalWrite(ledPin, LOW);\n  }\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"function_start","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"statement","code_end":4,"code_start":4,"english_end":4,"english_start":4},{"label":"statement","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"function_end","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"function_start","code_end":7,"code_start":7,"english_end":6,"english_start":6},{"label":"statement","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"control","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"statement","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"control","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"control","code_end":13,"code_start":13,"english_end":8,"english_start":8},{"label":"function_end","code_end":14,"code_start":14,"english_end":8,"english_start":6}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":4,\"english_end\":4,\"summary\":\"Configure the button as an internal pull-up input and the built-in LED as an output.\",\"calls\":[{\"english_start\":4,\"english_end\":4}]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":8,\"summary\":\"Continuously read the button and mirror its pressed state to the LED.\",\"calls\":[{\"english_start\":7,\"english_end\":7},{\"english_start\":8,\"english_end\":8}]}]}"},"python":{"code":"from machine import Pin\nled = Pin(\"LED\", Pin.OUT)\nbutton = Pin(0, Pin.IN, Pin.PULL_UP)\nif __name__ == \"__main__\":\"\n    while True:\n        if button.value() == 0:\n            led.value(1)\n        else:\n            led.value(0)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"setup","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"entry","code_end":4,"code_start":4,"english_end":8,"english_start":6},{"label":"loop","code_end":5,"code_start":5,"english_end":8,"english_start":6},{"label":"condition","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"then","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"else","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"else_body","code_end":9,"code_start":9,"english_end":8,"english_start":8}],"structure":"{\"functions\":[]}"},"ruby":{"code":"LED_PIN = 13\nBUTTON_PIN = 2\npin_mode(BUTTON_PIN, :input_pullup)\npin_mode(LED_PIN, :output)\n\nloop do\n  pressed = (digital_read(BUTTON_PIN) == :low)\n  digital_write(LED_PIN, pressed ? :high : :low)\nend","links":[{"label":"constant","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"constant","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"setup","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"setup","code_end":4,"code_start":4,"english_end":4,"english_start":4},{"label":"loop","code_end":6,"code_start":6,"english_end":8,"english_start":6},{"label":"read_button","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"set_led","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"loop_end","code_end":9,"code_start":9,"english_end":8,"english_start":6}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const five = require('johnny-five');\nconst board = new five.Board();\nboard.on('ready', () => {\n  const button = new five.Button({ pin: 2, isPullup: true });\n  const led = new five.Led(13);\n  button.on('change', () => {\n    if (button.isDown) {\n      led.on();\n    } else {\n      led.off();\n    }\n  });\n});","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"setup","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"hardware","code_end":4,"code_start":4,"english_end":4,"english_start":4},{"label":"hardware","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"loop","code_end":6,"code_start":6,"english_end":8,"english_start":6},{"label":"conditional","code_end":7,"code_start":7,"english_end":8,"english_start":7},{"label":"action","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"conditional","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"action","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"conditional","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"loop","code_end":12,"code_start":12,"english_end":8,"english_start":6},{"label":"setup","code_end":13,"code_start":13,"english_end":4,"english_start":4}],"structure":"{\"functions\":[]}"}}},{"slug":"serial-hello-counter","title":"Serial: hello + counter","description":"Print \"Hello\" once, then count up once a second over Serial.","english":"Talk to the computer over the serial port.\n\nStart the serial connection at 9600 baud and print \"Hello, world!\" once.\nKeep a counter starting at zero.\n\nForever:\n  Add one to the counter.\n  Print \"tick \" followed by the counter.\n  Wait one second.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"import argparse\nimport time\nimport serial\n\nparser = argparse.ArgumentParser()\nparser.add_argument(\"port\")\nargs = parser.parse_args()\nser = serial.Serial(args.port, 9600)\nprint(\"Hello, world!\")\ncounter = 0\n\nif __name__ == \"__main__\":\n    while True:\n        counter += 1\n        print(f\"tick {counter}\")\n        time.sleep(1)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"import","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"import","code_end":3,"code_start":3,"english_end":1,"english_start":1},{"label":"setup","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"setup","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"setup","code_end":7,"code_start":7,"english_end":3,"english_start":3},{"label":"setup","code_end":8,"code_start":8,"english_end":3,"english_start":3},{"label":"output","code_end":9,"code_start":9,"english_end":3,"english_start":3},{"label":"state","code_end":10,"code_start":10,"english_end":4,"english_start":4},{"label":"entrypoint","code_end":12,"code_start":12,"english_end":9,"english_start":6},{"label":"loop","code_end":13,"code_start":13,"english_end":9,"english_start":6},{"label":"loop_body","code_end":14,"code_start":14,"english_end":7,"english_start":7},{"label":"loop_body","code_end":15,"code_start":15,"english_end":8,"english_start":8},{"label":"loop_body","code_end":16,"code_start":16,"english_end":9,"english_start":9}],"structure":"{\"functions\":[]}"},"cpp":{"code":"long counter = 0;\n\nvoid setup() {\n  Serial.begin(9600);\n  Serial.println(\"Hello, world!\");\n}\n\nvoid loop() {\n  counter++;\n  Serial.print(\"tick \");\n  Serial.println(counter);\n  delay(1000);\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"function_start","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"statement","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"statement","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"function_end","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"function_start","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"statement","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"statement","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"statement","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"function_end","code_end":13,"code_start":13,"english_end":6,"english_start":6}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Start the serial connection and print a greeting once.\",\"calls\":[{\"english_start\":3,\"english_end\":3}]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":9,\"summary\":\"Increment the counter, print the tick message, and wait one second.\",\"calls\":[{\"english_start\":8,\"english_end\":8},{\"english_start\":9,\"english_end\":9}]}]}"},"ruby":{"code":"require 'serialport'\nport_name = ARGV[0] || '/dev/ttyUSB0'\nserial = SerialPort.new(port_name, 9600, 8, 1, SerialPort::NONE)\nserial.puts 'Hello, world!'\ncounter = 0\nloop do\n  counter += 1\n  serial.puts \"tick #{counter}\"\n  sleep 1\nend","links":[{"label":"require serial port support","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"choose serial port","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"open serial connection at 9600 baud","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"print greeting once","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"initialize counter","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"forever loop start","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"increment counter","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"print tick and counter","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"wait one second","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"forever loop end","code_end":10,"code_start":10,"english_end":6,"english_start":6}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const { SerialPort } = require('serialport');\nconst portPath = process.argv[2];\nconst port = new SerialPort({ path: portPath, baudRate: 9600 });\nport.write('Hello, world!\\n');\nlet counter = 0;\n\nconst wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n(async () => {\n  for (;;) {\n    counter += 1;\n    port.write(`tick ${counter}\\n`);\n    await wait(1000);\n  }\n})();","links":[{"label":"import serial support","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"get port path","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"open serial connection","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"send greeting","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"initialize counter","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"delay helper","code_end":7,"code_start":7,"english_end":9,"english_start":6},{"label":"start loop","code_end":8,"code_start":8,"english_end":9,"english_start":6},{"label":"infinite loop","code_end":9,"code_start":9,"english_end":9,"english_start":6},{"label":"increment counter","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"print tick","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"wait one second","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"end loop","code_end":13,"code_start":13,"english_end":9,"english_start":6},{"label":"run loop","code_end":14,"code_start":14,"english_end":9,"english_start":6}],"structure":"{\"functions\":[]}"}}},{"slug":"read-a-sensor","title":"Read a sensor","description":"Read an analog input (e.g. a potentiometer on A0) and print the value.","english":"Read an analog sensor on pin A0 and stream its value to the serial port.\n\nStart the serial connection at 9600 baud.\n\nForever:\n  Read the analog value on A0 (it will be between 0 and 1023).\n  Print that value on its own line.\n  Wait 100 milliseconds.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"import sys\nimport time\ntry:\n    from machine import ADC\n    sensor = ADC(0)\nexcept ImportError:\n    ADC = None\n    sensor = None\ndef read_sensor():\n    if sensor is not None:\n        return sensor.read()\n    return 0\nif __name__ == \"__main__\":\n    while True:\n        value = read_sensor()\n        print(value)\n        time.sleep(0.1)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"import","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"setup","code_end":3,"code_start":3,"english_end":1,"english_start":1},{"label":"setup","code_end":4,"code_start":4,"english_end":1,"english_start":1},{"label":"setup","code_end":5,"code_start":5,"english_end":1,"english_start":1},{"label":"setup","code_end":6,"code_start":6,"english_end":1,"english_start":1},{"label":"setup","code_end":7,"code_start":7,"english_end":1,"english_start":1},{"label":"setup","code_end":8,"code_start":8,"english_end":1,"english_start":1},{"label":"function","code_end":9,"code_start":9,"english_end":3,"english_start":3},{"label":"function","code_end":10,"code_start":10,"english_end":3,"english_start":3},{"label":"function","code_end":11,"code_start":11,"english_end":3,"english_start":3},{"label":"function","code_end":12,"code_start":12,"english_end":3,"english_start":3},{"label":"entry","code_end":13,"code_start":13,"english_end":8,"english_start":5},{"label":"loop","code_end":14,"code_start":14,"english_end":8,"english_start":5},{"label":"read","code_end":15,"code_start":15,"english_end":6,"english_start":6},{"label":"output","code_end":16,"code_start":16,"english_end":7,"english_start":7},{"label":"delay","code_end":17,"code_start":17,"english_end":8,"english_start":8}],"structure":"{\"functions\":[{\"name\":\"read_sensor\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Read the analog value from A0 when supported, otherwise return a fallback value.\",\"calls\":[]}]}"},"ruby":{"code":"require 'arduino_firmata'\nboard = ArduinoFirmata.connect\nloop do\n  value = board.analog_read(0)\n  puts value\n  sleep 0.1\nend","links":[{"label":"require hardware library","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"connect to board","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"forever loop","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"read analog value on A0","code_end":4,"code_start":4,"english_end":6,"english_start":6},{"label":"print value","code_end":5,"code_start":5,"english_end":7,"english_start":7},{"label":"wait 100 milliseconds","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"end loop","code_end":7,"code_start":7,"english_end":5,"english_start":5}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const { Board, Sensor } = require(\"johnny-five\");\nconst board = new Board();\n\nboard.on(\"ready\", () => {\n  const sensor = new Sensor(\"A0\");\n  this.io.serialConfig({ baud: 9600 });\n  setInterval(() => {\n    console.log(sensor.value);\n  }, 100);\n});","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"setup","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"loop","code_end":4,"code_start":4,"english_end":8,"english_start":5},{"label":"loop","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"loop","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"loop","code_end":7,"code_start":7,"english_end":7,"english_start":6},{"label":"loop","code_end":8,"code_start":8,"english_end":7,"english_start":6},{"label":"loop","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"loop","code_end":10,"code_start":10,"english_end":8,"english_start":5}],"structure":"{\"functions\":[]}"},"cpp":{"code":"const int sensorPin = A0;\nvoid setup() {\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int sensorValue = analogRead(sensorPin);\n  Serial.println(sensorValue);\n  delay(100);\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"function_start","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"statement","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"function_end","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"function_start","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"statement","code_end":7,"code_start":7,"english_end":6,"english_start":6},{"label":"statement","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"statement","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"function_end","code_end":10,"code_start":10,"english_end":5,"english_start":5}],"structure":"{\"functions\":[]}"}}},{"slug":"echo-what-you-type","title":"Echo what you type","description":"Read a line from the Serial Monitor and echo it back (and blink).","english":"Echo back anything typed into the Serial Monitor, and blink the LED each time.\n\nStart the serial connection at 9600 baud, set the built-in LED pin as an output, and print \"Type something and press Enter...\".\n\nForever:\n  If there is serial input waiting:\n    Read a whole line (up to the newline) and trim the whitespace off it.\n    Print \"you said: \" followed by that line.\n    Blink the LED briefly (on, short pause, off).\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup() {\n  Serial.begin(9600);\n  pinMode(LED_BUILTIN, OUTPUT);\n  Serial.println(\"Type something and press Enter...\");\n}\n\nvoid loop() {\n  if (Serial.available() > 0) {\n    String line = Serial.readStringUntil('\\n');\n    line.trim();\n    Serial.print(\"you said: \");\n    Serial.println(line);\n    digitalWrite(LED_BUILTIN, HIGH);\n    delay(100);\n    digitalWrite(LED_BUILTIN, LOW);\n    delay(100);\n  }\n}","links":[{"label":"function_start","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"statement","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"statement","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"statement","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"function_end","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"function_start","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"statement","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"statement","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"statement","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"statement","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"statement","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"statement","code_end":14,"code_start":14,"english_end":9,"english_start":9},{"label":"statement","code_end":15,"code_start":15,"english_end":9,"english_start":9},{"label":"statement","code_end":16,"code_start":16,"english_end":9,"english_start":9},{"label":"statement","code_end":17,"code_start":17,"english_end":9,"english_start":6},{"label":"function_end","code_end":18,"code_start":18,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Initialize serial at 9600 baud, configure the built-in LED as an output, and print the prompt.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":5,\"english_end\":9,\"summary\":\"Wait for serial input, read and trim a line, echo it back with a prefix, and blink the LED briefly.\",\"calls\":[{\"english_start\":6,\"english_end\":9}]}]}"},"python":{"code":"import sys\n\nprint('Type something and press Enter...')\nif __name__ == '__main__':\n    while True:\n        try:\n            line = input()\n        except EOFError:\n            break\n        line = line.strip()\n        print('you said: ' + line)\n        print('LED on')\n        sys.stdout.flush()\n        print('LED off')","links":[{"label":"import","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"greeting","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"entry","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"loop","code_end":5,"code_start":5,"english_end":9,"english_start":5},{"label":"input-check","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"read-line","code_end":7,"code_start":7,"english_end":7,"english_start":6},{"label":"eof","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"break","code_end":9,"code_start":9,"english_end":6,"english_start":6},{"label":"trim","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"echo","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"blink-on","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"flush","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"blink-off","code_end":14,"code_start":14,"english_end":9,"english_start":9}],"structure":"{\"functions\":[]}"},"ruby":{"code":"serial = Serial.new('/dev/ttyUSB0', 9600)\nled_pin = :built_in_led\nputs 'Type something and press Enter...'\nloop do\n  if serial.available? > 0\n    line = serial.gets.chomp\n    puts \"you said: #{line}\"\n    digital_write(led_pin, :high)\n    sleep 0.1\n    digital_write(led_pin, :low)\n  end\nend","links":[{"label":"Start the serial connection at 9600 baud","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"set the built-in LED pin as an output","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"and print \"Type something and press Enter...\"","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Forever:","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"If there is serial input waiting:","code_end":5,"code_start":5,"english_end":6,"english_start":6},{"label":"Read a whole line (up to the newline) and trim the whitespace off it.","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"Print \"you said: \" followed by that line.","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"Blink the LED briefly (on, short pause, off).","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"Blink the LED briefly (on, short pause, off).","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"Blink the LED briefly (on, short pause, off).","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"","code_end":11,"code_start":11,"english_end":9,"english_start":6},{"label":"","code_end":12,"code_start":12,"english_end":9,"english_start":5}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const readline = require('readline');\nconst rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n  terminal: false,\n});\nconsole.log('Type something and press Enter...');\nconst blinkLed = () => {\n  console.log('[LED ON]');\n  setTimeout(() => {\n    console.log('[LED OFF]');\n  }, 100);\n};\n\nrl.on('line', (line) => {\n  const text = line.trim();\n  console.log(`you said: ${text}`);\n  blinkLed();\n});","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"setup","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"setup","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"setup","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"prompt","code_end":7,"code_start":7,"english_end":3,"english_start":3},{"label":"function","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"function","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"function","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"function","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"function","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"function","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"event","code_end":15,"code_start":15,"english_end":9,"english_start":5},{"label":"process","code_end":16,"code_start":16,"english_end":7,"english_start":7},{"label":"output","code_end":17,"code_start":17,"english_end":8,"english_start":8},{"label":"action","code_end":18,"code_start":18,"english_end":9,"english_start":9},{"label":"event","code_end":19,"code_start":19,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"blinkLed\",\"params\":[],\"english_start\":9,\"english_end\":9,\"summary\":\"Simulate a brief LED blink by logging on/off messages with a short delay.\",\"calls\":[{\"english_start\":9,\"english_end\":9}]}]}"}}},{"slug":"play-a-little-melody","title":"Play a little melody","description":"Play a C-major scale on a piezo buzzer wired to pin 8.","english":"Play a short tune on a piezo buzzer connected to pin 8, then stop.\n\nMake a list of note frequencies for a C major scale: 262, 294, 330, 349, 392, 440, 494, 523 Hz.\n\nIn setup, for each note in the list:\n  Play the note on pin 8 for about 300 milliseconds.\n  Wait a touch longer than that so the notes don't run together, then stop the tone.\n\nThe loop does nothing — the tune plays once.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"const int buzzerPin = 8;\nconst int notes[] = {262, 294, 330, 349, 392, 440, 494, 523};\nconst int noteCount = sizeof(notes) / sizeof(notes[0]);\nvoid setup() {\n  for (int i = 0; i < noteCount; i++) {\n    tone(buzzerPin, notes[i]);\n    delay(300);\n    delay(100);\n    noTone(buzzerPin);\n  }\n}\n\nvoid loop() {\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"declaration","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"function","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"loop","code_end":5,"code_start":5,"english_end":7,"english_start":5},{"label":"action","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"action","code_end":7,"code_start":7,"english_end":6,"english_start":6},{"label":"action","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"action","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"loop_end","code_end":10,"code_start":10,"english_end":7,"english_start":5},{"label":"function_end","code_end":11,"code_start":11,"english_end":7,"english_start":5},{"label":"function","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"function_end","code_end":14,"code_start":14,"english_end":9,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":5,\"english_end\":7,\"summary\":\"Plays each note in the scale once on the buzzer with short gaps, then stops the tone after each note.\",\"calls\":[{\"english_start\":6,\"english_end\":6},{\"english_start\":7,\"english_end\":7}]},{\"name\":\"loop\",\"params\":[],\"english_start\":9,\"english_end\":9,\"summary\":\"Does nothing so the tune only plays once.\",\"calls\":[]}]}"},"python":{"code":"import time\nnotes = [262, 294, 330, 349, 392, 440, 494, 523]\ndef play_tone(pin, frequency, duration_ms):\n    print(f\"Playing {frequency} Hz on pin {pin} for {duration_ms} ms\")\n    time.sleep(duration_ms / 1000.0)\n    print(f\"Stopping tone on pin {pin}\")\n\nif __name__ == \"__main__\":\n    pin = 8\n    for note in notes:\n        play_tone(pin, note, 300)\n        time.sleep(0.1)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"data","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"function","code_end":3,"code_start":3,"english_end":7,"english_start":5},{"label":"function body","code_end":4,"code_start":4,"english_end":7,"english_start":5},{"label":"function body","code_end":5,"code_start":5,"english_end":7,"english_start":5},{"label":"function body","code_end":6,"code_start":6,"english_end":7,"english_start":5},{"label":"entry","code_end":8,"code_start":8,"english_end":9,"english_start":5},{"label":"main","code_end":9,"code_start":9,"english_end":9,"english_start":5},{"label":"loop","code_end":10,"code_start":10,"english_end":9,"english_start":5},{"label":"loop body","code_end":11,"code_start":11,"english_end":9,"english_start":5},{"label":"loop body","code_end":12,"code_start":12,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"play_tone\",\"params\":[\"pin\",\"frequency\",\"duration_ms\"],\"english_start\":5,\"english_end\":7,\"summary\":\"Simulates playing a tone on a pin for the requested duration, then stopping it.\",\"calls\":[{\"english_start\":5,\"english_end\":7}]}]}"},"ruby":{"code":"notes = [262, 294, 330, 349, 392, 440, 494, 523]\n\ndef tone(pin, frequency)\n  puts \"tone on pin \"+pin.to_s+\": \"+frequency.to_s+\" Hz\"\nend\n\ndef no_tone(pin)\n  puts \"stop tone on pin \"+pin.to_s\nend\n\ndef setup(notes)\n  notes.each do |frequency|\n    tone(8, frequency)\n    sleep 0.3\n    sleep 0.35\n    no_tone(8)\n  end\nend\n\ndef loop\nend\nsetup(notes)\nloop","links":[{"label":"create note list","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"tone helper","code_end":5,"code_start":3,"english_end":7,"english_start":5},{"label":"no_tone helper","code_end":9,"code_start":7,"english_end":7,"english_start":5},{"label":"start setup and iterate notes","code_end":12,"code_start":11,"english_end":7,"english_start":5},{"label":"play each note briefly","code_end":14,"code_start":13,"english_end":6,"english_start":6},{"label":"pause a little longer, then stop each note","code_end":18,"code_start":15,"english_end":7,"english_start":7},{"label":"empty loop","code_end":21,"code_start":20,"english_end":9,"english_start":9},{"label":"run the tune once","code_end":22,"code_start":22,"english_end":1,"english_start":1},{"label":"call empty loop","code_end":23,"code_start":23,"english_end":9,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"tone\",\"params\":[\"pin\",\"frequency\"],\"english_start\":5,\"english_end\":7,\"summary\":\"Print a simulated tone action for the given pin and frequency.\",\"calls\":[]},{\"name\":\"no_tone\",\"params\":[\"pin\"],\"english_start\":5,\"english_end\":7,\"summary\":\"Print a simulated stop-tone action for the given pin.\",\"calls\":[]},{\"name\":\"setup\",\"params\":[\"notes\"],\"english_start\":5,\"english_end\":7,\"summary\":\"Play each note in the scale once on pin 8 with a short delay and then stop the tone.\",\"calls\":[{\"english_start\":6,\"english_end\":6},{\"english_start\":7,\"english_end\":7}]},{\"name\":\"loop\",\"params\":[],\"english_start\":9,\"english_end\":9,\"summary\":\"Do nothing.\",\"calls\":[]}]}"},"javascript":{"code":"const pin = 8;\nconst notes = [262, 294, 330, 349, 392, 440, 494, 523];\n\nconst playTone = (frequency, durationMs) => {\n  console.log(`tone on pin ${pin}: ${frequency} Hz for ${durationMs} ms`);\n};\n\nconst stopTone = () => {\n  console.log(`stop tone on pin ${pin}`);\n};\n\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\n(async () => {\n  for (const note of notes) {\n    playTone(note, 300);\n    await sleep(350);\n    stopTone();\n  }\n})();","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"function_start","code_end":4,"code_start":4,"english_end":6,"english_start":6},{"label":"function_body","code_end":5,"code_start":5,"english_end":6,"english_start":6},{"label":"function_end","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"function_start","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"function_body","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"function_end","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"declaration","code_end":12,"code_start":12,"english_end":7,"english_start":7},{"label":"async_start","code_end":14,"code_start":14,"english_end":9,"english_start":5},{"label":"loop_start","code_end":15,"code_start":15,"english_end":9,"english_start":5},{"label":"loop_body","code_end":16,"code_start":16,"english_end":6,"english_start":6},{"label":"loop_body","code_end":17,"code_start":17,"english_end":7,"english_start":7},{"label":"loop_body","code_end":18,"code_start":18,"english_end":7,"english_start":7},{"label":"loop_end","code_end":19,"code_start":19,"english_end":9,"english_start":9},{"label":"async_end","code_end":20,"code_start":20,"english_end":9,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"playTone\",\"params\":[\"frequency\",\"durationMs\"],\"english_start\":6,\"english_end\":6,\"summary\":\"Logs that a tone would play on pin 8 for a given duration.\",\"calls\":[]},{\"name\":\"stopTone\",\"params\":[],\"english_start\":7,\"english_end\":7,\"summary\":\"Logs that the tone would stop on pin 8.\",\"calls\":[]},{\"name\":\"sleep\",\"params\":[\"ms\"],\"english_start\":7,\"english_end\":7,\"summary\":\"Returns a promise that resolves after the given delay.\",\"calls\":[]}]}"}}},{"slug":"reusable-beep-step","title":"A reusable \"beep\" step","description":"Names \"play a beep at a pitch\" once, then calls it several times — shows the ƒ function decorations & the named ribbon.","english":"Play a little sequence of beeps on a piezo buzzer wired to pin 8.\n\nHere's how to play a beep at a given pitch:\n  Play a tone on pin 8 at that pitch for 120 milliseconds.\n  Then stop the tone and wait 80 milliseconds before returning.\n\nStart the serial connection at 9600 baud.\n\nOver and over, forever:\n  Play a beep at 880 Hz.\n  Play a beep at 660 Hz.\n  Play a beep at 990 Hz.\n  Print \"beeped!\" to the serial port.\n  Wait one second before the next round.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void beepAtPitch(int pitch) {\n  tone(8, pitch, 120);\n  delay(120);\n  noTone(8);\n  delay(80);\n}\n\nvoid setup() {\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  beepAtPitch(880);\n  beepAtPitch(660);\n  beepAtPitch(990);\n  Serial.println(\"beeped!\");\n  delay(1000);\n}","links":[{"label":"function signature","code_end":1,"code_start":1,"english_end":5,"english_start":3},{"label":"play tone","code_end":2,"code_start":2,"english_end":4,"english_start":4},{"label":"wait while tone plays","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"stop tone","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"pause before returning","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"end function","code_end":6,"code_start":6,"english_end":5,"english_start":3},{"label":"setup signature","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"start serial","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"end setup","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"loop signature","code_end":12,"code_start":12,"english_end":14,"english_start":9},{"label":"first beep","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"second beep","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"third beep","code_end":15,"code_start":15,"english_end":12,"english_start":12},{"label":"serial message","code_end":16,"code_start":16,"english_end":13,"english_start":13},{"label":"wait between rounds","code_end":17,"code_start":17,"english_end":14,"english_start":14},{"label":"end loop","code_end":18,"code_start":18,"english_end":14,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"beepAtPitch\",\"params\":[\"int pitch\"],\"english_start\":3,\"english_end\":5,\"summary\":\"Plays a tone on pin 8 for 120 ms, stops it, then waits 80 ms.\",\"calls\":[{\"english_start\":4,\"english_end\":4},{\"english_start\":5,\"english_end\":5}]}]}"},"python":{"code":"import time\n\nprint(\"Serial connection started at 9600 baud\")\n\ndef beep(pitch):\n    print(f\"Tone on pin 8 at {pitch} Hz for 120 ms\")\n    time.sleep(0.12)\n    print(\"Stop tone\")\n    time.sleep(0.08)\n\nif __name__ == \"__main__\":\n    while True:\n        beep(880)\n        beep(660)\n        beep(990)\n        print(\"beeped!\")\n        time.sleep(1)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"serial_start","code_end":3,"code_start":3,"english_end":7,"english_start":7},{"label":"function_def","code_end":5,"code_start":5,"english_end":5,"english_start":3},{"label":"function_body","code_end":6,"code_start":6,"english_end":5,"english_start":3},{"label":"function_body","code_end":7,"code_start":7,"english_end":5,"english_start":3},{"label":"function_body","code_end":8,"code_start":8,"english_end":5,"english_start":3},{"label":"function_body","code_end":9,"code_start":9,"english_end":5,"english_start":3},{"label":"entrypoint","code_end":11,"code_start":11,"english_end":14,"english_start":9},{"label":"loop","code_end":12,"code_start":12,"english_end":14,"english_start":9},{"label":"call","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"call","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"call","code_end":15,"code_start":15,"english_end":12,"english_start":12},{"label":"print","code_end":16,"code_start":16,"english_end":13,"english_start":13},{"label":"sleep","code_end":17,"code_start":17,"english_end":14,"english_start":14}],"structure":"{\"functions\":[{\"name\":\"beep\",\"params\":[\"pitch\"],\"english_start\":3,\"english_end\":5,\"summary\":\"Play a tone at the given pitch for 120 milliseconds, then stop and wait 80 milliseconds.\",\"calls\":[{\"english_start\":4,\"english_end\":4},{\"english_start\":5,\"english_end\":5}]}]}"},"ruby":{"code":"PIN = 8\ndef beep(pitch)\n  puts \"tone on pin #{PIN} at #{pitch} Hz for 120 ms\"\n  sleep 0.08\nend\nputs \"serial connection started at 9600 baud\"\nloop do\n  beep 880\n  beep 660\n  beep 990\n  puts \"beeped!\"\n  sleep 1\nend","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"function","code_end":2,"code_start":2,"english_end":5,"english_start":3},{"label":"function","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"function","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"function","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"setup","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"loop","code_end":7,"code_start":7,"english_end":9,"english_start":9},{"label":"loop-body","code_end":8,"code_start":8,"english_end":10,"english_start":10},{"label":"loop-body","code_end":9,"code_start":9,"english_end":11,"english_start":11},{"label":"loop-body","code_end":10,"code_start":10,"english_end":12,"english_start":12},{"label":"loop-body","code_end":11,"code_start":11,"english_end":13,"english_start":13},{"label":"loop-body","code_end":12,"code_start":12,"english_end":14,"english_start":14},{"label":"loop","code_end":13,"code_start":13,"english_end":14,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"beep\",\"params\":[\"pitch\"],\"english_start\":3,\"english_end\":5,\"summary\":\"Play one beep at the given pitch by announcing the tone and waiting before stopping.\",\"calls\":[]}]}"},"javascript":{"code":"const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\nconst SERIAL_BAUD = 9600;\nconst BUZZER_PIN = 8;\nconsole.log(`Serial connection started at ${SERIAL_BAUD} baud.`);\nasync function playBeep(pitch) {\n  console.log(`Tone on pin ${BUZZER_PIN} at ${pitch} Hz for 120 ms.`);\n  await sleep(120);\n  console.log(`Stop tone on pin ${BUZZER_PIN}.`);\n  await sleep(80);\n}\nasync function main() {\n  while (true) {\n    await playBeep(880);\n    await playBeep(660);\n    await playBeep(990);\n    console.log('beeped!');\n    await sleep(1000);\n  }\n}\n\nmain().catch((error) => {\n  console.error(error);\n  process.exitCode = 1;\n});","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":7,"english_start":7},{"label":"declaration","code_end":3,"code_start":3,"english_end":1,"english_start":1},{"label":"statement","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"function_start","code_end":5,"code_start":5,"english_end":5,"english_start":3},{"label":"statement","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"statement","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"statement","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"statement","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"function_end","code_end":10,"code_start":10,"english_end":5,"english_start":5},{"label":"function_start","code_end":11,"code_start":11,"english_end":14,"english_start":9},{"label":"loop_start","code_end":12,"code_start":12,"english_end":14,"english_start":9},{"label":"statement","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"statement","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"statement","code_end":15,"code_start":15,"english_end":12,"english_start":12},{"label":"statement","code_end":16,"code_start":16,"english_end":13,"english_start":13},{"label":"statement","code_end":17,"code_start":17,"english_end":14,"english_start":14},{"label":"loop_end","code_end":18,"code_start":18,"english_end":14,"english_start":9},{"label":"function_end","code_end":19,"code_start":19,"english_end":14,"english_start":9},{"label":"statement","code_end":21,"code_start":21,"english_end":9,"english_start":9},{"label":"statement","code_end":22,"code_start":22,"english_end":9,"english_start":9},{"label":"statement","code_end":23,"code_start":23,"english_end":9,"english_start":9},{"label":"statement","code_end":24,"code_start":24,"english_end":9,"english_start":9}],"structure":"{\"functions\":[{\"name\":\"playBeep\",\"params\":[\"pitch\"],\"english_start\":3,\"english_end\":5,\"summary\":\"Plays one beep at the given pitch, then stops and pauses briefly.\",\"calls\":[{\"english_start\":4,\"english_end\":4},{\"english_start\":5,\"english_end\":5},{\"english_start\":5,\"english_end\":5},{\"english_start\":5,\"english_end\":5}]},{\"name\":\"main\",\"params\":[],\"english_start\":9,\"english_end\":14,\"summary\":\"Runs the repeating three-beep sequence and prints a message after each round.\",\"calls\":[{\"english_start\":10,\"english_end\":10},{\"english_start\":11,\"english_end\":11},{\"english_start\":12,\"english_end\":12},{\"english_start\":13,\"english_end\":13},{\"english_start\":14,\"english_end\":14}]}]}"}}},{"slug":"plot-a5-voltage","title":"Plot the A5 voltage","description":"Read analog pin A5 ~20×/s and print \"A5:raw,volts:v\" so the Plot tab can graph it live (and the Data tab can log it).","english":"Read the analog input on pin A5 — that's the voltage on the wire, somewhere between 0 and 5 volts — and stream it to the serial port so the Plot tab can graph it live.\n\nStart the serial connection at 9600 baud.\n\nOver and over, about twenty times a second:\n  Read the analog value on pin A5. It comes back as a whole number from 0 (0 volts) to 1023 (5 volts).\n  Work out the voltage: divide the reading by 1023 and multiply by 5.\n  Print one line with two labelled numbers — the raw reading as \"A5\" and the voltage (to two decimal places) as \"volts\" — like \"A5:512,volts:2.50\".\n  Wait about 50 milliseconds before the next reading.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup() {\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int reading = analogRead(A5);\n  float voltage = reading * 5.0 / 1023.0;\n  Serial.print(\"A5:\");\n  Serial.print(reading);\n  Serial.print(\",volts:\");\n  Serial.println(voltage, 2);\n  delay(50);\n}","links":[{"label":"function","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"statement","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"function_end","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"function","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"statement","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"statement","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"statement","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"statement","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"statement","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"statement","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"function_end","code_end":13,"code_start":13,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Starts the serial connection at 9600 baud.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":5,\"english_end\":9,\"summary\":\"Repeatedly reads A5, converts the reading to voltage, prints both values, and waits 50 ms.\",\"calls\":[{\"english_start\":6,\"english_end\":6},{\"english_start\":7,\"english_end\":7},{\"english_start\":8,\"english_end\":8},{\"english_start\":9,\"english_end\":9}]}]}"},"ruby":{"code":"Serial.begin(9600)\n\nloop do\n  reading = analogRead(:A5)\n  voltage = reading.to_f / 1023 * 5\n  Serial.println(\"A5:#{reading},volts:#{format('%.2f', voltage)}\")\n  sleep 0.05\nend","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"loop_start","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"read_analog","code_end":4,"code_start":4,"english_end":6,"english_start":6},{"label":"compute_voltage","code_end":5,"code_start":5,"english_end":7,"english_start":7},{"label":"print_values","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"delay","code_end":7,"code_start":7,"english_end":9,"english_start":9},{"label":"loop_end","code_end":8,"code_start":8,"english_end":9,"english_start":5}],"structure":"{\"functions\":[]}"},"python":{"code":"import time\ntry:\n    from machine import ADC, Pin\nexcept ImportError:\n    ADC = Pin = None\nBAUD_RATE = 9600\nDELAY_SECONDS = 0.05\nif Pin is not None:\n    sensor = ADC(Pin(\"A5\"))\nelse:\n    sensor = None\nwhile True:\n    reading = sensor.read()\n    voltage = reading / 1023 * 5\n    print(f\"A5:{reading},volts:{voltage:.2f}\")\n    time.sleep(DELAY_SECONDS)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"import","code_end":5,"code_start":2,"english_end":1,"english_start":1},{"label":"constant","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"constant","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"setup","code_end":9,"code_start":8,"english_end":1,"english_start":1},{"label":"setup","code_end":11,"code_start":10,"english_end":1,"english_start":1},{"label":"loop","code_end":12,"code_start":12,"english_end":9,"english_start":5},{"label":"loop-body","code_end":13,"code_start":13,"english_end":6,"english_start":6},{"label":"loop-body","code_end":14,"code_start":14,"english_end":7,"english_start":7},{"label":"loop-body","code_end":15,"code_start":15,"english_end":8,"english_start":8},{"label":"loop-body","code_end":16,"code_start":16,"english_end":9,"english_start":9}],"structure":"{\"functions\":[]}"},"javascript":{"code":"function setup() {\n  Serial.begin(9600);\n}\n\nfunction loop() {\n  const reading = analogRead(A5);\n  const voltage = (reading / 1023) * 5;\n  Serial.println(`A5:${reading},volts:${voltage.toFixed(2)}`);\n  delay(50);\n}","links":[{"label":"function_start","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"serial_baud","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"function_end","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"function_start","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"read_analog","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"compute_voltage","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"print_values","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"wait","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"function_end","code_end":10,"code_start":10,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":3,\"summary\":\"Start the serial connection at 9600 baud.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":5,\"english_end\":9,\"summary\":\"Repeatedly read A5, convert to voltage, print both values, and pause about 50 ms.\",\"calls\":[]}]}"}}},{"slug":"pot-button-stream","title":"Pot + button → stream A5 and D7","description":"Send the A5 potentiometer and the D7 button ~30×/s as \"pot:NNN,d7:0|1\" — pairs with the Drum pad and Asteroids demos on the App tab.","english":"Read a potentiometer on pin A5 and a pushbutton on pin 7, and stream both to the serial port fast enough to drive a game — about thirty times a second.\n\nStart the serial connection at 9600 baud.\nSet pin 7 as an input using the internal pull-up resistor, so it reads HIGH when the button is open and LOW when it is pressed.\n\nOver and over:\n  Read the analog value on A5 — a whole number from 0 to 1023.\n  Read pin 7. Because of the pull-up it reads LOW when the button is pressed, so call that 1, and not-pressed 0.\n  Print one line with two labelled numbers: the pot reading as \"pot\" and the button state as \"d7\" — like \"pot:512,d7:0\".\n  Wait about 30 milliseconds.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"import time\nfrom machine import ADC, Pin\n\npot = ADC('A5')\nbutton = Pin(7, Pin.IN, Pin.PULL_UP)\n\nif __name__ == \"__main__\":\n    while True:\n        pot_value = pot.read_u16() // 64\n        button_value = 1 if button.value() == 0 else 0\n        print(f\"pot:{pot_value},d7:{button_value}\")\n        time.sleep(0.03)","links":[{"label":"import time","code_end":1,"code_start":1,"english_end":4,"english_start":3},{"label":"import machine","code_end":2,"code_start":2,"english_end":4,"english_start":3},{"label":"setup potentiometer","code_end":4,"code_start":4,"english_end":4,"english_start":3},{"label":"setup button","code_end":5,"code_start":5,"english_end":4,"english_start":3},{"label":"entry point","code_end":7,"code_start":7,"english_end":10,"english_start":6},{"label":"loop","code_end":8,"code_start":8,"english_end":10,"english_start":6},{"label":"read pot","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"read button","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"print line","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"delay","code_end":12,"code_start":12,"english_end":10,"english_start":10}],"structure":"{\"functions\":[]}"},"cpp":{"code":"const int potPin = A5;\nconst int buttonPin = 7;\nvoid setup() {\n  Serial.begin(9600);\n  pinMode(buttonPin, INPUT_PULLUP);\n}\n\nvoid loop() {\n  int potValue = analogRead(potPin);\n  int buttonState = digitalRead(buttonPin) == LOW ? 1 : 0;\n  Serial.print(\"pot:\");\n  Serial.print(potValue);\n  Serial.print(\",d7:\");\n  Serial.println(buttonState);\n  delay(30);\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"function_start","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"statement","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"statement","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"function_end","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"function_start","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"statement","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"statement","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"statement","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"statement","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"statement","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"statement","code_end":14,"code_start":14,"english_end":9,"english_start":9},{"label":"statement","code_end":15,"code_start":15,"english_end":10,"english_start":10},{"label":"function_end","code_end":16,"code_start":16,"english_end":10,"english_start":10}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":3,\"english_end\":4,\"summary\":\"Start serial at 9600 baud and configure pin 7 with the internal pull-up resistor.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":6,\"english_end\":10,\"summary\":\"Repeatedly read the potentiometer and button, print a labeled line, then wait about 30 ms.\",\"calls\":[{\"english_start\":7,\"english_end\":7},{\"english_start\":8,\"english_end\":8}]}]}"},"javascript":{"code":"const BAUD = 9600;\nconst SAMPLE_MS = 30;\nconst POT_PIN = 'A5';\nconst BUTTON_PIN = 7;\n\nconsole.log(`Serial started at ${BAUD} baud`);\nconsole.log(`Pin ${BUTTON_PIN} set as input with internal pull-up`);\n\nsetInterval(() => {\n  const pot = 0;\n  const d7 = 0;\n  console.log(`pot:${pot},d7:${d7}`);\n}, SAMPLE_MS);","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"setup","code_end":3,"code_start":3,"english_end":1,"english_start":1},{"label":"setup","code_end":4,"code_start":4,"english_end":1,"english_start":1},{"label":"serial","code_end":6,"code_start":6,"english_end":4,"english_start":3},{"label":"pin-setup","code_end":7,"code_start":7,"english_end":4,"english_start":4},{"label":"loop-start","code_end":9,"code_start":9,"english_end":10,"english_start":6},{"label":"read-pot","code_end":10,"code_start":10,"english_end":8,"english_start":7},{"label":"read-button","code_end":11,"code_start":11,"english_end":8,"english_start":7},{"label":"print","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"loop-end","code_end":13,"code_start":13,"english_end":10,"english_start":10}],"structure":"{\"functions\":[]}"},"ruby":{"code":"serial_begin(9600)\npin_mode(7, :input_pullup)\nloop do\n  pot = analog_read(:A5)\n  d7 = digital_read(7) == :low ? 1 : 0\n  puts \"pot:\", pot, \",d7:\", d7\n  sleep 0.03\nend","links":[{"label":"start serial","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"configure button pin","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"repeat forever","code_end":3,"code_start":3,"english_end":10,"english_start":6},{"label":"read potentiometer","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"read button and convert","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"print values","code_end":6,"code_start":6,"english_end":9,"english_start":9},{"label":"wait 30 ms","code_end":7,"code_start":7,"english_end":10,"english_start":10},{"label":"end loop","code_end":8,"code_start":8,"english_end":10,"english_start":6}],"structure":"{\"functions\":[]}"}}},{"slug":"ctc-01-blink","title":"Crack the Code · PRP #01 — Blink (D12)","description":"Flash the ThinkerShield's D12 LED on for one second, off for one second, forever — the first Arduino sketch.","english":"Flash an LED on pin 12 — on for one second, off for one second, forever. This is the classic \"Hello, world!\" for hardware.\n\nSet pin 12 as an output.\n\nForever:\n  Turn pin 12 on (HIGH).\n  Wait one second.\n  Turn pin 12 off (LOW).\n  Wait one second.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"void setup() {              // runs once when you press reset or power the board\n  pinMode(12, OUTPUT);      // make digital pin 12 an output\n}\n\nvoid loop() {               // runs over and over again, forever\n  digitalWrite(12, HIGH);   // turn the LED on (HIGH is the voltage level)\n  delay(1000);              // wait for one second (1000 milliseconds)\n  digitalWrite(12, LOW);    // turn the LED off (LOW)\n  delay(1000);              // wait for one second\n}\n","links":[],"structure":null},"ruby":{"code":"require 'pi_piper'\nled = PiPiper::Pin.new(pin: 12, direction: :out)\nloop do\n  led.on\n  sleep 1\n  led.off\n  sleep 1\nend","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"setup","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"loop","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"loop","code_end":4,"code_start":4,"english_end":6,"english_start":6},{"label":"loop","code_end":5,"code_start":5,"english_end":7,"english_start":7},{"label":"loop","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"loop","code_end":7,"code_start":7,"english_end":9,"english_start":9},{"label":"loop","code_end":8,"code_start":8,"english_end":9,"english_start":5}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const { Gpio } = require('onoff');\nconst led = new Gpio(12, 'out');\nconst wait = ms => new Promise(resolve => setTimeout(resolve, ms));\nconst blink = async () => {\n  led.writeSync(1);\n  await wait(1000);\n  led.writeSync(0);\n  await wait(1000);\n};\nsetInterval(() => {\n  blink().catch(err => console.error(err));\n}, 2000);\n\nprocess.on('SIGINT', () => {\n  led.writeSync(0);\n  led.unexport();\n  process.exit(0);\n});","links":[{"label":"setup","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"setup","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"helper","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"function","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"function_body","code_end":5,"code_start":5,"english_end":6,"english_start":6},{"label":"function_body","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"function_body","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"function_body","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"function_end","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"loop","code_end":10,"code_start":10,"english_end":9,"english_start":5},{"label":"loop","code_end":11,"code_start":11,"english_end":9,"english_start":5},{"label":"loop","code_end":12,"code_start":12,"english_end":9,"english_start":5},{"label":"cleanup","code_end":14,"code_start":14,"english_end":9,"english_start":5},{"label":"cleanup","code_end":15,"code_start":15,"english_end":9,"english_start":5},{"label":"cleanup","code_end":16,"code_start":16,"english_end":9,"english_start":5},{"label":"cleanup","code_end":17,"code_start":17,"english_end":9,"english_start":5},{"label":"cleanup","code_end":18,"code_start":18,"english_end":9,"english_start":5}],"structure":"{\"functions\":[{\"name\":\"blink\",\"params\":[],\"english_start\":5,\"english_end\":9,\"summary\":\"Turn the LED on, wait one second, turn it off, then wait one second.\",\"calls\":[{\"english_start\":7,\"english_end\":7},{\"english_start\":9,\"english_end\":9}]}]}"},"python":{"code":"import time\nimport RPi.GPIO as GPIO\n\nGPIO.setmode(GPIO.BCM)\nGPIO.setup(12, GPIO.OUT)\ntry:\n    while True:\n        GPIO.output(12, GPIO.HIGH)\n        time.sleep(1)\n        GPIO.output(12, GPIO.LOW)\n        time.sleep(1)\nfinally:\n    GPIO.cleanup()\n\nif __name__ == \"__main__\":\n    pass","links":[{"label":"import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"import","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"loop","code_end":6,"code_start":6,"english_end":9,"english_start":5},{"label":"loop","code_end":7,"code_start":7,"english_end":9,"english_start":5},{"label":"output_high","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"sleep","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"output_low","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"sleep","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"cleanup","code_end":12,"code_start":12,"english_end":9,"english_start":5},{"label":"cleanup","code_end":13,"code_start":13,"english_end":9,"english_start":5},{"label":"entry","code_end":15,"code_start":15,"english_end":9,"english_start":5},{"label":"entry","code_end":16,"code_start":16,"english_end":9,"english_start":5}],"structure":"{\"functions\":[]}"}}},{"slug":"ctc-02-button","title":"Crack the Code · PRP #02 — Button → LED (D7 → D12)","description":"Use the ThinkerShield's pushbutton on D7 to switch the D12 LED on and off — digitalRead and an if/else.","english":"Light the LED on pin 12 while the pushbutton on pin 7 is pressed; turn it off when the button is released.\n\nCall pin 7 \"buttonPin\" and pin 12 \"ledPin\". Keep an integer \"buttonState\" for the current button reading, starting at 0.\n\nSet ledPin as an output and buttonPin as an input.\n\nForever:\n  Read buttonPin into buttonState.\n  If buttonState is HIGH (the button is pressed): turn ledPin on.\n  Otherwise: turn ledPin off.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"int buttonPin = 7;        // the pushbutton is on pin D7 of the ThinkerShield\nint ledPin = 12;          // the LED is on pin D12\nint buttonState = 0;      // variable for reading the pushbutton's state\n\nvoid setup() {\n  pinMode(ledPin, OUTPUT);     // the LED pin is an output\n  pinMode(buttonPin, INPUT);   // the button pin is an input\n}\n\nvoid loop() {\n  buttonState = digitalRead(buttonPin);   // read the button\n  if (buttonState == HIGH) {              // is it pressed?\n    digitalWrite(ledPin, HIGH);           // yes -> LED on\n  } else {\n    digitalWrite(ledPin, LOW);            // no  -> LED off\n  }\n}\n","links":[],"structure":null},"python":{"code":"from machine import Pin\nbuttonPin = Pin(7, Pin.IN)\nledPin = Pin(12, Pin.OUT)\nbuttonState = 0\n\nwhile True:\n    buttonState = buttonPin.value()\n    if buttonState == 1:\n        ledPin.value(1)\n    else:\n        ledPin.value(0)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"declaration","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"declaration","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"loop","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"assignment","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"if","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"then","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"else","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"else_body","code_end":11,"code_start":11,"english_end":10,"english_start":10}],"structure":"{\"functions\":[]}"},"ruby":{"code":"buttonPin = 7\nledPin = 12\nbuttonState = 0\npin_mode(ledPin, OUTPUT)\npin_mode(buttonPin, INPUT)\nloop do\nbuttonState = digital_read(buttonPin)\nif buttonState == HIGH\ndigital_write(ledPin, HIGH)\nelse\ndigital_write(ledPin, LOW)\nend","links":[{"label":"assignment","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"assignment","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"assignment","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"statement","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"statement","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"control","code_end":6,"code_start":6,"english_end":10,"english_start":7},{"label":"statement","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"control","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"statement","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"control","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"statement","code_end":11,"code_start":11,"english_end":10,"english_start":10},{"label":"control","code_end":12,"code_start":12,"english_end":10,"english_start":7}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const { Board, Led, Button } = require('johnny-five');\nconst buttonPin = 7;\nconst ledPin = 12;\nlet buttonState = 0;\nconst board = new Board();\nboard.on('ready', () => {\n  const led = new Led(ledPin);\n  const button = new Button(buttonPin);\n  const updateLed = () => {\n    buttonState = button.isPressed ? 1 : 0;\n    if (buttonState === 1) {\n      led.on();\n    } else {\n      led.off();\n  };\n  setInterval(updateLed, 10);\n});","links":[{"label":"import hardware library","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"set button pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"set led pin","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"initialize button state","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"create board","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"board ready handler","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"configure led as output","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"configure button as input","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"start loop","code_end":9,"code_start":9,"english_end":10,"english_start":8},{"label":"read button state","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"pressed branch","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"turn led on","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"released branch","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"turn led off","code_end":14,"code_start":14,"english_end":10,"english_start":10},{"label":"end loop","code_end":15,"code_start":15,"english_end":10,"english_start":7},{"label":"repeat forever","code_end":16,"code_start":16,"english_end":10,"english_start":7},{"label":"close board ready handler","code_end":17,"code_start":17,"english_end":10,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"updateLed\",\"params\":[],\"english_start\":8,\"english_end\":10,\"summary\":\"Reads the button state and turns the LED on while pressed, otherwise off.\",\"calls\":[]}]}"}}},{"slug":"ctc-03-int","title":"Crack the Code · PRP #02 — The int command","description":"Blink, rewritten to give pin 12 the name LED with the int command — clearer code, and you only change a pin in one place.","english":"Blink the LED — but give pin 12 a name first, so the rest of the code reads more clearly and you only have one place to change if the wiring moves.\n\nCall pin 12 \"LED\".\n\nSet LED as an output.\n\nForever:\n  Turn LED on.\n  Wait one second.\n  Turn LED off.\n  Wait one second.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"LED = 12\nprint(\"Set LED as an output.\")\nwhile True:\n    print(\"Turn LED on.\")\n    time.sleep(1)\n    print(\"Turn LED off.\")\n    time.sleep(1)","links":[{"label":"assign name to pin 12","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"set LED as output","code_end":2,"code_start":2,"english_end":5,"english_start":5},{"label":"forever loop","code_end":3,"code_start":3,"english_end":7,"english_start":7},{"label":"turn LED on","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"wait one second","code_end":5,"code_start":5,"english_end":9,"english_start":9},{"label":"turn LED off","code_end":6,"code_start":6,"english_end":10,"english_start":10},{"label":"wait one second","code_end":7,"code_start":7,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"ruby":{"code":"# Blink the LED, but give pin 12 a name first, so the rest of the code reads more clearly and you only have one place to change if the wiring moves.\nLED = 12\n# Set LED as an output.\nloop do\n  puts \"LED on\"\n  sleep 1\n  puts \"LED off\"\n  sleep 1\nend","links":[{"label":"comment","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"constant","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"comment","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"loop_start","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"on","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"wait_on","code_end":6,"code_start":6,"english_end":9,"english_start":9},{"label":"off","code_end":7,"code_start":7,"english_end":10,"english_start":10},{"label":"wait_off","code_end":8,"code_start":8,"english_end":11,"english_start":11},{"label":"loop_end","code_end":9,"code_start":9,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const { Board, Led } = require('johnny-five');\nconst LED_PIN = 12;\nconst board = new Board();\nboard.on('ready', () => {\n  const LED = new Led(LED_PIN);\n  LED.on();\n  setInterval(() => {\n    LED.on();\n    setTimeout(() => {\n      LED.off();\n      setTimeout(() => {\n      }, 1000);\n    }, 1000);\n  }, 2000);\n});","links":[{"label":"import hardware library","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"name pin 12","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"create board","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"forever setup start","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"create led from named pin","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"set led as output and initial state","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"forever loop start","code_end":7,"code_start":7,"english_end":11,"english_start":7},{"label":"turn led on","code_end":8,"code_start":8,"english_end":11,"english_start":8},{"label":"wait one second before turning off","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"turn led off","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"wait one second before next cycle","code_end":11,"code_start":11,"english_end":11,"english_start":11},{"label":"end wait","code_end":12,"code_start":12,"english_end":11,"english_start":11},{"label":"end off delay","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"repeat forever","code_end":14,"code_start":14,"english_end":11,"english_start":7},{"label":"close board ready handler","code_end":15,"code_start":15,"english_end":11,"english_start":7}],"structure":"{\"functions\":[]}"},"cpp":{"code":"int LED = 12;             // call pin 12 \"LED\" for the rest of this sketch\n\nvoid setup() {\n  pinMode(LED, OUTPUT);   // make the LED pin an output\n}\n\nvoid loop() {             // runs over and over again, forever\n  digitalWrite(LED, HIGH);  // turn the LED on\n  delay(1000);              // wait for one second\n  digitalWrite(LED, LOW);   // turn the LED off\n  delay(1000);              // wait for one second\n}\n","links":[],"structure":null}}},{"slug":"ctc-05-analog-input","title":"Crack the Code · PRP #03 — Analog input (A5 → blink rate)","description":"Read the ThinkerShield's potentiometer on A5 with analogRead, use the value to set the LED's blink rate, and print it to the Serial Monitor.","english":"Read the potentiometer on analog pin A5, use its value to set the blink rate of the LED on pin 12, and print the reading to the serial port.\n\nCall A5 \"sensorPin\" and pin 12 \"ledPin\". Keep an integer \"sensorValue\" for the latest reading, starting at 0.\n\nSet ledPin as an output. Start the serial connection at 9600 baud so we can print the sensor value.\n\nForever:\n  Read the analog value on sensorPin into sensorValue (it'll be 0 to 1023).\n  Turn the LED on.\n  Wait sensorValue milliseconds.\n  Turn the LED off.\n  Wait sensorValue milliseconds again.\n  Print \"The sensor value is: \" followed by sensorValue to the serial port.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"int sensorPin = A5;       // the potentiometer (POT A5) on the ThinkerShield\nint ledPin = 12;          // the LED on pin D12\nint sensorValue = 0;      // variable to store the value from the sensor\n\nvoid setup() {\n  pinMode(ledPin, OUTPUT);  // the LED pin is an output\n  Serial.begin(9600);       // start serial so we can print the sensor value\n}\n\nvoid loop() {\n  sensorValue = analogRead(sensorPin);  // read the knob (0 to 1023)\n  digitalWrite(ledPin, HIGH);           // LED on\n  delay(sensorValue);                   // wait — bigger value, longer wait\n  digitalWrite(ledPin, LOW);            // LED off\n  delay(sensorValue);                   // wait again\n  Serial.print(\"The sensor value is: \");\n  Serial.println(sensorValue);          // print the value to the Serial Monitor\n}\n","links":[],"structure":null},"python":{"code":"sensorPin = 'A5'\nledPin = 12\nsensorValue = 0\n\nimport random\nimport time\n\ndef serial_begin(baud):\n    pass\n\nserial_begin(9600)\n\nwhile True:\n    sensorValue = random.randint(0, 1023)\n    print(f'LED on pin {ledPin} ON')\n    time.sleep(sensorValue / 1000.0)\n    print(f'LED on pin {ledPin} OFF')\n    time.sleep(sensorValue / 1000.0)\n    print(f'The sensor value is: {sensorValue}')","links":[{"label":"assignment","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"assignment","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"assignment","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"import","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"import","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"function","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"function_body","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"call","code_end":11,"code_start":11,"english_end":5,"english_start":5},{"label":"loop","code_end":13,"code_start":13,"english_end":13,"english_start":7},{"label":"assignment","code_end":14,"code_start":14,"english_end":8,"english_start":8},{"label":"print","code_end":15,"code_start":15,"english_end":9,"english_start":9},{"label":"sleep","code_end":16,"code_start":16,"english_end":10,"english_start":10},{"label":"print","code_end":17,"code_start":17,"english_end":11,"english_start":11},{"label":"sleep","code_end":18,"code_start":18,"english_end":12,"english_start":12},{"label":"print","code_end":19,"code_start":19,"english_end":13,"english_start":13}],"structure":"{\"functions\":[{\"name\":\"serial_begin\",\"params\":[\"baud\"],\"english_start\":5,\"english_end\":5,\"summary\":\"Placeholder for starting the serial connection.\",\"calls\":[]}]}"},"ruby":{"code":"sensorPin = :A5\nledPin = 12\nsensorValue = 0\npinMode(ledPin, :output)\nserialBegin(9600)\nloop do\n  sensorValue = analogRead(sensorPin)\n  digitalWrite(ledPin, :high)\n  sleep(sensorValue / 1000.0)\n  digitalWrite(ledPin, :low)\n  sleep(sensorValue / 1000.0)\n  serialPrintln(\"The sensor value is: #{sensorValue}\")\nend","links":[{"label":"assignment","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"assignment","code_end":2,"code_start":2,"english_end":1,"english_start":1},{"label":"assignment","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"statement","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"statement","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"loop_start","code_end":6,"code_start":6,"english_end":13,"english_start":7},{"label":"statement","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"statement","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"statement","code_end":9,"code_start":9,"english_end":10,"english_start":10},{"label":"statement","code_end":10,"code_start":10,"english_end":11,"english_start":11},{"label":"statement","code_end":11,"code_start":11,"english_end":12,"english_start":12},{"label":"statement","code_end":12,"code_start":12,"english_end":13,"english_start":13},{"label":"loop_end","code_end":13,"code_start":13,"english_end":13,"english_start":7}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const sensorPin = 'A5';\nconst ledPin = 12;\nlet sensorValue = 0;\n\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconsole.log('Serial started at 9600 baud');\nconsole.log(`Pin ${ledPin} set as output`);\n(async () => {\n  while (true) {\n    sensorValue = Math.floor(Math.random() * 1024);\n    console.log(`LED ${ledPin} ON`);\n    await sleep(sensorValue);\n    console.log(`LED ${ledPin} OFF`);\n    await sleep(sensorValue);\n    console.log(`The sensor value is: ${sensorValue}`);\n  }\n})();","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"declaration","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"helper","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"setup","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"setup","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"loop_start","code_end":9,"code_start":9,"english_end":13,"english_start":7},{"label":"loop","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"read_sensor","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"led_on","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"delay","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"led_off","code_end":14,"code_start":14,"english_end":11,"english_start":11},{"label":"delay","code_end":15,"code_start":15,"english_end":12,"english_start":12},{"label":"print","code_end":16,"code_start":16,"english_end":13,"english_start":13},{"label":"loop_end","code_end":17,"code_start":17,"english_end":13,"english_start":8},{"label":"loop_end","code_end":18,"code_start":18,"english_end":13,"english_start":7}],"structure":"{\"functions\":[]}"}}},{"slug":"ctc-07-buzzer1","title":"Crack the Code · PRP #04 — Buzzer (D3)","description":"Beep the ThinkerShield's piezo buzzer on D3 with the tone(pin, frequency, duration) command.","english":"Beep the piezo buzzer on pin 3 a few times a second, forever.\n\nCall pin 3 \"buzzerPin\".\n\nSet buzzerPin as an output.\n\nForever:\n  Play a 600 Hz tone on buzzerPin for 30 milliseconds.\n  Wait 150 milliseconds before repeating.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"int buzzerPin = 3;        // the piezo buzzer is on pin D3 of the ThinkerShield\n\nvoid setup() {\n  pinMode(buzzerPin, OUTPUT);   // the buzzer pin is an output\n}\n\nvoid loop() {\n  tone(buzzerPin, 600, 30);     // play a 600 Hz tone for 30 ms...\n  delay(150);                   // ...then wait 150 ms before repeating\n}\n","links":[],"structure":null},"python":{"code":"buzzerPin = 3\nfrom machine import Pin, PWM\nbuzzerPin = Pin(buzzerPin, Pin.OUT)\nif __name__ == \"__main__\":\n    while True:\n        buzzer = PWM(buzzerPin)\n        buzzer.freq(600)\n        buzzer.duty_u16(32768)\n        import time\n        time.sleep_ms(30)\n        buzzer.deinit()\n        time.sleep_ms(150)","links":[{"label":"assignment","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"import","code_end":2,"code_start":2,"english_end":5,"english_start":5},{"label":"setup_pin","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"entry_point","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"loop","code_end":5,"code_start":5,"english_end":7,"english_start":7},{"label":"tone_setup","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"tone_freq","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"tone_on","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"import_time","code_end":9,"code_start":9,"english_end":8,"english_start":8},{"label":"tone_duration","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"tone_off","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"pause","code_end":12,"code_start":12,"english_end":9,"english_start":9}],"structure":"{\"functions\":[]}"},"ruby":{"code":"buzzerPin = 3\npinMode(buzzerPin, OUTPUT)\nloop do\n  tone(buzzerPin, 600, 30)\n  sleep 0.15\nend","links":[{"label":"declare buzzer pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"set pin as output","code_end":2,"code_start":2,"english_end":5,"english_start":5},{"label":"start forever loop","code_end":3,"code_start":3,"english_end":7,"english_start":7},{"label":"play tone","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"wait before repeating","code_end":5,"code_start":5,"english_end":9,"english_start":9},{"label":"end forever loop","code_end":6,"code_start":6,"english_end":9,"english_start":7}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const buzzerPin = 3;\nconsole.log(`Setting buzzerPin (${buzzerPin}) as an output.`);\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\nconst playTone = async () => {\n  console.log(`Playing a 600 Hz tone on buzzerPin for 30 milliseconds.`);\n  await sleep(30);\n};\n\n(async () => {\n  while (true) {\n    await playTone();\n    await sleep(150);\n  }\n})();","links":[{"label":"declare buzzer pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"set pin as output","code_end":2,"code_start":2,"english_end":5,"english_start":5},{"label":"sleep helper","code_end":3,"code_start":3,"english_end":9,"english_start":8},{"label":"start tone function","code_end":4,"code_start":4,"english_end":8,"english_start":8},{"label":"tone on message","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"tone duration","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"end tone function","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"start forever loop","code_end":9,"code_start":9,"english_end":9,"english_start":7},{"label":"infinite loop","code_end":10,"code_start":10,"english_end":9,"english_start":7},{"label":"play tone each cycle","code_end":11,"code_start":11,"english_end":9,"english_start":7},{"label":"wait between tones","code_end":12,"code_start":12,"english_end":9,"english_start":7},{"label":"close infinite loop","code_end":13,"code_start":13,"english_end":9,"english_start":7},{"label":"run forever loop","code_end":14,"code_start":14,"english_end":9,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"sleep\",\"params\":[\"ms\"],\"english_start\":8,\"english_end\":9,\"summary\":\"Wait for the given number of milliseconds.\",\"calls\":[{\"english_start\":8,\"english_end\":9}]},{\"name\":\"playTone\",\"params\":[],\"english_start\":8,\"english_end\":8,\"summary\":\"Log a 600 Hz buzzer tone action and hold it for 30 milliseconds.\",\"calls\":[{\"english_start\":8,\"english_end\":9}]}]}"}}},{"slug":"ctc-08-buzzer2-alarm","title":"Crack the Code · PRP #04 — Two-tone alarm","description":"Alternate a low tone and a high tone so the buzzer sounds like an alarm — a drop-in alarm sounder for the design project.","english":"Make the piezo buzzer on pin 3 sound like a two-tone alarm — alternating a low tone and a high tone, half a second each.\n\nKeep an integer lowTone equal to 400 (Hz) and an integer highTone equal to 600 (Hz). Use a constant ALARMSOUNDER to remember the buzzer is on pin 3.\n\nSet ALARMSOUNDER as an output.\n\nForever:\n  Play the low tone on ALARMSOUNDER for 500 milliseconds.\n  Wait 500 milliseconds.\n  Play the high tone on ALARMSOUNDER for 500 milliseconds.\n  Wait 500 milliseconds.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"from time import sleep\n\nlowTone = 400\nhighTone = 600\nALARMSOUNDER = 3\n\ndef set_output(pin):\n    pass\n\nwhile True:\n    print(f\"tone {lowTone} Hz on pin {ALARMSOUNDER}\")\n    sleep(0.5)\n    print(f\"tone {highTone} Hz on pin {ALARMSOUNDER}\")\n    sleep(0.5)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"assign","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"assign","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"assign","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"function_def","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"function_body","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"loop","code_end":10,"code_start":10,"english_end":11,"english_start":8},{"label":"statement","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"statement","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"statement","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"statement","code_end":14,"code_start":14,"english_end":10,"english_start":10}],"structure":"{\"functions\":[{\"name\":\"set_output\",\"params\":[\"pin\"],\"english_start\":5,\"english_end\":5,\"summary\":\"Placeholder for setting the buzzer pin as an output.\",\"calls\":[]}]}"},"ruby":{"code":"ALARMSOUNDER = 3\nlowTone = 400\nhighTone = 600\n\nputs \"Set pin #{ALARMSOUNDER} as an output\"\n\nloop do\n  puts \"Playing low tone #{lowTone} Hz on pin #{ALARMSOUNDER} for 500 ms\"\n  sleep 0.5\n  puts \"Playing high tone #{highTone} Hz on pin #{ALARMSOUNDER} for 500 ms\"\n  sleep 0.5\nend","links":[{"label":"constant","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"variable","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"variable","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"output","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"loop_start","code_end":7,"code_start":7,"english_end":11,"english_start":7},{"label":"action","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"wait","code_end":9,"code_start":9,"english_end":9,"english_start":8},{"label":"action","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"wait","code_end":11,"code_start":11,"english_end":11,"english_start":10},{"label":"loop_end","code_end":12,"code_start":12,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const ALARMSOUNDER = 3;\nconst lowTone = 400;\nconst highTone = 600;\npinMode(ALARMSOUNDER, OUTPUT);\nsetInterval(() => {\n  tone(ALARMSOUNDER, lowTone, 500);\n  setTimeout(() => {\n    tone(ALARMSOUNDER, highTone, 500);\n  }, 500);\n}, 1000);","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"declaration","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"loop_start","code_end":5,"code_start":5,"english_end":11,"english_start":7},{"label":"low_tone","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"delay_start","code_end":7,"code_start":7,"english_end":9,"english_start":9},{"label":"high_tone","code_end":8,"code_start":8,"english_end":10,"english_start":10},{"label":"delay_end","code_end":9,"code_start":9,"english_end":11,"english_start":11},{"label":"loop_end","code_end":10,"code_start":10,"english_end":11,"english_start":11}],"structure":"{\"functions\":[]}"},"cpp":{"code":"int lowTone = 400;\nint highTone = 600;\nconst int ALARMSOUNDER = 3;     // the buzzer is on pin D3\n\nvoid setup() {\n  pinMode(ALARMSOUNDER, OUTPUT);\n}\n\nvoid loop() {\n  tone(ALARMSOUNDER, lowTone, 500);   // low tone for half a second\n  delay(500);\n  tone(ALARMSOUNDER, highTone, 500);  // high tone for half a second\n  delay(500);\n}\n","links":[],"structure":null}}},{"slug":"ctc-09-buzzer3-sweep","title":"Crack the Code · PRP #04 extension — Tone sweep with a for loop","description":"Use a for loop to sweep the buzzer's tone smoothly up and back down — for loops are beyond the core unit, so this is an extension.","english":"Sweep the piezo buzzer's pitch smoothly up and back down, forever, using a for loop.\n\nUse a constant ALARMSOUNDER to remember the buzzer is on pin 3. Keep an integer i starting at 200.\n\nSet ALARMSOUNDER as an output.\n\nForever:\n  For i from 200 up to (but not including) 700, stepping up by 2 each time:\n    Play the tone i Hz on ALARMSOUNDER for 10 milliseconds.\n    Wait 10 milliseconds.\n  For i from 701 back down to (but not including) 200, stepping down by 2 each time:\n    Play the tone i Hz on ALARMSOUNDER for 10 milliseconds.\n    Wait 10 milliseconds.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"int i = 200;\nconst int ALARMSOUNDER = 3;     // the buzzer is on pin D3\n\nvoid setup() {\n  pinMode(ALARMSOUNDER, OUTPUT);\n}\n\nvoid loop() {\n  for (i = 200; i < 700; i = i + 2) {   // sweep from a low tone up to a high tone\n    tone(ALARMSOUNDER, i, 10);          // play the tone, changing every 10 ms\n    delay(10);\n  }\n  for (i = 701; i > 200; i = i - 2) {   // sweep back down\n    tone(ALARMSOUNDER, i, 10);\n    delay(10);\n  }\n}\n","links":[],"structure":null},"python":{"code":"from machine import Pin, PWM\n\nALARMSOUNDER = 3\ni = 200\nbuzzer = PWM(Pin(ALARMSOUNDER))\nbuzzer.duty_u16(32768)\n\nwhile True:\n    for i in range(200, 700, 2):\n        buzzer.freq(i)\n        import time; time.sleep(0.01)\n    for i in range(701, 200, -2):\n        buzzer.freq(i)\n        import time; time.sleep(0.01)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"constant","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"initialize","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"setup","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"loop","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"up_sweep","code_end":9,"code_start":9,"english_end":10,"english_start":8},{"label":"tone","code_end":10,"code_start":10,"english_end":10,"english_start":9},{"label":"wait","code_end":11,"code_start":11,"english_end":10,"english_start":9},{"label":"down_sweep","code_end":12,"code_start":12,"english_end":13,"english_start":11},{"label":"tone","code_end":13,"code_start":13,"english_end":13,"english_start":12},{"label":"wait","code_end":14,"code_start":14,"english_end":13,"english_start":12}],"structure":"{\"functions\":[]}"},"ruby":{"code":"ALARMSOUNDER = 3\ni = 200\npin_mode(ALARMSOUNDER, :output)\nloop do\n  (200...700).step(2) do |i|\n    tone(ALARMSOUNDER, i, 10)\n    sleep(0.01)\n  end\n  (701...200).step(-2) do |i|\n    tone(ALARMSOUNDER, i, 10)\n    sleep(0.01)\n  end\nend","links":[{"label":"declare constant","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"initialize counter","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"set output mode","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"forever loop start","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"rising sweep loop","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"play tone","code_end":6,"code_start":6,"english_end":9,"english_start":9},{"label":"wait","code_end":7,"code_start":7,"english_end":10,"english_start":10},{"label":"end rising sweep loop","code_end":8,"code_start":8,"english_end":8,"english_start":8},{"label":"falling sweep loop","code_end":9,"code_start":9,"english_end":11,"english_start":11},{"label":"play tone","code_end":10,"code_start":10,"english_end":12,"english_start":12},{"label":"wait","code_end":11,"code_start":11,"english_end":13,"english_start":13},{"label":"end falling sweep loop","code_end":12,"code_start":12,"english_end":11,"english_start":11},{"label":"forever loop end","code_end":13,"code_start":13,"english_end":7,"english_start":7}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const ALARMSOUNDER = 3;\nlet i = 200;\nconst setOutput = (pin) => {\n  console.log(`Set pin ${pin} as output`);\n};\nsetOutput(ALARMSOUNDER);\nconst sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst playTone = async (pin, frequency, duration) => {\n  console.log(`Play tone ${frequency} Hz on pin ${pin} for ${duration} ms`);\n  await sleep(duration);\n};\n\n(async () => {\n  for (i = 200; i < 700; i += 2) {\n    await playTone(ALARMSOUNDER, i, 10);\n    await sleep(10);\n  }\n  for (i = 701; i >= 200; i -= 2) {\n    await playTone(ALARMSOUNDER, i, 10);\n    await sleep(10);\n  }\n})();","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"function","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"statement","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"function_end","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"call","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"helper","code_end":7,"code_start":7,"english_end":13,"english_start":7},{"label":"function","code_end":9,"code_start":9,"english_end":13,"english_start":7},{"label":"statement","code_end":10,"code_start":10,"english_end":12,"english_start":9},{"label":"statement","code_end":11,"code_start":11,"english_end":13,"english_start":7},{"label":"function_end","code_end":12,"code_start":12,"english_end":13,"english_start":7},{"label":"loop","code_end":14,"code_start":14,"english_end":13,"english_start":7},{"label":"for_up","code_end":15,"code_start":15,"english_end":10,"english_start":8},{"label":"tone","code_end":16,"code_start":16,"english_end":10,"english_start":9},{"label":"wait","code_end":17,"code_start":17,"english_end":10,"english_start":9},{"label":"for_end","code_end":18,"code_start":18,"english_end":10,"english_start":8},{"label":"for_down","code_end":19,"code_start":19,"english_end":13,"english_start":11},{"label":"tone","code_end":20,"code_start":20,"english_end":13,"english_start":12},{"label":"wait","code_end":21,"code_start":21,"english_end":13,"english_start":12},{"label":"for_end","code_end":22,"code_start":22,"english_end":13,"english_start":11},{"label":"end","code_end":23,"code_start":23,"english_end":13,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"setOutput\",\"params\":[\"pin\"],\"english_start\":5,\"english_end\":5,\"summary\":\"Marks the buzzer pin as output.\",\"calls\":[]},{\"name\":\"sleep\",\"params\":[\"ms\"],\"english_start\":7,\"english_end\":13,\"summary\":\"Returns a promise that resolves after a delay.\",\"calls\":[]},{\"name\":\"playTone\",\"params\":[\"pin\",\"frequency\",\"duration\"],\"english_start\":9,\"english_end\":12,\"summary\":\"Logs a tone playback and waits for its duration.\",\"calls\":[{\"english_start\":7,\"english_end\":13}]}]}"}}},{"slug":"ctc-10-alarm-basic","title":"Crack the Code · Design project — Basic box alarm","description":"Worked model for the design brief: a switch on the box arms the alarm after a short exit delay; opening the box flashes an LED and sounds the buzzer.","english":"A simple box alarm. After a short exit delay the alarm arms itself with a double-beep. When the box is opened (the switch on pin 7 reads LOW) the alarm triggers — the LED on pin 13 lights up and the buzzer alternates between two tones, forever.\n\nCall pin 7 \"sensorPin\" (the switch on the box), pin 13 \"flashPin\" (the LED that lights up when the alarm sounds), and pin 3 \"buzzerPin\". Keep an integer Status starting at 0 (0 = exit delay, 1 = armed, 2 = triggered), and an integer sensor starting at 0 for the current sensor reading.\n\nSet sensorPin as an input, and flashPin and buzzerPin as outputs.\n\nForever:\n  If Status is 0 — first time through the loop, so arm the alarm:\n    Wait 3 seconds (gives you 3 seconds to close the box).\n    Play a 725 Hz tone on buzzerPin for 40 ms.\n    Wait 200 ms.\n    Play another 725 Hz tone on buzzerPin for 40 ms — a double-beep that confirms it's armed.\n    Set Status to 1.\n\n  If Status is 1: read sensorPin into the sensor variable.\n\n  If sensor is 0 (the box has been opened): set Status to 2.\n\n  If Status is 2 — triggered, so flash the LED and sound the alarm:\n    Turn flashPin on (HIGH).\n    Play a 725 Hz tone on buzzerPin for 1000 milliseconds.\n    Wait 1000 milliseconds.\n    Play a 330 Hz tone on buzzerPin for 1000 milliseconds.\n    Wait 1000 milliseconds.\n","app_html":"","settings":{},"by_lang":{"python":{"code":"from time import sleep\nfrom gpiozero import DigitalInputDevice, LED, TonalBuzzer, Tone\n\nsensorPin = DigitalInputDevice(7, pull_up=True)\nflashPin = LED(13)\nbuzzerPin = TonalBuzzer(3)\nStatus = 0\nsensor = 0\nsensorPin.close()\nflashPin.close()\nbuzzerPin.close()\nsensorPin = DigitalInputDevice(7, pull_up=True)\nflashPin = LED(13)\nbuzzerPin = TonalBuzzer(3)\nif __name__ == \"__main__\":\n    while True:\n        if Status == 0:\n            sleep(3)\n            buzzerPin.play(Tone(725))\n            sleep(0.04)\n            buzzerPin.stop()\n            sleep(0.2)\n            buzzerPin.play(Tone(725))\n            sleep(0.04)\n            buzzerPin.stop()\n            Status = 1\n        if Status == 1:\n            sensor = 0 if sensorPin.value else 1\n            if sensor == 0:\n                Status = 2\n        if Status == 2:\n            flashPin.on()\n            buzzerPin.play(Tone(725))\n            sleep(1)\n            buzzerPin.stop()\n            sleep(1)\n            buzzerPin.play(Tone(330))\n            sleep(1)\n            buzzerPin.stop()\n            sleep(1)","links":[{"label":"import","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"import","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"setup","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"setup","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"state","code_end":7,"code_start":7,"english_end":3,"english_start":3},{"label":"state","code_end":8,"code_start":8,"english_end":3,"english_start":3},{"label":"setup","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"setup","code_end":10,"code_start":10,"english_end":5,"english_start":5},{"label":"setup","code_end":11,"code_start":11,"english_end":5,"english_start":5},{"label":"setup","code_end":12,"code_start":12,"english_end":5,"english_start":5},{"label":"setup","code_end":13,"code_start":13,"english_end":5,"english_start":5},{"label":"setup","code_end":14,"code_start":14,"english_end":5,"english_start":5},{"label":"entry","code_end":15,"code_start":15,"english_end":24,"english_start":7},{"label":"loop","code_end":16,"code_start":16,"english_end":24,"english_start":7},{"label":"branch","code_end":17,"code_start":17,"english_end":13,"english_start":8},{"label":"delay","code_end":18,"code_start":18,"english_end":9,"english_start":9},{"label":"tone","code_end":19,"code_start":19,"english_end":10,"english_start":10},{"label":"delay","code_end":20,"code_start":20,"english_end":11,"english_start":10},{"label":"tone","code_end":21,"code_start":21,"english_end":12,"english_start":10},{"label":"delay","code_end":22,"code_start":22,"english_end":11,"english_start":11},{"label":"tone","code_end":23,"code_start":23,"english_end":12,"english_start":12},{"label":"delay","code_end":24,"code_start":24,"english_end":12,"english_start":12},{"label":"tone","code_end":25,"code_start":25,"english_end":12,"english_start":12},{"label":"state","code_end":26,"code_start":26,"english_end":13,"english_start":13},{"label":"branch","code_end":27,"code_start":27,"english_end":17,"english_start":15},{"label":"read","code_end":28,"code_start":28,"english_end":15,"english_start":15},{"label":"branch","code_end":29,"code_start":29,"english_end":17,"english_start":17},{"label":"state","code_end":30,"code_start":30,"english_end":17,"english_start":17},{"label":"branch","code_end":31,"code_start":31,"english_end":24,"english_start":19},{"label":"output","code_end":32,"code_start":32,"english_end":20,"english_start":20},{"label":"tone","code_end":33,"code_start":33,"english_end":21,"english_start":21},{"label":"delay","code_end":34,"code_start":34,"english_end":22,"english_start":21},{"label":"tone","code_end":35,"code_start":35,"english_end":22,"english_start":21},{"label":"delay","code_end":36,"code_start":36,"english_end":22,"english_start":22},{"label":"tone","code_end":37,"code_start":37,"english_end":23,"english_start":23},{"label":"delay","code_end":38,"code_start":38,"english_end":24,"english_start":23},{"label":"tone","code_end":39,"code_start":39,"english_end":24,"english_start":23},{"label":"delay","code_end":40,"code_start":40,"english_end":24,"english_start":24}],"structure":"{\"functions\":[]}"},"cpp":{"code":"int sensorPin = 7;    // the sensor (a switch on the box) connects to pin 7\nint flashPin = 13;    // an LED that lights up when the alarm sounds\nint buzzerPin = 3;    // the buzzer connects to pin 3\nint Status = 0;       // 0 = exit delay, 1 = armed, 2 = triggered\nint sensor = 0;       // the current sensor reading\n\nvoid setup() {\n  pinMode(sensorPin, INPUT);\n  pinMode(flashPin, OUTPUT);\n  pinMode(buzzerPin, OUTPUT);\n}\n\nvoid loop() {\n  if (Status == 0) {            // first time through the loop — arm the alarm\n    delay(3000);                // gives you 3 seconds to close the box\n    tone(buzzerPin, 725, 40);   // a short beep...\n    delay(200);\n    tone(buzzerPin, 725, 40);   // ...and another, so it double-beeps when armed\n    Status = 1;                 // armed — don't run this block again\n  }\n  if (Status == 1) {\n    sensor = digitalRead(sensorPin);   // read the switch\n  }\n  if (sensor == 0) {            // the box has been opened\n    Status = 2;\n  }\n  if (Status == 2) {            // triggered — flash the LED and sound the alarm\n    digitalWrite(flashPin, HIGH);\n    tone(buzzerPin, 725, 1000);\n    delay(1000);\n    tone(buzzerPin, 330, 1000);\n    delay(1000);\n  }\n}\n","links":[],"structure":null},"ruby":{"code":"def pinMode(pin, mode)\nend\ndef digitalRead(pin)\n  1\nend\ndef digitalWrite(pin, value)\nend\ndef tone(pin, frequency, duration_ms)\nend\nsensorPin = 7\nflashPin = 13\nbuzzerPin = 3\nstatus = 0\nsensor = 0\npinMode(sensorPin, :input)\npinMode(flashPin, :output)\npinMode(buzzerPin, :output)\nloop do\n  if status == 0\n    sleep 3\n    tone(buzzerPin, 725, 40)\n    sleep 0.2\n    tone(buzzerPin, 725, 40)\n    status = 1\n  end\n  if status == 1\n    sensor = digitalRead(sensorPin)\n  end\n  if sensor == 0\n    status = 2\n  end\n  if status == 2\n    digitalWrite(flashPin, :high)\n    tone(buzzerPin, 725, 1000)\n    sleep 1\n    tone(buzzerPin, 330, 1000)\n    sleep 1\n  end\nend","links":[{"label":"hardware stub","code_end":2,"code_start":1,"english_end":1,"english_start":1},{"label":"hardware stub","code_end":5,"code_start":3,"english_end":1,"english_start":1},{"label":"hardware stub","code_end":7,"code_start":6,"english_end":1,"english_start":1},{"label":"hardware stub","code_end":9,"code_start":8,"english_end":1,"english_start":1},{"label":"pin name","code_end":10,"code_start":10,"english_end":3,"english_start":3},{"label":"pin name","code_end":11,"code_start":11,"english_end":3,"english_start":3},{"label":"pin name","code_end":12,"code_start":12,"english_end":3,"english_start":3},{"label":"state","code_end":13,"code_start":13,"english_end":3,"english_start":3},{"label":"state","code_end":14,"code_start":14,"english_end":3,"english_start":3},{"label":"setup input","code_end":15,"code_start":15,"english_end":5,"english_start":5},{"label":"setup output","code_end":16,"code_start":16,"english_end":5,"english_start":5},{"label":"setup output","code_end":17,"code_start":17,"english_end":5,"english_start":5},{"label":"main loop","code_end":18,"code_start":18,"english_end":7,"english_start":7},{"label":"arm on first pass","code_end":19,"code_start":19,"english_end":8,"english_start":8},{"label":"exit delay","code_end":20,"code_start":20,"english_end":9,"english_start":9},{"label":"first beep","code_end":21,"code_start":21,"english_end":10,"english_start":10},{"label":"beep gap","code_end":22,"code_start":22,"english_end":11,"english_start":11},{"label":"second beep","code_end":23,"code_start":23,"english_end":12,"english_start":12},{"label":"armed","code_end":24,"code_start":24,"english_end":13,"english_start":13},{"label":"end arm check","code_end":25,"code_start":25,"english_end":13,"english_start":13},{"label":"read sensor while armed","code_end":26,"code_start":26,"english_end":15,"english_start":15},{"label":"read sensor","code_end":27,"code_start":27,"english_end":15,"english_start":15},{"label":"end sensor read","code_end":28,"code_start":28,"english_end":15,"english_start":15},{"label":"opened box check","code_end":29,"code_start":29,"english_end":17,"english_start":17},{"label":"triggered","code_end":30,"code_start":30,"english_end":17,"english_start":17},{"label":"end opened check","code_end":31,"code_start":31,"english_end":17,"english_start":17},{"label":"triggered alarm","code_end":32,"code_start":32,"english_end":19,"english_start":19},{"label":"LED on","code_end":33,"code_start":33,"english_end":20,"english_start":20},{"label":"alarm tone one","code_end":34,"code_start":34,"english_end":21,"english_start":21},{"label":"alarm wait one","code_end":35,"code_start":35,"english_end":22,"english_start":22},{"label":"alarm tone two","code_end":36,"code_start":36,"english_end":23,"english_start":23},{"label":"alarm wait two","code_end":37,"code_start":37,"english_end":24,"english_start":24},{"label":"end triggered alarm","code_end":38,"code_start":38,"english_end":24,"english_start":24},{"label":"end loop","code_end":39,"code_start":39,"english_end":24,"english_start":24}],"structure":"{\"functions\":[{\"name\":\"pinMode\",\"params\":[\"pin\",\"mode\"],\"english_start\":1,\"english_end\":1,\"summary\":\"No-op hardware stub for setting a pin mode.\",\"calls\":[]},{\"name\":\"digitalRead\",\"params\":[\"pin\"],\"english_start\":1,\"english_end\":1,\"summary\":\"No-op hardware stub that returns a non-triggered reading.\",\"calls\":[]},{\"name\":\"digitalWrite\",\"params\":[\"pin\",\"value\"],\"english_start\":1,\"english_end\":1,\"summary\":\"No-op hardware stub for writing a pin state.\",\"calls\":[]},{\"name\":\"tone\",\"params\":[\"pin\",\"frequency\",\"duration_ms\"],\"english_start\":1,\"english_end\":1,\"summary\":\"No-op hardware stub for playing a tone.\",\"calls\":[]}]}"},"javascript":{"code":"const sensorPin = 7;\nconst flashPin = 13;\nconst buzzerPin = 3;\nlet Status = 0;\nlet sensor = 0;\nfunction setup() {\n  pinMode(sensorPin, INPUT);\n  pinMode(flashPin, OUTPUT);\n  pinMode(buzzerPin, OUTPUT);\n}\nfunction loop() {\n  if (Status === 0) {\n    delay(3000);\n    tone(buzzerPin, 725, 40);\n    delay(200);\n    tone(buzzerPin, 725, 40);\n    Status = 1;\n  }\n  if (Status === 1) {\n    sensor = digitalRead(sensorPin);\n    if (sensor === LOW) {\n      Status = 2;\n    }\n  }\n  if (Status === 2) {\n    digitalWrite(flashPin, HIGH);\n    tone(buzzerPin, 725, 1000);\n    delay(1000);\n    tone(buzzerPin, 330, 1000);\n    delay(1000);\n  }\n}","links":[{"label":"declaration","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"declaration","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"declaration","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"declaration","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"declaration","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"function","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"statement","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"statement","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"statement","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"end","code_end":10,"code_start":10,"english_end":5,"english_start":5},{"label":"function","code_end":11,"code_start":11,"english_end":7,"english_start":7},{"label":"if","code_end":12,"code_start":12,"english_end":13,"english_start":8},{"label":"statement","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"statement","code_end":14,"code_start":14,"english_end":12,"english_start":10},{"label":"statement","code_end":15,"code_start":15,"english_end":12,"english_start":11},{"label":"statement","code_end":16,"code_start":16,"english_end":12,"english_start":12},{"label":"statement","code_end":17,"code_start":17,"english_end":13,"english_start":13},{"label":"end","code_end":18,"code_start":18,"english_end":13,"english_start":13},{"label":"if","code_end":19,"code_start":19,"english_end":17,"english_start":15},{"label":"statement","code_end":20,"code_start":20,"english_end":15,"english_start":15},{"label":"if","code_end":21,"code_start":21,"english_end":17,"english_start":17},{"label":"statement","code_end":22,"code_start":22,"english_end":17,"english_start":17},{"label":"end","code_end":23,"code_start":23,"english_end":17,"english_start":17},{"label":"end","code_end":24,"code_start":24,"english_end":17,"english_start":15},{"label":"if","code_end":25,"code_start":25,"english_end":24,"english_start":19},{"label":"statement","code_end":26,"code_start":26,"english_end":20,"english_start":20},{"label":"statement","code_end":27,"code_start":27,"english_end":21,"english_start":21},{"label":"statement","code_end":28,"code_start":28,"english_end":22,"english_start":22},{"label":"statement","code_end":29,"code_start":29,"english_end":23,"english_start":23},{"label":"statement","code_end":30,"code_start":30,"english_end":24,"english_start":24},{"label":"end","code_end":31,"code_start":31,"english_end":24,"english_start":19},{"label":"end","code_end":32,"code_start":32,"english_end":24,"english_start":7}],"structure":"{\"functions\":[]}"}}},{"slug":"vce-u1-03-read-ldr","title":"VCE Systems Engineering · PRP #03 — Read an LDR (A0)","description":"Read an LDR voltage divider on A0 once a second and print the raw 0-1023 value to the Serial Monitor at 9600 baud.","english":"Read a light-dependent resistor on pin A0 once a second and print the raw number to the Serial Monitor — wire the LDR and a fixed resistor as a voltage divider, with the junction going to A0.\n\nCall pin A0 \"LDR_PIN\".\n\nStart the serial connection at 9600 baud.\n\nForever:\n  Read the analogue value on LDR_PIN into an integer called \"reading\" (it comes back from 0 to 1023, and that is only a raw voltage reading, not a light level in any real unit yet).\n  Print reading to the serial port, followed by a new line.\n  Wait one second before taking the next sample.\n","app_html":"","settings":{},"by_lang":{"ruby":{"code":"# Wire the LDR and fixed resistor as a voltage divider, with the junction connected to A0.\nLDR_PIN = \"A0\"\nSTDOUT.sync = true # Serial connection at 9600 baud\nloop do\n  reading = rand(0..1023)\n  puts reading\n  sleep 1\nend","links":[{"label":"voltage divider wiring","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"name the sensor pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"start serial output","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"repeat forever","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"read the analogue value","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"print the reading","code_end":6,"code_start":6,"english_end":9,"english_start":9},{"label":"wait one second","code_end":7,"code_start":7,"english_end":10,"english_start":10},{"label":"end repeating loop","code_end":8,"code_start":8,"english_end":7,"english_start":7}],"structure":"{\"functions\":[]}"},"cpp":{"code":"// PRP 3 — light sensing with an LDR.\n// Wire the LDR and a fixed resistor as a divider, junction to A0.\n\nconst int LDR_PIN = A0;\n\nvoid setup() {\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int reading = analogRead(LDR_PIN);   // 0-1023, NOT a light level yet\n  Serial.println(reading);\n  delay(1000);\n}\n","links":[],"structure":null},"python":{"code":"SERIAL_BAUD = 9600\nLDR_PIN = \"A0\"\nprint(f\"Serial connection started at {SERIAL_BAUD} baud\")\nwhile True:\n    reading = int(input())\n    print(reading)\n    __import__(\"time\").sleep(1)","links":[{"label":"serial baud rate","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"LDR pin name","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"start serial connection","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"forever loop","code_end":4,"code_start":4,"english_end":7,"english_start":7},{"label":"read analogue value","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"print reading","code_end":6,"code_start":6,"english_end":9,"english_start":9},{"label":"wait one second","code_end":7,"code_start":7,"english_end":10,"english_start":10}],"structure":"{\"functions\":[]}"},"javascript":{"code":"// LDR voltage divider junction connected to A0; raw readings are printed once per second.\n\nconst LDR_PIN = \"A0\";\nconst serial = { begin: () => {}, println: value => console.log(value) };\nserial.begin(9600);\nsetInterval(() => {\n  const reading = Math.floor(Math.random() * 1024);\n  serial.println(reading);\n}, 1000);","links":[{"label":"LDR wiring and sampling","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"name the LDR pin","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"start serial interface","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"set baud rate","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"start forever loop","code_end":6,"code_start":6,"english_end":7,"english_start":7},{"label":"read analogue value","code_end":7,"code_start":7,"english_end":8,"english_start":8},{"label":"print reading","code_end":8,"code_start":8,"english_end":9,"english_start":9},{"label":"wait one second","code_end":9,"code_start":9,"english_end":10,"english_start":10}],"structure":"{\"functions\":[]}"}}},{"slug":"vce-u1-04-read-dht22","title":"VCE Systems Engineering · PRP #04 — Temperature and humidity (DHT22)","description":"Read a DHT22 on pin 2, print both values over Serial every two seconds, and report a failed reading instead of a stale one.","english":"Read the temperature and humidity from a DHT22 sensor on pin 2 and print both to the Serial Monitor every two seconds — two seconds is the fastest a DHT22 can be sampled, so that wait is a limit of the sensor, not a choice.\n\nCall pin 2 \"DHT_PIN\". Set up a DHT22 sensor called \"dht\" connected to DHT_PIN.\n\nStart the serial connection at 9600 baud. Start the sensor.\n\nForever:\n  Read the humidity from the sensor into a decimal number \"humidity\".\n  Read the temperature in degrees Celsius from the sensor into a decimal number \"tempC\".\n  If either humidity or tempC is not a number (the sensor did not answer): print the line \"read failed\".\n  Otherwise: print tempC, then print a single space, then print humidity and end the line.\n  Wait two seconds.\n","app_html":"","settings":{},"by_lang":{"ruby":{"code":"DHT_PIN = 2\ndht = DHT22.new(DHT_PIN)\n$stdout.sync = true\ndht.start\nloop do\n  humidity = dht.read_humidity\n  temp_c = dht.read_temperature_celsius\n  if humidity.nil? || temp_c.nil?\n    puts \"read failed\"\n  else\n    print temp_c, \" \", humidity, \"\\n\"\n  end\n  sleep 2\nend","links":[{"label":"Define the sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Create the DHT22 sensor","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Prepare serial-style output","code_end":3,"code_start":3,"english_end":4,"english_start":4},{"label":"Start the sensor","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"Repeat forever","code_end":5,"code_start":5,"english_end":7,"english_start":7},{"label":"Read humidity","code_end":6,"code_start":6,"english_end":8,"english_start":8},{"label":"Read Celsius temperature","code_end":7,"code_start":7,"english_end":9,"english_start":9},{"label":"Check whether the reading failed","code_end":8,"code_start":8,"english_end":10,"english_start":10},{"label":"Print the failure message","code_end":9,"code_start":9,"english_end":10,"english_start":10},{"label":"Handle a successful reading","code_end":10,"code_start":10,"english_end":11,"english_start":11},{"label":"Print temperature and humidity","code_end":11,"code_start":11,"english_end":11,"english_start":11},{"label":"Finish the reading check","code_end":12,"code_start":12,"english_end":11,"english_start":10},{"label":"Wait two seconds","code_end":13,"code_start":13,"english_end":12,"english_start":12},{"label":"Finish the forever loop","code_end":14,"code_start":14,"english_end":7,"english_start":7}],"structure":"{\"functions\":[]}"},"cpp":{"code":"// PRP 4 — temperature and humidity, plotted over time.\n// Requires the DHT sensor library.\n//\n// The DHT22 needs at least 2 seconds between reads. Sampling faster\n// returns stale values or nan — it is the most common cause of both.\n\n#include <DHT.h>\n\nconst int DHT_PIN = 2;\nDHT dht(DHT_PIN, DHT22);\n\nvoid setup() {\n  Serial.begin(9600);\n  dht.begin();\n}\n\nvoid loop() {\n  float humidity = dht.readHumidity();\n  float tempC = dht.readTemperature();\n\n  if (isnan(humidity) || isnan(tempC)) {\n    Serial.println(\"read failed\");   // check wiring, and check you waited 2s\n  } else {\n    Serial.print(tempC);\n    Serial.print(\" \");\n    Serial.println(humidity);       // two values, space separated, for the plotter\n  }\n\n  delay(2000);                       // minimum sampling interval for this sensor\n}\n","links":[],"structure":null},"python":{"code":"import adafruit_dht\nimport board\nimport time\nDHT_PIN = board.D2\ndht = adafruit_dht.DHT22(DHT_PIN)\ndef main():\n    print(\"Serial connection started at 9600 baud\")\n    dht.measure()\n    while True:\n        try:\n            humidity = dht.humidity\n            tempC = dht.temperature\n        except (RuntimeError, TypeError):\n            humidity = None\n            tempC = None\n        if humidity is None or tempC is None:\n            print(\"read failed\")\n        else:\n            print(tempC, humidity)\n        time.sleep(2)\n\nif __name__ == \"__main__\":\n    main()","links":[{"label":"Import the DHT sensor library","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Import board pin definitions","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Import timing support","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Assign pin 2 to DHT_PIN","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"Create the DHT22 sensor","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"Define the program entry point","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"Start the serial connection at 9600 baud","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"Start the sensor","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"Repeat forever","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"Attempt to read the sensor","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"Read the humidity","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"Read the temperature in Celsius","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"Handle a failed sensor response","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"Mark humidity as unavailable","code_end":14,"code_start":14,"english_end":10,"english_start":10},{"label":"Mark temperature as unavailable","code_end":15,"code_start":15,"english_end":10,"english_start":10},{"label":"Check whether either reading failed","code_end":16,"code_start":16,"english_end":10,"english_start":10},{"label":"Print the failure message","code_end":17,"code_start":17,"english_end":10,"english_start":10},{"label":"Handle valid readings","code_end":18,"code_start":18,"english_end":11,"english_start":11},{"label":"Print temperature and humidity separated by a space","code_end":19,"code_start":19,"english_end":11,"english_start":11},{"label":"Wait two seconds before the next reading","code_end":20,"code_start":20,"english_end":12,"english_start":12},{"label":"Run the program when executed directly","code_end":22,"code_start":22,"english_end":12,"english_start":7},{"label":"Start the main program","code_end":23,"code_start":23,"english_end":12,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"main\",\"params\":[],\"english_start\":5,\"english_end\":12,\"summary\":\"Initializes the DHT22 sensor, repeatedly reads its values, reports failures or readings, and waits two seconds between samples.\",\"calls\":[]}]}"},"javascript":{"code":"const DHT_PIN = 2;\nconst dht = {\n  begin() {},\n  readHumidity() { return Number.parseFloat(process.env.DHT_HUMIDITY); },\n  readTemperatureC() { return Number.parseFloat(process.env.DHT_TEMPERATURE_C); }\n};\nconst BAUD_RATE = 9600;\nconsole.log(`Serial connection started at ${BAUD_RATE} baud`);\ndht.begin();\n\nfunction readAndPrint() {\n  const humidity = dht.readHumidity();\n  const tempC = dht.readTemperatureC();\n  if (Number.isNaN(humidity) || Number.isNaN(tempC)) {\n    console.log(\"read failed\");\n    return;\n  }\n  console.log(`${tempC} ${humidity}`);\n}\nsetInterval(readAndPrint, 2000);","links":[{"label":"Define the sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Create the DHT22 sensor","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Initialize the sensor","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Read humidity","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"Read Celsius temperature","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"Finish sensor setup","code_end":6,"code_start":6,"english_end":3,"english_start":3},{"label":"Set the serial baud rate","code_end":7,"code_start":7,"english_end":4,"english_start":4},{"label":"Start the serial connection","code_end":8,"code_start":8,"english_end":4,"english_start":4},{"label":"Start the sensor","code_end":9,"code_start":9,"english_end":4,"english_start":4},{"label":"Repeat the sensor-reading work","code_end":11,"code_start":11,"english_end":7,"english_start":7},{"label":"Read humidity","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"Read Celsius temperature","code_end":13,"code_start":13,"english_end":9,"english_start":9},{"label":"Check whether either reading failed","code_end":14,"code_start":14,"english_end":10,"english_start":10},{"label":"Report a failed reading","code_end":15,"code_start":15,"english_end":10,"english_start":10},{"label":"Stop processing the failed reading","code_end":16,"code_start":16,"english_end":10,"english_start":10},{"label":"Finish the failure check","code_end":17,"code_start":17,"english_end":11,"english_start":11},{"label":"Print temperature and humidity","code_end":18,"code_start":18,"english_end":11,"english_start":11},{"label":"Finish one sensor-reading cycle","code_end":19,"code_start":19,"english_end":12,"english_start":12},{"label":"Run the cycle every two seconds","code_end":20,"code_start":20,"english_end":12,"english_start":12}],"structure":"{\"functions\":[{\"name\":\"readAndPrint\",\"params\":[],\"english_start\":7,\"english_end\":12,\"summary\":\"Reads both DHT22 values, reports failures, and prints valid readings.\",\"calls\":[{\"english_start\":8,\"english_end\":8},{\"english_start\":9,\"english_end\":9}]}]}"}}},{"slug":"vce-u1-05-threshold","title":"VCE Systems Engineering · PRP #05 — Threshold control","description":"Read a sensor on A0, print it to the serial monitor, and switch pin 13 on whenever the reading falls below a threshold of 500.","english":"Watch a sensor on A0 and switch an output on pin 13 whenever the reading drops below a threshold — the threshold is a design decision you make from your own recorded data.\n\nCall pin A0 \"SENSOR_PIN\" and pin 13 \"OUTPUT_PIN\". Call the whole number 500 \"THRESHOLD\" — a starting value, to be replaced with your own.\n\nSet OUTPUT_PIN as an output. Start serial communication at 9600 baud.\n\nForever:\n  Read the analogue value on SENSOR_PIN into a whole number called \"reading\" (somewhere from 0 to 1023).\n  Print reading to the serial monitor on its own line, so you can watch the values and choose your threshold.\n  If reading is less than THRESHOLD: turn OUTPUT_PIN on (HIGH).\n  Otherwise: turn OUTPUT_PIN off (LOW).\n  Wait one hundred milliseconds (a tenth of a second) before the next reading.\n","app_html":"","settings":{},"by_lang":{"ruby":{"code":"SENSOR_PIN = :A0\nOUTPUT_PIN = 13\nTHRESHOLD = 500\ndef pin_mode(pin, mode)\n  puts \"Pin #{pin} set to #{mode}\"\nend\ndef serial_begin(baud_rate)\n  puts \"Serial started at #{baud_rate} baud\"\nend\ndef analog_read(_pin)\n  rand(1024)\nend\npin_mode(OUTPUT_PIN, :output)\nserial_begin(9600)\n\nloop do\n  reading = analog_read(SENSOR_PIN)\n  puts reading\n  output_state = reading < THRESHOLD ? :high : :low\n  puts \"Pin #{OUTPUT_PIN}: #{output_state}\"\n  sleep 0.1\nend","links":[{"label":"Define sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Define output pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Define threshold","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Define pin mode operation","code_end":4,"code_start":4,"english_end":4,"english_start":4},{"label":"Simulate pin setup","code_end":5,"code_start":5,"english_end":4,"english_start":4},{"label":"Finish pin mode operation","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"Define serial startup","code_end":7,"code_start":7,"english_end":4,"english_start":4},{"label":"Start simulated serial communication","code_end":8,"code_start":8,"english_end":4,"english_start":4},{"label":"Finish serial startup","code_end":9,"code_start":9,"english_end":4,"english_start":4},{"label":"Define analogue reading","code_end":10,"code_start":10,"english_end":8,"english_start":8},{"label":"Generate a simulated sensor reading","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"Finish analogue reading","code_end":12,"code_start":12,"english_end":8,"english_start":8},{"label":"Set output pin as output","code_end":13,"code_start":13,"english_end":4,"english_start":4},{"label":"Start serial communication","code_end":14,"code_start":14,"english_end":4,"english_start":4},{"label":"Repeat forever","code_end":16,"code_start":16,"english_end":7,"english_start":7},{"label":"Read sensor value","code_end":17,"code_start":17,"english_end":8,"english_start":8},{"label":"Print sensor value","code_end":18,"code_start":18,"english_end":9,"english_start":9},{"label":"Switch output based on threshold","code_end":19,"code_start":19,"english_end":11,"english_start":10},{"label":"Apply output state","code_end":20,"code_start":20,"english_end":11,"english_start":10},{"label":"Wait one hundred milliseconds","code_end":21,"code_start":21,"english_end":12,"english_start":12},{"label":"Finish forever loop","code_end":22,"code_start":22,"english_end":7,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"pin_mode\",\"params\":[\"pin\",\"mode\"],\"english_start\":4,\"english_end\":4,\"summary\":\"Simulates configuring a pin mode.\",\"calls\":[]},{\"name\":\"serial_begin\",\"params\":[\"baud_rate\"],\"english_start\":4,\"english_end\":4,\"summary\":\"Simulates starting serial communication.\",\"calls\":[]},{\"name\":\"analog_read\",\"params\":[\"_pin\"],\"english_start\":8,\"english_end\":8,\"summary\":\"Returns a simulated analogue sensor value from 0 through 1023.\",\"calls\":[]}]}"},"python":{"code":"const int SENSOR_PIN = A0;\nconst int OUTPUT_PIN = 13;\nconst int THRESHOLD = 500;\n\nvoid setup() {\n  pinMode(OUTPUT_PIN, OUTPUT);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int reading = analogRead(SENSOR_PIN);\n  Serial.println(reading);\n  if (reading < THRESHOLD) {\n    digitalWrite(OUTPUT_PIN, HIGH);\n  }\n  else {\n    digitalWrite(OUTPUT_PIN, LOW);\n  }\n  delay(100);\n}","links":[{"label":"sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"output pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"threshold","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"setup","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"configure output","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"start serial communication","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"end setup","code_end":8,"code_start":8,"english_end":5,"english_start":5},{"label":"forever loop","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"read sensor","code_end":11,"code_start":11,"english_end":8,"english_start":8},{"label":"print reading","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"check threshold","code_end":13,"code_start":13,"english_end":10,"english_start":10},{"label":"turn output on","code_end":14,"code_start":14,"english_end":10,"english_start":10},{"label":"end threshold check","code_end":15,"code_start":15,"english_end":10,"english_start":10},{"label":"otherwise","code_end":16,"code_start":16,"english_end":11,"english_start":11},{"label":"turn output off","code_end":17,"code_start":17,"english_end":11,"english_start":11},{"label":"end otherwise","code_end":18,"code_start":18,"english_end":11,"english_start":11},{"label":"wait before next reading","code_end":19,"code_start":19,"english_end":12,"english_start":12},{"label":"end forever loop","code_end":20,"code_start":20,"english_end":7,"english_start":7}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":5,\"english_end\":5,\"summary\":\"Configures the output pin and starts serial communication.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":7,\"english_end\":12,\"summary\":\"Repeatedly reads the sensor, reports the value, switches the output based on the threshold, and waits.\",\"calls\":[]}]}"},"cpp":{"code":"// PRP 5 — a single threshold decision.\n//\n// THRESHOLD is a design decision. Replace this value with one you\n// chose from your own recorded readings, and be able to defend it.\n//\n// Expect this sketch to chatter when the reading sits near the\n// threshold. That fault is the point of the activity — PRP 6 fixes it.\n\nconst int SENSOR_PIN = A0;\nconst int OUTPUT_PIN = 13;\nconst int THRESHOLD  = 500;   // <-- your number, from your data\n\nvoid setup() {\n  pinMode(OUTPUT_PIN, OUTPUT);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int reading = analogRead(SENSOR_PIN);\n  Serial.println(reading);\n\n  if (reading < THRESHOLD) {\n    digitalWrite(OUTPUT_PIN, HIGH);\n  } else {\n    digitalWrite(OUTPUT_PIN, LOW);\n  }\n\n  delay(100);\n}\n","links":[],"structure":null},"javascript":{"code":"const SENSOR_PIN = \"A0\";\nconst OUTPUT_PIN = 13;\nconst THRESHOLD = 500;\nlet outputState = false;\nconst analogRead = () => Math.floor(Math.random() * 1024);\nconst digitalWrite = (pin, state) => {\n  outputState = state;\n};\nconst setup = () => {\n  console.log(`Pin ${OUTPUT_PIN} configured as OUTPUT`);\n  console.log(\"Serial communication started at 9600 baud\");\n};\nconst loop = () => {\n  const reading = analogRead(SENSOR_PIN);\n  console.log(reading);\n  if (reading < THRESHOLD) {\n    digitalWrite(OUTPUT_PIN, true);\n  } else {\n    digitalWrite(OUTPUT_PIN, false);\n  }\n};\n\nsetup();\nsetInterval(loop, 100);","links":[{"label":"Define the sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Define the output pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Define the starting threshold","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Track the simulated output state","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"Simulate an analogue sensor reading","code_end":5,"code_start":5,"english_end":8,"english_start":8},{"label":"Define output switching","code_end":6,"code_start":6,"english_end":11,"english_start":10},{"label":"Set the simulated output state","code_end":7,"code_start":7,"english_end":10,"english_start":10},{"label":"Finish output switching","code_end":8,"code_start":8,"english_end":11,"english_start":10},{"label":"Initialize the program","code_end":9,"code_start":9,"english_end":5,"english_start":5},{"label":"Configure the output pin","code_end":10,"code_start":10,"english_end":5,"english_start":5},{"label":"Start serial communication","code_end":11,"code_start":11,"english_end":5,"english_start":5},{"label":"Finish initialization","code_end":12,"code_start":12,"english_end":5,"english_start":5},{"label":"Begin the repeating sensor loop","code_end":13,"code_start":13,"english_end":7,"english_start":7},{"label":"Read the analogue sensor value","code_end":14,"code_start":14,"english_end":8,"english_start":8},{"label":"Print the reading","code_end":15,"code_start":15,"english_end":9,"english_start":9},{"label":"Check whether the reading is below the threshold","code_end":16,"code_start":16,"english_end":10,"english_start":10},{"label":"Turn the output on","code_end":17,"code_start":17,"english_end":10,"english_start":10},{"label":"Handle readings at or above the threshold","code_end":18,"code_start":18,"english_end":11,"english_start":10},{"label":"Turn the output off","code_end":19,"code_start":19,"english_end":11,"english_start":11},{"label":"Finish the threshold decision","code_end":20,"code_start":20,"english_end":11,"english_start":10},{"label":"Finish the repeating loop","code_end":21,"code_start":21,"english_end":12,"english_start":7},{"label":"Run initialization","code_end":23,"code_start":23,"english_end":5,"english_start":5},{"label":"Repeat the loop every one hundred milliseconds","code_end":24,"code_start":24,"english_end":12,"english_start":12}],"structure":"{\"functions\":[{\"name\":\"setup\",\"params\":[],\"english_start\":5,\"english_end\":5,\"summary\":\"Configures the simulated output and starts serial communication.\",\"calls\":[]},{\"name\":\"loop\",\"params\":[],\"english_start\":7,\"english_end\":12,\"summary\":\"Reads the simulated sensor, prints the reading, switches the output, and repeats every 100 milliseconds.\",\"calls\":[{\"english_start\":8,\"english_end\":8},{\"english_start\":10,\"english_end\":11}]}]}"}}},{"slug":"vce-u1-06-hysteresis","title":"VCE Systems Engineering · PRP #06 — Hysteresis","description":"Switch pin 13 from an A0 reading using two thresholds — on below 480, off above 520 — so sensor noise cannot make it chatter.","english":"Switch an output on and off from an analogue sensor using two thresholds instead of one, so the sensor's own noise cannot make the output chatter.\n\nCall analogue pin A0 \"SENSOR_PIN\" and pin 13 \"OUTPUT_PIN\". Keep two fixed whole numbers: \"TURN_ON_BELOW\" equal to 480, and \"TURN_OFF_ABOVE\" equal to 520 — the gap between them is wider than the sensor's noise, and between the two thresholds nothing changes at all.\n\nKeep a true/false value \"outputOn\" for whether the output is currently on, starting as false.\n\nSet OUTPUT_PIN as an output. Start the serial connection at 9600 baud so we can print the readings.\n\nForever:\n  Read the analogue value on SENSOR_PIN into a whole number \"reading\" (it will be 0 to 1023).\n  If outputOn is false and reading is less than TURN_ON_BELOW (480): set outputOn to true.\n  Otherwise, if outputOn is true and reading is greater than TURN_OFF_ABOVE (520): set outputOn to false.\n  Otherwise, leave outputOn exactly as it is.\n  Turn OUTPUT_PIN on (HIGH) if outputOn is true, otherwise turn it off (LOW).\n  Print reading to the serial port on its own line.\n  Wait 100 milliseconds before reading again.\n","app_html":"","settings":{},"by_lang":{"cpp":{"code":"// PRP 6 — hysteresis.\n//\n// One threshold chatters because the sensor's own noise crosses it\n// repeatedly. Two thresholds with a gap wider than that noise fixes it.\n//\n// Make the gap wider than the noise you measured in PRP 4, and no wider.\n\nconst int SENSOR_PIN = A0;\nconst int OUTPUT_PIN = 13;\nconst int TURN_ON_BELOW  = 480;   // <-- your numbers\nconst int TURN_OFF_ABOVE = 520;\n\nbool outputOn = false;\n\nvoid setup() {\n  pinMode(OUTPUT_PIN, OUTPUT);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int reading = analogRead(SENSOR_PIN);\n\n  if (!outputOn && reading < TURN_ON_BELOW) {\n    outputOn = true;\n  } else if (outputOn && reading > TURN_OFF_ABOVE) {\n    outputOn = false;\n  }\n  // Between the two thresholds nothing changes. That is the whole trick.\n\n  digitalWrite(OUTPUT_PIN, outputOn ? HIGH : LOW);\n  Serial.println(reading);\n  delay(100);\n}\n","links":[],"structure":null},"python":{"code":"from machine import ADC, Pin\nSENSOR_PIN = ADC(0)\nOUTPUT_PIN = Pin(13, Pin.OUT)\nTURN_ON_BELOW = 480\nTURN_OFF_ABOVE = 520\noutputOn = False\nOUTPUT_PIN.value(0)\nprint(\"Serial connection started at 9600 baud\")\nwhile True:\n    reading = SENSOR_PIN.read_u16() * 1023 // 65535\n    if not outputOn and reading < TURN_ON_BELOW:\n        outputOn = True\n    elif outputOn and reading > TURN_OFF_ABOVE:\n        outputOn = False\n    OUTPUT_PIN.value(1 if outputOn else 0)\n    print(reading)\n    time.sleep_ms(100)","links":[{"label":"Import hardware interfaces","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Configure analogue sensor pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Configure output pin","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Set turn-on threshold","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"Set turn-off threshold","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"Initialize output state","code_end":6,"code_start":6,"english_end":4,"english_start":4},{"label":"Start with output off","code_end":7,"code_start":7,"english_end":6,"english_start":6},{"label":"Start serial output","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"Repeat forever","code_end":9,"code_start":9,"english_end":16,"english_start":9},{"label":"Read analogue sensor value","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"Check turn-on condition","code_end":11,"code_start":11,"english_end":11,"english_start":11},{"label":"Turn output state on","code_end":12,"code_start":12,"english_end":11,"english_start":11},{"label":"Check turn-off condition","code_end":13,"code_start":13,"english_end":12,"english_start":12},{"label":"Turn output state off","code_end":14,"code_start":14,"english_end":12,"english_start":12},{"label":"Apply output state","code_end":15,"code_start":15,"english_end":14,"english_start":14},{"label":"Print sensor reading","code_end":16,"code_start":16,"english_end":15,"english_start":15},{"label":"Wait before next reading","code_end":17,"code_start":17,"english_end":16,"english_start":16}],"structure":"{\"functions\":[]}"},"ruby":{"code":"SENSOR_PIN = 0\nOUTPUT_PIN = 13\nTURN_ON_BELOW = 480\nTURN_OFF_ABOVE = 520\noutput_on = false\nHIGH = 1\nLOW = 0\nserial_baud = 9600\nwhile (line = STDIN.gets)\n  reading = line.to_i\n  if !output_on && reading < TURN_ON_BELOW\n    output_on = true\n  elsif output_on && reading > TURN_OFF_ABOVE\n    output_on = false\n  end\n  output_pin_state = output_on ? HIGH : LOW\n  puts reading\n  sleep 0.1\nend","links":[{"label":"Define the sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Define the output pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Define the turn-on threshold","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"Define the turn-off threshold","code_end":4,"code_start":4,"english_end":3,"english_start":3},{"label":"Initialize the output state","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"Define the high output state","code_end":6,"code_start":6,"english_end":6,"english_start":6},{"label":"Define the low output state","code_end":7,"code_start":7,"english_end":6,"english_start":6},{"label":"Start the serial connection","code_end":8,"code_start":8,"english_end":6,"english_start":6},{"label":"Repeat while sensor readings are available","code_end":9,"code_start":9,"english_end":9,"english_start":9},{"label":"Read the analogue value","code_end":10,"code_start":10,"english_end":10,"english_start":10},{"label":"Check whether to turn the output on","code_end":11,"code_start":11,"english_end":11,"english_start":11},{"label":"Turn the output on","code_end":12,"code_start":12,"english_end":11,"english_start":11},{"label":"Check whether to turn the output off","code_end":13,"code_start":13,"english_end":12,"english_start":12},{"label":"Turn the output off","code_end":14,"code_start":14,"english_end":12,"english_start":12},{"label":"Leave the output unchanged otherwise","code_end":15,"code_start":15,"english_end":13,"english_start":13},{"label":"Set the output pin state","code_end":16,"code_start":16,"english_end":14,"english_start":14},{"label":"Print the reading","code_end":17,"code_start":17,"english_end":15,"english_start":15},{"label":"Wait before reading again","code_end":18,"code_start":18,"english_end":16,"english_start":16},{"label":"End the repeated reading loop","code_end":19,"code_start":19,"english_end":9,"english_start":9}],"structure":"{\"functions\":[]}"},"javascript":{"code":"const SENSOR_PIN = \"A0\";\nconst OUTPUT_PIN = 13;\nconst TURN_ON_BELOW = 480;\nconst TURN_OFF_ABOVE = 520;\nlet outputOn = false;\n\nfunction pinMode(pin, mode) {\n  console.log(`Pin ${pin} configured as ${mode}.`);\n}\n\nfunction beginSerial(baudRate) {\n  console.log(`Serial started at ${baudRate} baud.`);\n}\n\nfunction analogRead(pin) {\n  return Math.floor(Math.random() * 1024);\n}\n\nfunction digitalWrite(pin, value) {\n  console.log(`Pin ${pin}: ${value}`);\n}\n\npinMode(OUTPUT_PIN, \"OUTPUT\");\nbeginSerial(9600);\n\nsetInterval(() => {\n  const reading = analogRead(SENSOR_PIN);\n  if (!outputOn && reading < TURN_ON_BELOW) {\n    outputOn = true;\n  } else if (outputOn && reading > TURN_OFF_ABOVE) {\n    outputOn = false;\n  }\n  digitalWrite(OUTPUT_PIN, outputOn ? \"HIGH\" : \"LOW\");\n  console.log(reading);\n}, 100);","links":[{"label":"sensor pin","code_end":1,"code_start":1,"english_end":2,"english_start":2},{"label":"output pin","code_end":2,"code_start":2,"english_end":2,"english_start":2},{"label":"turn-on threshold","code_end":3,"code_start":3,"english_end":2,"english_start":2},{"label":"turn-off threshold","code_end":4,"code_start":4,"english_end":2,"english_start":2},{"label":"output state","code_end":5,"code_start":5,"english_end":3,"english_start":3},{"label":"configure pin","code_end":7,"code_start":7,"english_end":4,"english_start":4},{"label":"configure pin","code_end":8,"code_start":8,"english_end":4,"english_start":4},{"label":"configure pin","code_end":9,"code_start":9,"english_end":4,"english_start":4},{"label":"start serial connection","code_end":11,"code_start":11,"english_end":4,"english_start":4},{"label":"start serial connection","code_end":12,"code_start":12,"english_end":4,"english_start":4},{"label":"start serial connection","code_end":13,"code_start":13,"english_end":4,"english_start":4},{"label":"read analogue sensor","code_end":15,"code_start":15,"english_end":4,"english_start":4},{"label":"read analogue sensor","code_end":16,"code_start":16,"english_end":4,"english_start":4},{"label":"read analogue sensor","code_end":17,"code_start":17,"english_end":4,"english_start":4},{"label":"set digital output","code_end":19,"code_start":19,"english_end":4,"english_start":4},{"label":"set digital output","code_end":20,"code_start":20,"english_end":4,"english_start":4},{"label":"set digital output","code_end":21,"code_start":21,"english_end":4,"english_start":4},{"label":"configure output","code_end":23,"code_start":23,"english_end":7,"english_start":7},{"label":"start serial","code_end":24,"code_start":24,"english_end":7,"english_start":7},{"label":"repeat forever","code_end":26,"code_start":26,"english_end":10,"english_start":10},{"label":"read sensor","code_end":27,"code_start":27,"english_end":10,"english_start":10},{"label":"turn output on below threshold","code_end":28,"code_start":28,"english_end":11,"english_start":11},{"label":"turn output on","code_end":29,"code_start":29,"english_end":11,"english_start":11},{"label":"turn output off above threshold","code_end":30,"code_start":30,"english_end":12,"english_start":12},{"label":"turn output off","code_end":31,"code_start":31,"english_end":12,"english_start":12},{"label":"preserve output state otherwise","code_end":32,"code_start":32,"english_end":13,"english_start":13},{"label":"write output state","code_end":33,"code_start":33,"english_end":14,"english_start":14},{"label":"print reading","code_end":34,"code_start":34,"english_end":15,"english_start":15},{"label":"wait before next reading","code_end":35,"code_start":35,"english_end":16,"english_start":16}],"structure":"{\"functions\":[{\"name\":\"pinMode\",\"params\":[\"pin\",\"mode\"],\"english_start\":7,\"english_end\":7,\"summary\":\"Configures a simulated output pin.\",\"calls\":[{\"english_start\":7,\"english_end\":7}]},{\"name\":\"beginSerial\",\"params\":[\"baudRate\"],\"english_start\":7,\"english_end\":7,\"summary\":\"Starts a simulated serial connection.\",\"calls\":[{\"english_start\":7,\"english_end\":7}]},{\"name\":\"analogRead\",\"params\":[\"pin\"],\"english_start\":10,\"english_end\":10,\"summary\":\"Returns a simulated analogue reading from 0 through 1023.\",\"calls\":[{\"english_start\":10,\"english_end\":10}]},{\"name\":\"digitalWrite\",\"params\":[\"pin\",\"value\"],\"english_start\":14,\"english_end\":14,\"summary\":\"Sets a simulated digital output value.\",\"calls\":[{\"english_start\":14,\"english_end\":14}]},{\"name\":\"loop\",\"params\":[],\"english_start\":9,\"english_end\":16,\"summary\":\"Reads the sensor, applies hysteresis, updates the output, and prints the reading repeatedly.\",\"calls\":[{\"english_start\":10,\"english_end\":16}]}]}"}}},{"slug":"vce-u1-07-watering","title":"VCE Systems Engineering · PRP #07 — Automatic watering","description":"Read soil moisture on A0 and drive a pump on pin 9 with dry/wet thresholds, a 15 second run limit and a 60 second rest between waterings.","english":"Water a plant by itself — read a soil moisture sensor on A0 and run a pump on pin 9 only while the soil is dry, with a maximum run time, a compulsory rest, and separate start and stop thresholds so the pump cannot chatter on and off.\n\nCall A0 \"MOISTURE_PIN\" (the soil moisture sensor) and pin 9 \"PUMP_PIN\". Pin 9 goes to the input of a motor driver module, never straight to the pump — a board pin supplies tens of milliamps and the pump wants hundreds.\n\nUse constants: DRY_BELOW is 400 (a reading under this counts as dry soil), WET_ABOVE is 600 (a reading over this counts as wet enough), MAX_RUN_MS is 15000 milliseconds (fifteen seconds — the longest one watering is ever allowed to run, so a sensor that has fallen out of the soil cannot empty the reservoir onto the bench), and REST_MS is 60000 milliseconds (sixty seconds — the pump must sit idle at least this long before it may start again, so the water can soak in). The two millisecond constants are long counts that never go negative, because 60000 will not fit in a plain integer. Those four numbers are your design decisions — tune them to your plant, pot and pump.\n\nKeep a true/false flag \"pumping\" for whether the pump is running, starting at false. Keep two millisecond timestamps, \"pumpStartedAt\" and \"pumpStoppedAt\" — long counts that never go negative, like the constants — both starting at 0, so the rest period is already counting from the moment the board powers up.\n\nSet PUMP_PIN as an output and immediately turn it off (LOW), so the pump cannot kick on while the board is starting. Start the serial connection at 9600 baud.\n\nForever:\n  Read the analogue level on MOISTURE_PIN (0 to 1023) into an integer \"moisture\".\n  Read the number of milliseconds since the board started into \"now\", a long count that never goes negative.\n\n  If pumping (the pump is currently running):\n    Work out \"wetEnough\": true when moisture is greater than WET_ABOVE (600).\n    Work out \"runTooLong\": true when now minus pumpStartedAt is MAX_RUN_MS (15000 milliseconds) or more.\n    If wetEnough or runTooLong:\n      Turn PUMP_PIN off (LOW).\n      Set pumping to false.\n      Set pumpStoppedAt to now.\n      If it was runTooLong that stopped it, print \"STOPPED ON RUN LIMIT - check the sensor\" on its own line — fifteen seconds of pumping that never read wet is a fault, not a thirsty plant.\n\n  Otherwise (the pump is off):\n    Work out \"dry\": true when moisture is less than DRY_BELOW (400).\n    Work out \"rested\": true when now minus pumpStoppedAt is REST_MS (60000 milliseconds) or more.\n    If dry and rested:\n      Turn PUMP_PIN on (HIGH).\n      Set pumping to true.\n      Set pumpStartedAt to now.\n\n  Print moisture on its own line, every time round the loop, whether the pump is running or not.\n  Wait 500 milliseconds (half a second).\n","app_html":"","settings":{},"by_lang":{"python":{"code":"import time\nMOISTURE_PIN = \"A0\"\nPUMP_PIN = 9\nDRY_BELOW = 400\nWET_ABOVE = 600\nMAX_RUN_MS = 15000\nREST_MS = 60000\npumping = False\npumpStartedAt = 0\npumpStoppedAt = 0\ndef set_pump(on):\n    print(f\"PUMP {'HIGH' if on else 'LOW'}\")\ndef read_moisture():\n    try:\n        return int(input(f\"{MOISTURE_PIN} moisture (0-1023): \"))\n    except (EOFError, ValueError):\n        return 1023\n\ndef main():\n    set_pump(False)\n    print(\"Serial started at 9600 baud\")\n    pumping = False\n    pumpStartedAt = 0\n    pumpStoppedAt = 0\n    while True:\n        moisture = read_moisture()\n        now = time.monotonic_ns() // 1_000_000\n        if pumping:\n            wetEnough = moisture > WET_ABOVE\n            runTooLong = now - pumpStartedAt >= MAX_RUN_MS\n            if wetEnough or runTooLong:\n                set_pump(False)\n                pumping = False\n                pumpStoppedAt = now\n                if runTooLong:\n                    print(\"STOPPED ON RUN LIMIT - check the sensor\")\n        else:\n            dry = moisture < DRY_BELOW\n            rested = now - pumpStoppedAt >= REST_MS\n            if dry and rested:\n                set_pump(True)\n                pumping = True\n                pumpStartedAt = now\n        print(moisture)\n        time.sleep(0.5)\n\nif __name__ == \"__main__\":\n    main()","links":[{"label":"standard library import","code_end":1,"code_start":1,"english_end":1,"english_start":1},{"label":"moisture pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"pump pin","code_end":3,"code_start":3,"english_end":3,"english_start":3},{"label":"dry threshold","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"wet threshold","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"maximum pump runtime","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"pump rest period","code_end":7,"code_start":7,"english_end":5,"english_start":5},{"label":"pump state","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"pump start timestamp","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"pump stop timestamp","code_end":10,"code_start":10,"english_end":7,"english_start":7},{"label":"pump output helper","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"set pump output","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"moisture input helper","code_end":13,"code_start":13,"english_end":12,"english_start":12},{"label":"read simulated sensor","code_end":14,"code_start":14,"english_end":12,"english_start":12},{"label":"read analogue moisture","code_end":15,"code_start":15,"english_end":12,"english_start":12},{"label":"handle missing sensor input","code_end":16,"code_start":16,"english_end":12,"english_start":12},{"label":"default sensor reading","code_end":17,"code_start":17,"english_end":12,"english_start":12},{"label":"watering controller","code_end":19,"code_start":19,"english_end":1,"english_start":1},{"label":"initially turn pump off","code_end":20,"code_start":20,"english_end":9,"english_start":9},{"label":"start serial connection","code_end":21,"code_start":21,"english_end":9,"english_start":9},{"label":"initialize pump state","code_end":22,"code_start":22,"english_end":7,"english_start":7},{"label":"initialize start timestamp","code_end":23,"code_start":23,"english_end":7,"english_start":7},{"label":"initialize stop timestamp","code_end":24,"code_start":24,"english_end":7,"english_start":7},{"label":"forever loop","code_end":25,"code_start":25,"english_end":11,"english_start":11},{"label":"read soil moisture","code_end":26,"code_start":26,"english_end":12,"english_start":12},{"label":"read elapsed milliseconds","code_end":27,"code_start":27,"english_end":13,"english_start":13},{"label":"pump-running branch","code_end":28,"code_start":28,"english_end":15,"english_start":15},{"label":"check wet threshold","code_end":29,"code_start":29,"english_end":16,"english_start":16},{"label":"check maximum runtime","code_end":30,"code_start":30,"english_end":17,"english_start":17},{"label":"stop condition","code_end":31,"code_start":31,"english_end":18,"english_start":18},{"label":"turn pump off","code_end":32,"code_start":32,"english_end":19,"english_start":19},{"label":"clear pump state","code_end":33,"code_start":33,"english_end":20,"english_start":20},{"label":"record stop time","code_end":34,"code_start":34,"english_end":21,"english_start":21},{"label":"run-limit fault condition","code_end":35,"code_start":35,"english_end":22,"english_start":22},{"label":"report run-limit fault","code_end":36,"code_start":36,"english_end":22,"english_start":22},{"label":"pump-off branch","code_end":37,"code_start":37,"english_end":23,"english_start":23},{"label":"check dry threshold","code_end":38,"code_start":38,"english_end":25,"english_start":25},{"label":"check rest period","code_end":39,"code_start":39,"english_end":26,"english_start":26},{"label":"start condition","code_end":40,"code_start":40,"english_end":27,"english_start":27},{"label":"turn pump on","code_end":41,"code_start":41,"english_end":28,"english_start":28},{"label":"set pump state","code_end":42,"code_start":42,"english_end":29,"english_start":29},{"label":"record start time","code_end":43,"code_start":43,"english_end":30,"english_start":30},{"label":"report moisture","code_end":44,"code_start":44,"english_end":32,"english_start":32},{"label":"wait half a second","code_end":45,"code_start":45,"english_end":33,"english_start":33},{"label":"program entry point","code_end":47,"code_start":47,"english_end":1,"english_start":1},{"label":"run controller","code_end":48,"code_start":48,"english_end":1,"english_start":1}],"structure":"{\"functions\":[{\"name\":\"set_pump\",\"params\":[\"on\"],\"english_start\":9,\"english_end\":9,\"summary\":\"Simulates setting the motor-driver input HIGH or LOW.\",\"calls\":[]},{\"name\":\"read_moisture\",\"params\":[],\"english_start\":12,\"english_end\":12,\"summary\":\"Reads a simulated A0 moisture value from standard input.\",\"calls\":[]},{\"name\":\"main\",\"params\":[],\"english_start\":1,\"english_end\":33,\"summary\":\"Runs the hysteresis-based watering controller indefinitely.\",\"calls\":[{\"english_start\":9,\"english_end\":9},{\"english_start\":12,\"english_end\":12}]}]}"},"javascript":{"code":"const MOISTURE_PIN = \"A0\";\nconst PUMP_PIN = 9;\nconst DRY_BELOW = 400;\nconst WET_ABOVE = 600;\nconst MAX_RUN_MS = 15000;\nconst REST_MS = 60000;\nlet pumping = false;\nlet pumpStartedAt = 0;\nlet pumpStoppedAt = 0;\npinMode(PUMP_PIN, \"OUTPUT\");\ndigitalWrite(PUMP_PIN, LOW);\nSerial.begin(9600);\nasync function loop() {\n  const moisture = analogRead(MOISTURE_PIN);\n  const now = millis();\n  if (pumping) {\n    const wetEnough = moisture > WET_ABOVE;\n    const runTooLong = now - pumpStartedAt >= MAX_RUN_MS;\n    if (wetEnough || runTooLong) {\n      digitalWrite(PUMP_PIN, LOW);\n      pumping = false;\n      pumpStoppedAt = now;\n      if (runTooLong) {\n        Serial.println(\"STOPPED ON RUN LIMIT - check the sensor\");\n      }\n    }\n  } else {\n    const dry = moisture < DRY_BELOW;\n    const rested = now - pumpStoppedAt >= REST_MS;\n    if (dry && rested) {\n      digitalWrite(PUMP_PIN, HIGH);\n      pumping = true;\n      pumpStartedAt = now;\n    }\n  }\n  Serial.println(moisture);\n  await delay(500);\n}\n\nconst LOW = 0;\nconst HIGH = 1;\nconst startedAt = Date.now();\nconst Serial = { begin: () => {}, println: value => console.log(value) };\nconst pinMode = () => {};\nconst digitalWrite = (pin, state) => {};\nconst analogRead = () => 1023;\nconst millis = () => Date.now() - startedAt;\nconst delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));\nloop();","links":[{"label":"name the soil moisture sensor","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"name the pump control pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"define the dry threshold","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"define the wet threshold","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"define the maximum run time","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"define the compulsory rest time","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"initialize the pump state","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"initialize the pump start timestamp","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"initialize the pump stop timestamp","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"configure the pump pin as an output","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"turn the pump off during startup","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"start serial communication","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"repeat the control loop","code_end":13,"code_start":13,"english_end":11,"english_start":11},{"label":"read the soil moisture","code_end":14,"code_start":14,"english_end":12,"english_start":12},{"label":"read elapsed time","code_end":15,"code_start":15,"english_end":13,"english_start":13},{"label":"handle a running pump","code_end":16,"code_start":16,"english_end":15,"english_start":15},{"label":"check whether the soil is wet enough","code_end":17,"code_start":17,"english_end":16,"english_start":16},{"label":"check the maximum run time","code_end":18,"code_start":18,"english_end":17,"english_start":17},{"label":"stop when wet or over the run limit","code_end":19,"code_start":19,"english_end":18,"english_start":18},{"label":"turn the pump off","code_end":20,"code_start":20,"english_end":19,"english_start":19},{"label":"record that the pump stopped","code_end":21,"code_start":21,"english_end":20,"english_start":20},{"label":"record the stop time","code_end":22,"code_start":22,"english_end":21,"english_start":21},{"label":"check whether the run limit caused the stop","code_end":23,"code_start":23,"english_end":22,"english_start":22},{"label":"report a run-limit fault","code_end":24,"code_start":24,"english_end":22,"english_start":22},{"label":"finish the run-limit check","code_end":25,"code_start":25,"english_end":22,"english_start":22},{"label":"finish the stop condition","code_end":26,"code_start":26,"english_end":18,"english_start":18},{"label":"handle a stopped pump","code_end":27,"code_start":27,"english_end":23,"english_start":23},{"label":"check whether the soil is dry","code_end":28,"code_start":28,"english_end":25,"english_start":25},{"label":"check whether the pump has rested","code_end":29,"code_start":29,"english_end":26,"english_start":26},{"label":"start only when dry and rested","code_end":30,"code_start":30,"english_end":27,"english_start":27},{"label":"turn the pump on","code_end":31,"code_start":31,"english_end":28,"english_start":28},{"label":"record that the pump started","code_end":32,"code_start":32,"english_end":29,"english_start":29},{"label":"record the start time","code_end":33,"code_start":33,"english_end":30,"english_start":30},{"label":"finish the start condition","code_end":34,"code_start":34,"english_end":27,"english_start":27},{"label":"finish the pump-state branch","code_end":35,"code_start":35,"english_end":23,"english_start":23},{"label":"print the moisture reading","code_end":36,"code_start":36,"english_end":32,"english_start":32},{"label":"wait half a second","code_end":37,"code_start":37,"english_end":33,"english_start":33},{"label":"finish the control loop","code_end":38,"code_start":38,"english_end":11,"english_start":11},{"label":"define the low output state","code_end":40,"code_start":40,"english_end":1,"english_start":1},{"label":"define the high output state","code_end":41,"code_start":41,"english_end":1,"english_start":1},{"label":"record program start time","code_end":42,"code_start":42,"english_end":1,"english_start":1},{"label":"provide serial output","code_end":43,"code_start":43,"english_end":1,"english_start":1},{"label":"provide pin configuration","code_end":44,"code_start":44,"english_end":1,"english_start":1},{"label":"provide digital output","code_end":45,"code_start":45,"english_end":1,"english_start":1},{"label":"provide an analog sensor adapter","code_end":46,"code_start":46,"english_end":1,"english_start":1},{"label":"provide elapsed milliseconds","code_end":47,"code_start":47,"english_end":1,"english_start":1},{"label":"provide a non-blocking delay","code_end":48,"code_start":48,"english_end":1,"english_start":1},{"label":"start the controller","code_end":49,"code_start":49,"english_end":1,"english_start":1}],"structure":"{\"functions\":[{\"name\":\"loop\",\"params\":[],\"english_start\":11,\"english_end\":33,\"summary\":\"Reads moisture, controls the pump with hysteresis, enforces run and rest limits, reports readings, and repeats forever.\",\"calls\":[]}]}"},"cpp":{"code":"// PRP 7 — automatic watering.\n//\n// Pump is driven through a motor driver module, NOT directly from a pin.\n// A board pin supplies tens of milliamps; the pump wants hundreds.\n//\n// MAX_RUN_MS is the safety limit. If the sensor falls out of the soil or\n// fails open, an unlimited pump empties the reservoir onto the bench.\n// A control system that cannot fail safely is not finished.\n\nconst int MOISTURE_PIN = A0;\nconst int PUMP_PIN     = 9;      // to the driver module input\n\nconst int DRY_BELOW  = 400;      // <-- your calibrated numbers\nconst int WET_ABOVE  = 600;\nconst unsigned long MAX_RUN_MS  = 15000UL;   // never pump longer than this\nconst unsigned long REST_MS     = 60000UL;   // let water soak in before re-reading\n\nbool pumping = false;\nunsigned long pumpStartedAt = 0;\nunsigned long pumpStoppedAt = 0;\n\nvoid setup() {\n  pinMode(PUMP_PIN, OUTPUT);\n  digitalWrite(PUMP_PIN, LOW);\n  Serial.begin(9600);\n}\n\nvoid loop() {\n  int moisture = analogRead(MOISTURE_PIN);\n  unsigned long now = millis();\n\n  if (pumping) {\n    bool wetEnough = moisture > WET_ABOVE;\n    bool runTooLong = (now - pumpStartedAt) >= MAX_RUN_MS;\n\n    if (wetEnough || runTooLong) {\n      digitalWrite(PUMP_PIN, LOW);\n      pumping = false;\n      pumpStoppedAt = now;\n      if (runTooLong) {\n        Serial.println(\"STOPPED ON RUN LIMIT - check the sensor\");\n      }\n    }\n  } else {\n    bool dry = moisture < DRY_BELOW;\n    bool rested = (now - pumpStoppedAt) >= REST_MS;\n\n    if (dry && rested) {\n      digitalWrite(PUMP_PIN, HIGH);\n      pumping = true;\n      pumpStartedAt = now;\n    }\n  }\n\n  Serial.println(moisture);\n  delay(500);\n}\n","links":[],"structure":null},"ruby":{"code":"MOISTURE_PIN = \"A0\"\nPUMP_PIN = 9\nDRY_BELOW = 400\nWET_ABOVE = 600\nMAX_RUN_MS = 15_000\nREST_MS = 60_000\npumping = false\npump_started_at = 0\npump_stopped_at = 0\nputs \"PUMP_PIN configured as OUTPUT\"\nputs \"PUMP_PIN: LOW\"\nputs \"Serial started at 9600 baud\"\nloop do\nmoisture = STDIN.gets.to_i\nnow = (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i\nif pumping\nwet_enough = moisture > WET_ABOVE\nrun_too_long = now - pump_started_at >= MAX_RUN_MS\nif wet_enough || run_too_long\nputs \"PUMP_PIN: LOW\"\npumping = false\npump_stopped_at = now\nputs \"STOPPED ON RUN LIMIT - check the sensor\" if run_too_long\nend\nend\nelse\ndry = moisture < DRY_BELOW\nrested = now - pump_stopped_at >= REST_MS\nif dry && rested\nputs \"PUMP_PIN: HIGH\"\npumping = true\npump_started_at = now\nend\nend\nputs moisture\nsleep 0.5\nend","links":[{"label":"Define moisture sensor pin","code_end":1,"code_start":1,"english_end":3,"english_start":3},{"label":"Define pump control pin","code_end":2,"code_start":2,"english_end":3,"english_start":3},{"label":"Define dry threshold","code_end":3,"code_start":3,"english_end":5,"english_start":5},{"label":"Define wet threshold","code_end":4,"code_start":4,"english_end":5,"english_start":5},{"label":"Define maximum pump runtime","code_end":5,"code_start":5,"english_end":5,"english_start":5},{"label":"Define compulsory rest period","code_end":6,"code_start":6,"english_end":5,"english_start":5},{"label":"Initialize pump state","code_end":7,"code_start":7,"english_end":7,"english_start":7},{"label":"Initialize pump start timestamp","code_end":8,"code_start":8,"english_end":7,"english_start":7},{"label":"Initialize pump stop timestamp","code_end":9,"code_start":9,"english_end":7,"english_start":7},{"label":"Configure pump output","code_end":10,"code_start":10,"english_end":9,"english_start":9},{"label":"Turn pump off at startup","code_end":11,"code_start":11,"english_end":9,"english_start":9},{"label":"Start serial connection","code_end":12,"code_start":12,"english_end":9,"english_start":9},{"label":"Begin forever loop","code_end":13,"code_start":13,"english_end":11,"english_start":11},{"label":"Read soil moisture","code_end":14,"code_start":14,"english_end":12,"english_start":12},{"label":"Read elapsed milliseconds","code_end":15,"code_start":15,"english_end":13,"english_start":13},{"label":"Handle running pump","code_end":16,"code_start":16,"english_end":15,"english_start":15},{"label":"Check wet threshold","code_end":17,"code_start":17,"english_end":16,"english_start":16},{"label":"Check maximum runtime","code_end":18,"code_start":18,"english_end":17,"english_start":17},{"label":"Check whether pumping must stop","code_end":19,"code_start":19,"english_end":18,"english_start":18},{"label":"Turn pump off","code_end":20,"code_start":20,"english_end":19,"english_start":19},{"label":"Record pump stopped","code_end":21,"code_start":21,"english_end":20,"english_start":20},{"label":"Record stop time","code_end":22,"code_start":22,"english_end":21,"english_start":21},{"label":"Report runtime fault","code_end":23,"code_start":23,"english_end":22,"english_start":22},{"label":"End stop condition","code_end":24,"code_start":24,"english_end":22,"english_start":22},{"label":"End running-pump branch","code_end":25,"code_start":25,"english_end":23,"english_start":23},{"label":"Handle stopped pump","code_end":26,"code_start":26,"english_end":23,"english_start":23},{"label":"Check dry threshold","code_end":27,"code_start":27,"english_end":25,"english_start":25},{"label":"Check compulsory rest","code_end":28,"code_start":28,"english_end":26,"english_start":26},{"label":"Check whether watering may start","code_end":29,"code_start":29,"english_end":27,"english_start":27},{"label":"Turn pump on","code_end":30,"code_start":30,"english_end":28,"english_start":28},{"label":"Record pump running","code_end":31,"code_start":31,"english_end":29,"english_start":29},{"label":"Record start time","code_end":32,"code_start":32,"english_end":30,"english_start":30},{"label":"End start condition","code_end":33,"code_start":33,"english_end":31,"english_start":31},{"label":"End pump-state branch","code_end":34,"code_start":34,"english_end":31,"english_start":31},{"label":"Print moisture reading","code_end":35,"code_start":35,"english_end":32,"english_start":32},{"label":"Wait half a second","code_end":36,"code_start":36,"english_end":33,"english_start":33},{"label":"Repeat forever","code_end":37,"code_start":37,"english_end":33,"english_start":33}],"structure":"{\"functions\":[]}"}}}]}