├── arduino_extension.js ├── arduino_extension_debug.js ├── arduino_extension_simple.js ├── arduino_extension_tone.js ├── bin ├── ScratchDevicePlugin.dmg └── ScratchDevicePlugin.msi ├── blocks.html ├── examples.html ├── examples ├── Arduino Example - Adjusting LED with Rotation Knob.sbx ├── Arduino Example - Blink a LED.sbx ├── Arduino Example - Blink an LED.sbx ├── Arduino Example - Button.sbx ├── Arduino Example - Fade a LED.sbx ├── Arduino Example - Fade an LED.sbx ├── Arduino Example - Light Sensor.sbx ├── Arduino Example - Rotation Knob.sbx └── Arduino Example - Swing a Servo.sbx ├── gettingstarted.html ├── hardware.html ├── images ├── ArduinoUnoPins.png ├── arduino-board.png ├── arduino-port.png ├── arduino-upload-button.png ├── arduino-upload.png ├── arduino.png ├── blocks │ ├── button-boolean.png │ ├── button-when.png │ ├── device-connected.png │ ├── led-change.png │ ├── led-connect.png │ ├── led-digital.png │ ├── led-set.png │ ├── map.png │ ├── pin-read-analog.png │ ├── pin-read-digital.png │ ├── pin-when-analog.png │ ├── pin-when-digital.png │ ├── pin-write-analog.png │ ├── pin-write-digital.png │ ├── sensor-connect.png │ ├── sensor-read.png │ ├── sensor-when.png │ ├── servo-change.png │ └── servo-set.png ├── chrome-npapi.png ├── chrome-npapi2.png ├── chrome-npapi3.png ├── chrome-plugin-broken.png ├── chrome-plugin-enable.png ├── connected.png ├── disconnected.png ├── firefox-plugin.png ├── firefox-plugin2.png ├── firmata.png ├── github-banner.png ├── grove-button.jpg ├── grove-led.jpg ├── grove-light-sensor.jpg ├── grove-rotation-knob.jpg ├── grove-servo-motor.jpg ├── grove-shield.jpg ├── grove-temperature-sensor.jpg ├── grove-wired.jpg ├── grove.jpg ├── moreblocks.png └── upload.png ├── index.html └── style.css /arduino_extension.js: -------------------------------------------------------------------------------- 1 | /* 2 | *This program is free software: you can redistribute it and/or modify 3 | *it under the terms of the GNU General Public License as published by 4 | *the Free Software Foundation, either version 3 of the License, or 5 | *(at your option) any later version. 6 | * 7 | *This program is distributed in the hope that it will be useful, 8 | *but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | *GNU General Public License for more details. 11 | * 12 | *You should have received a copy of the GNU General Public License 13 | *along with this program. If not, see . 14 | */ 15 | 16 | (function(ext) { 17 | 18 | var PIN_MODE = 0xF4, 19 | REPORT_DIGITAL = 0xD0, 20 | REPORT_ANALOG = 0xC0, 21 | DIGITAL_MESSAGE = 0x90, 22 | START_SYSEX = 0xF0, 23 | END_SYSEX = 0xF7, 24 | QUERY_FIRMWARE = 0x79, 25 | REPORT_VERSION = 0xF9, 26 | ANALOG_MESSAGE = 0xE0, 27 | ANALOG_MAPPING_QUERY = 0x69, 28 | ANALOG_MAPPING_RESPONSE = 0x6A, 29 | CAPABILITY_QUERY = 0x6B, 30 | CAPABILITY_RESPONSE = 0x6C; 31 | 32 | var INPUT = 0x00, 33 | OUTPUT = 0x01, 34 | ANALOG = 0x02, 35 | PWM = 0x03, 36 | SERVO = 0x04, 37 | SHIFT = 0x05, 38 | I2C = 0x06, 39 | ONEWIRE = 0x07, 40 | STEPPER = 0x08, 41 | ENCODER = 0x09, 42 | SERIAL = 0x0A, 43 | PULLUP = 0x0B, 44 | IGNORE = 0x7F, 45 | TOTAL_PIN_MODES = 13; 46 | 47 | var LOW = 0, 48 | HIGH = 1; 49 | 50 | var MAX_DATA_BYTES = 4096; 51 | var MAX_PINS = 128; 52 | 53 | var parsingSysex = false, 54 | waitForData = 0, 55 | executeMultiByteCommand = 0, 56 | multiByteChannel = 0, 57 | sysexBytesRead = 0, 58 | storedInputData = new Uint8Array(MAX_DATA_BYTES); 59 | 60 | var digitalOutputData = new Uint8Array(16), 61 | digitalInputData = new Uint8Array(16), 62 | analogInputData = new Uint16Array(16); 63 | 64 | var analogChannel = new Uint8Array(MAX_PINS); 65 | var pinModes = []; 66 | for (var i = 0; i < TOTAL_PIN_MODES; i++) pinModes[i] = []; 67 | 68 | var majorVersion = 0, 69 | minorVersion = 0; 70 | 71 | var connected = false; 72 | var notifyConnection = false; 73 | var device = null; 74 | var inputData = null; 75 | 76 | // TEMPORARY WORKAROUND 77 | // Since _deviceRemoved is not used with Serial devices 78 | // ping device regularly to check connection 79 | var pinging = false; 80 | var pingCount = 0; 81 | var pinger = null; 82 | 83 | var hwList = new HWList(); 84 | 85 | function HWList() { 86 | this.devices = []; 87 | 88 | this.add = function(dev, pin) { 89 | var device = this.search(dev); 90 | if (!device) { 91 | device = {name: dev, pin: pin, val: 0}; 92 | this.devices.push(device); 93 | } else { 94 | device.pin = pin; 95 | device.val = 0; 96 | } 97 | }; 98 | 99 | this.search = function(dev) { 100 | for (var i=0; i 6) { 123 | clearInterval(pinger); 124 | pinger = null; 125 | connected = false; 126 | if (device) device.close(); 127 | device = null; 128 | return; 129 | } 130 | } else { 131 | if (!device) { 132 | clearInterval(pinger); 133 | pinger = null; 134 | return; 135 | } 136 | queryFirmware(); 137 | pinging = true; 138 | } 139 | }, 100); 140 | } 141 | 142 | function hasCapability(pin, mode) { 143 | if (pinModes[mode].indexOf(pin) > -1) 144 | return true; 145 | else 146 | return false; 147 | } 148 | 149 | function queryFirmware() { 150 | var output = new Uint8Array([START_SYSEX, QUERY_FIRMWARE, END_SYSEX]); 151 | device.send(output.buffer); 152 | } 153 | 154 | function queryCapabilities() { 155 | console.log('Querying ' + device.id + ' capabilities'); 156 | var msg = new Uint8Array([ 157 | START_SYSEX, CAPABILITY_QUERY, END_SYSEX]); 158 | device.send(msg.buffer); 159 | } 160 | 161 | function queryAnalogMapping() { 162 | console.log('Querying ' + device.id + ' analog mapping'); 163 | var msg = new Uint8Array([ 164 | START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX]); 165 | device.send(msg.buffer); 166 | } 167 | 168 | function setDigitalInputs(portNum, portData) { 169 | digitalInputData[portNum] = portData; 170 | } 171 | 172 | function setAnalogInput(pin, val) { 173 | analogInputData[pin] = val; 174 | } 175 | 176 | function setVersion(major, minor) { 177 | majorVersion = major; 178 | minorVersion = minor; 179 | } 180 | 181 | function processSysexMessage() { 182 | switch(storedInputData[0]) { 183 | case CAPABILITY_RESPONSE: 184 | for (var i = 1, pin = 0; pin < MAX_PINS; pin++) { 185 | while (storedInputData[i++] != 0x7F) { 186 | pinModes[storedInputData[i-1]].push(pin); 187 | i++; //Skip mode resolution 188 | } 189 | if (i == sysexBytesRead) break; 190 | } 191 | queryAnalogMapping(); 192 | break; 193 | case ANALOG_MAPPING_RESPONSE: 194 | for (var pin = 0; pin < analogChannel.length; pin++) 195 | analogChannel[pin] = 127; 196 | for (var i = 1; i < sysexBytesRead; i++) 197 | analogChannel[i-1] = storedInputData[i]; 198 | for (var pin = 0; pin < analogChannel.length; pin++) { 199 | if (analogChannel[pin] != 127) { 200 | var out = new Uint8Array([ 201 | REPORT_ANALOG | analogChannel[pin], 0x01]); 202 | device.send(out.buffer); 203 | } 204 | } 205 | notifyConnection = true; 206 | setTimeout(function() { 207 | notifyConnection = false; 208 | }, 100); 209 | break; 210 | case QUERY_FIRMWARE: 211 | if (!connected) { 212 | clearInterval(poller); 213 | poller = null; 214 | clearTimeout(watchdog); 215 | watchdog = null; 216 | connected = true; 217 | setTimeout(init, 200); 218 | } 219 | pinging = false; 220 | pingCount = 0; 221 | break; 222 | } 223 | } 224 | 225 | function processInput(inputData) { 226 | for (var i=0; i < inputData.length; i++) { 227 | if (parsingSysex) { 228 | if (inputData[i] == END_SYSEX) { 229 | parsingSysex = false; 230 | processSysexMessage(); 231 | } else { 232 | storedInputData[sysexBytesRead++] = inputData[i]; 233 | } 234 | } else if (waitForData > 0 && inputData[i] < 0x80) { 235 | storedInputData[--waitForData] = inputData[i]; 236 | if (executeMultiByteCommand !== 0 && waitForData === 0) { 237 | switch(executeMultiByteCommand) { 238 | case DIGITAL_MESSAGE: 239 | setDigitalInputs(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 240 | break; 241 | case ANALOG_MESSAGE: 242 | setAnalogInput(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 243 | break; 244 | case REPORT_VERSION: 245 | setVersion(storedInputData[1], storedInputData[0]); 246 | break; 247 | } 248 | } 249 | } else { 250 | if (inputData[i] < 0xF0) { 251 | command = inputData[i] & 0xF0; 252 | multiByteChannel = inputData[i] & 0x0F; 253 | } else { 254 | command = inputData[i]; 255 | } 256 | switch(command) { 257 | case DIGITAL_MESSAGE: 258 | case ANALOG_MESSAGE: 259 | case REPORT_VERSION: 260 | waitForData = 2; 261 | executeMultiByteCommand = command; 262 | break; 263 | case START_SYSEX: 264 | parsingSysex = true; 265 | sysexBytesRead = 0; 266 | break; 267 | } 268 | } 269 | } 270 | } 271 | 272 | function pinMode(pin, mode) { 273 | var msg = new Uint8Array([PIN_MODE, pin, mode]); 274 | device.send(msg.buffer); 275 | } 276 | 277 | function analogRead(pin) { 278 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 279 | return Math.round((analogInputData[pin] * 100) / 1023); 280 | } else { 281 | var valid = []; 282 | for (var i = 0; i < pinModes[ANALOG].length; i++) 283 | valid.push(i); 284 | console.log('ERROR: valid analog pins are ' + valid.join(', ')); 285 | return; 286 | } 287 | } 288 | 289 | function digitalRead(pin) { 290 | if (!hasCapability(pin, INPUT)) { 291 | console.log('ERROR: valid input pins are ' + pinModes[INPUT].join(', ')); 292 | return; 293 | } 294 | pinMode(pin, INPUT); 295 | return (digitalInputData[pin >> 3] >> (pin & 0x07)) & 0x01; 296 | } 297 | 298 | function analogWrite(pin, val) { 299 | if (!hasCapability(pin, PWM)) { 300 | console.log('ERROR: valid PWM pins are ' + pinModes[PWM].join(', ')); 301 | return; 302 | } 303 | if (val < 0) val = 0; 304 | else if (val > 100) val = 100; 305 | val = Math.round((val / 100) * 255); 306 | pinMode(pin, PWM); 307 | var msg = new Uint8Array([ 308 | ANALOG_MESSAGE | (pin & 0x0F), 309 | val & 0x7F, 310 | val >> 7]); 311 | device.send(msg.buffer); 312 | } 313 | 314 | function digitalWrite(pin, val) { 315 | if (!hasCapability(pin, OUTPUT)) { 316 | console.log('ERROR: valid output pins are ' + pinModes[OUTPUT].join(', ')); 317 | return; 318 | } 319 | var portNum = (pin >> 3) & 0x0F; 320 | if (val == LOW) 321 | digitalOutputData[portNum] &= ~(1 << (pin & 0x07)); 322 | else 323 | digitalOutputData[portNum] |= (1 << (pin & 0x07)); 324 | pinMode(pin, OUTPUT); 325 | var msg = new Uint8Array([ 326 | DIGITAL_MESSAGE | portNum, 327 | digitalOutputData[portNum] & 0x7F, 328 | digitalOutputData[portNum] >> 0x07]); 329 | device.send(msg.buffer); 330 | } 331 | 332 | function rotateServo(pin, deg) { 333 | if (!hasCapability(pin, SERVO)) { 334 | console.log('ERROR: valid servo pins are ' + pinModes[SERVO].join(', ')); 335 | return; 336 | } 337 | pinMode(pin, SERVO); 338 | var msg = new Uint8Array([ 339 | ANALOG_MESSAGE | (pin & 0x0F), 340 | deg & 0x7F, 341 | deg >> 0x07]); 342 | device.send(msg.buffer); 343 | } 344 | 345 | ext.whenConnected = function() { 346 | if (notifyConnection) return true; 347 | return false; 348 | }; 349 | 350 | ext.analogWrite = function(pin, val) { 351 | analogWrite(pin, val); 352 | }; 353 | 354 | ext.digitalWrite = function(pin, val) { 355 | if (val == menus[lang]['outputs'][0]) 356 | digitalWrite(pin, HIGH); 357 | else if (val == menus[lang]['outputs'][1]) 358 | digitalWrite(pin, LOW); 359 | }; 360 | 361 | ext.analogRead = function(pin) { 362 | return analogRead(pin); 363 | }; 364 | 365 | ext.digitalRead = function(pin) { 366 | return digitalRead(pin); 367 | }; 368 | 369 | ext.whenAnalogRead = function(pin, op, val) { 370 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 371 | if (op == '>') 372 | return analogRead(pin) > val; 373 | else if (op == '<') 374 | return analogRead(pin) < val; 375 | else if (op == '=') 376 | return analogRead(pin) == val; 377 | else 378 | return false; 379 | } 380 | }; 381 | 382 | ext.whenDigitalRead = function(pin, val) { 383 | if (hasCapability(pin, INPUT)) { 384 | if (val == menus[lang]['outputs'][0]) 385 | return digitalRead(pin); 386 | else if (val == menus[lang]['outputs'][1]) 387 | return digitalRead(pin) === false; 388 | } 389 | }; 390 | 391 | ext.connectHW = function(hw, pin) { 392 | hwList.add(hw, pin); 393 | }; 394 | 395 | ext.rotateServo = function(servo, deg) { 396 | var hw = hwList.search(servo); 397 | if (!hw) return; 398 | if (deg < 0) deg = 0; 399 | else if (deg > 180) deg = 180; 400 | rotateServo(hw.pin, deg); 401 | hw.val = deg; 402 | }; 403 | 404 | ext.changeServo = function(servo, change) { 405 | var hw = hwList.search(servo); 406 | if (!hw) return; 407 | var deg = hw.val + change; 408 | if (deg < 0) deg = 0; 409 | else if (deg > 180) deg = 180; 410 | rotateServo(hw.pin, deg); 411 | hw.val = deg; 412 | }; 413 | 414 | ext.setLED = function(led, val) { 415 | var hw = hwList.search(led); 416 | if (!hw) return; 417 | analogWrite(hw.pin, val); 418 | hw.val = val; 419 | }; 420 | 421 | ext.changeLED = function(led, val) { 422 | var hw = hwList.search(led); 423 | if (!hw) return; 424 | var b = hw.val + val; 425 | if (b < 0) b = 0; 426 | else if (b > 100) b = 100; 427 | analogWrite(hw.pin, b); 428 | hw.val = b; 429 | }; 430 | 431 | ext.digitalLED = function(led, val) { 432 | var hw = hwList.search(led); 433 | if (!hw) return; 434 | if (val == 'on') { 435 | digitalWrite(hw.pin, HIGH); 436 | hw.val = 255; 437 | } else if (val == 'off') { 438 | digitalWrite(hw.pin, LOW); 439 | hw.val = 0; 440 | } 441 | }; 442 | 443 | ext.readInput = function(name) { 444 | var hw = hwList.search(name); 445 | if (!hw) return; 446 | return analogRead(hw.pin); 447 | }; 448 | 449 | ext.whenButton = function(btn, state) { 450 | var hw = hwList.search(btn); 451 | if (!hw) return; 452 | if (state === 'pressed') 453 | return digitalRead(hw.pin); 454 | else if (state === 'released') 455 | return !digitalRead(hw.pin); 456 | }; 457 | 458 | ext.isButtonPressed = function(btn) { 459 | var hw = hwList.search(btn); 460 | if (!hw) return; 461 | return digitalRead(hw.pin); 462 | }; 463 | 464 | ext.whenInput = function(name, op, val) { 465 | var hw = hwList.search(name); 466 | if (!hw) return; 467 | if (op == '>') 468 | return analogRead(hw.pin) > val; 469 | else if (op == '<') 470 | return analogRead(hw.pin) < val; 471 | else if (op == '=') 472 | return analogRead(hw.pin) == val; 473 | else 474 | return false; 475 | }; 476 | 477 | ext.mapValues = function(val, aMin, aMax, bMin, bMax) { 478 | var output = (((bMax - bMin) * (val - aMin)) / (aMax - aMin)) + bMin; 479 | return Math.round(output); 480 | }; 481 | 482 | ext._getStatus = function() { 483 | if (!connected) 484 | return { status:1, msg:'Disconnected' }; 485 | else 486 | return { status:2, msg:'Connected' }; 487 | }; 488 | 489 | ext._deviceRemoved = function(dev) { 490 | console.log('Device removed'); 491 | // Not currently implemented with serial devices 492 | }; 493 | 494 | var potentialDevices = []; 495 | ext._deviceConnected = function(dev) { 496 | potentialDevices.push(dev); 497 | if (!device) 498 | tryNextDevice(); 499 | }; 500 | 501 | var poller = null; 502 | var watchdog = null; 503 | function tryNextDevice() { 504 | device = potentialDevices.shift(); 505 | if (!device) return; 506 | 507 | device.open({ stopBits: 0, bitRate: 57600, ctsFlowControl: 0 }); 508 | console.log('Attempting connection with ' + device.id); 509 | device.set_receive_handler(function(data) { 510 | var inputData = new Uint8Array(data); 511 | processInput(inputData); 512 | }); 513 | 514 | poller = setInterval(function() { 515 | queryFirmware(); 516 | }, 1000); 517 | 518 | watchdog = setTimeout(function() { 519 | clearInterval(poller); 520 | poller = null; 521 | device.set_receive_handler(null); 522 | device.close(); 523 | device = null; 524 | tryNextDevice(); 525 | }, 5000); 526 | } 527 | 528 | ext._shutdown = function() { 529 | // TODO: Bring all pins down 530 | if (device) device.close(); 531 | if (poller) clearInterval(poller); 532 | device = null; 533 | }; 534 | 535 | // Check for GET param 'lang' 536 | var paramString = window.location.search.replace(/^\?|\/$/g, ''); 537 | var vars = paramString.split("&"); 538 | var lang = 'en'; 539 | for (var i=0; i 1 && pair[0]=='lang') 542 | lang = pair[1]; 543 | } 544 | 545 | var blocks = { 546 | en: [ 547 | ['h', 'when device is connected', 'whenConnected'], 548 | [' ', 'connect %m.hwOut to pin %n', 'connectHW', 'led A', 3], 549 | [' ', 'connect %m.hwIn to analog %n', 'connectHW', 'rotation knob', 0], 550 | ['-'], 551 | [' ', 'set %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 552 | [' ', 'set %m.leds brightness to %n%', 'setLED', 'led A', 100], 553 | [' ', 'change %m.leds brightness by %n%', 'changeLED', 'led A', 20], 554 | ['-'], 555 | [' ', 'rotate %m.servos to %n degrees', 'rotateServo', 'servo A', 180], 556 | [' ', 'rotate %m.servos by %n degrees', 'changeServo', 'servo A', 20], 557 | ['-'], 558 | ['h', 'when %m.buttons is %m.btnStates', 'whenButton', 'button A', 'pressed'], 559 | ['b', '%m.buttons pressed?', 'isButtonPressed', 'button A'], 560 | ['-'], 561 | ['h', 'when %m.hwIn %m.ops %n%', 'whenInput', 'rotation knob', '>', 50], 562 | ['r', 'read %m.hwIn', 'readInput', 'rotation knob'], 563 | ['-'], 564 | [' ', 'set pin %n %m.outputs', 'digitalWrite', 1, 'on'], 565 | [' ', 'set pin %n to %n%', 'analogWrite', 3, 100], 566 | ['-'], 567 | ['h', 'when pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 568 | ['b', 'pin %n on?', 'digitalRead', 1], 569 | ['-'], 570 | ['h', 'when analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 571 | ['r', 'read analog %n', 'analogRead', 0], 572 | ['-'], 573 | ['r', 'map %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 574 | ], 575 | de: [ 576 | ['h', 'Wenn Arduino verbunden ist', 'whenConnected'], 577 | [' ', 'Verbinde %m.hwOut mit Pin %n', 'connectHW', 'LED A', 3], 578 | [' ', 'Verbinde %m.hwIn mit Analog %n', 'connectHW', 'Drehknopf', 0], 579 | ['-'], 580 | [' ', 'Schalte %m.leds %m.outputs', 'digitalLED', 'LED A', 'Ein'], 581 | [' ', 'Setze %m.leds Helligkeit auf %n%', 'setLED', 'LED A', 100], 582 | [' ', 'Ändere %m.leds Helligkeit um %n%', 'changeLED', 'LED A', 20], 583 | ['-'], 584 | [' ', 'Drehe %m.servos auf %n Grad', 'rotateServo', 'Servo A', 180], 585 | [' ', 'Drehe %m.servos um %n Grad', 'changeServo', 'Servo A', 20], 586 | ['-'], 587 | ['h', 'Wenn %m.buttons ist %m.btnStates', 'whenButton', 'Taste A', 'gedrückt'], 588 | ['b', '%m.buttons gedrückt?', 'isButtonPressed', 'Taste A'], 589 | ['-'], 590 | ['h', 'Wenn %m.hwIn %m.ops %n%', 'whenInput', 'Drehknopf', '>', 50], 591 | ['r', 'Wert von %m.hwIn', 'readInput', 'Drehknopf'], 592 | ['-'], 593 | [' ', 'Schalte Pin %n %m.outputs', 'digitalWrite', 1, 'Ein'], 594 | [' ', 'Setze Pin %n auf %n%', 'analogWrite', 3, 100], 595 | ['-'], 596 | ['h', 'Wenn Pin %n ist %m.outputs', 'whenDigitalRead', 1, 'Ein'], 597 | ['b', 'Pin %n ein?', 'digitalRead', 1], 598 | ['-'], 599 | ['h', 'Wenn Analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 600 | ['r', 'Wert von Analog %n', 'analogRead', 0], 601 | ['-'], 602 | ['r', 'Setze %n von %n %n auf %n %n', 'mapValues', 50, 0, 100, -240, 240] 603 | ], 604 | fr: [ 605 | ['h', "Quand l'appareil est connecté", 'whenConnected'], 606 | [' ', 'Connecté %m.hwOut au pin %n', 'connectHW', 'LED A', 3], 607 | [' ', 'Connecté %m.hwIn au pin analogue %n', 'connectHW', 'Potentiomètre', 0], 608 | ['-'], 609 | [' ', 'Régler %m.leds LED %m.output Sortie', 'digitalLED', 'LED A', 'ON'], 610 | [' ', 'Régler %m.leds Luminosité de la LED à %n%', 'setLED', 'LED A', 100], 611 | [' ', 'Changer %m.leds Luminosité de la LED de %n%', 'changeLED', 'LED A', 20], 612 | ['-'], 613 | [' ', 'Tourner %m.servos Servo Moteur à %n degrés', 'rotateServo', 'Servo Moteur A', 180], 614 | [' ', 'Tourner %m.servos Servo Moteur de %n degrés', 'changeServo', 'Servo Moteur A', 20], 615 | ['-'], 616 | ['h', 'Quand %m.buttons Bouton est %m.btnStates', 'whenButton', 'Bouton A', 'Appuyé'], 617 | ['b', 'Le %m.buttons est-il pressé?', 'isButtonPressed', 'Bouton A'], 618 | ['-'], 619 | ['h', 'Quand %m.hwIn %m.ops %n%', 'whenInput', 'Potentiomètre', '>', 50], 620 | ['r', 'Lire %m.hwIn', 'readInput', 'Potentiomètre'], 621 | ['-'], 622 | [' ', 'Régler le Pin %n %m.outputs Sortie', 'digitalWrite', 1, 'ON'], 623 | [' ', 'Régler le Pin %n à %n%', 'analogWrite', 3, 100], 624 | ['-'], 625 | ['h', 'Quand le Pin %n est %m.outputs Sortie', 'whenDigitalRead', 1, 'ON'], 626 | ['b', 'Le Pin %n est-il démarré?', 'digitalRead', 1], 627 | ['-'], 628 | ['h', 'Quand le Pin analogique est %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 629 | ['r', 'Lire le Pin Analogique %n', 'analogRead', 0], 630 | ['-'], 631 | ['r', 'Mapper %n de %n %n à %n %n', 'mapValues', 50, 0, 100, -240, 240] 632 | ], 633 | it: [ 634 | ['h', 'quando Arduino è connesso', 'whenConnected'], 635 | [' ', 'connetti il %m.hwOut al pin %n', 'connectHW', 'led A', 3], 636 | [' ', 'connetti il %m.hwIn ad analog %n', 'connectHW', 'potenziometro', 0], 637 | ['-'], 638 | [' ', 'imposta %m.leds a %m.outputs', 'digitalLED', 'led A', 'acceso'], 639 | [' ', 'porta luminosità di %m.leds a %n%', 'setLED', 'led A', 100], 640 | [' ', 'cambia luminosità di %m.leds a %n%', 'changeLED', 'led A', 20], 641 | ['-'], 642 | [' ', 'ruota %m.servos fino a %n gradi', 'rotateServo', 'servo A', 180], 643 | [' ', 'ruota %m.servos di %n gradi', 'changeServo', 'servo A', 20], 644 | ['-'], 645 | ['h', 'quando tasto %m.buttons è %m.btnStates', 'whenButton', 'pulsante A', 'premuto'], 646 | ['b', '%m.buttons premuto?', 'isButtonPressed', 'pulsante A'], 647 | ['-'], 648 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenziometro', '>', 50], 649 | ['r', 'leggi %m.hwIn', 'readInput', 'potenziometro'], 650 | ['-'], 651 | [' ', 'imposta pin %n a %m.outputs', 'digitalWrite', 1, 'acceso'], 652 | [' ', 'porta pin %n al %n%', 'analogWrite', 3, 100], 653 | ['-'], 654 | ['h', 'quando pin %n è %m.outputs', 'whenDigitalRead', 1, 'acceso'], 655 | ['b', 'pin %n acceso?', 'digitalRead', 1], 656 | ['-'], 657 | ['h', 'quando analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 658 | ['r', 'leggi analog %n', 'analogRead', 0], 659 | ['-'], 660 | ['r', 'porta %n da %n %n a %n %n', 'mapValues', 50, 0, 100, -240, 240] 661 | ], 662 | ja: [ 663 | ['h', 'デバイスがつながったとき', 'whenConnected'], 664 | [' ', '%m.hwOut を %n ピンへつなぐ', 'connectHW', 'led A', 3], 665 | [' ', '%m.hwIn をアナログ入力 %n ピンへつなぐ', 'connectHW', 'rotation knob', 0], 666 | ['-'], 667 | [' ', '%m.leds を %m.outputs にする', 'digitalLED', 'led A', 'on'], 668 | [' ', '%m.leds の明るさを %n% にする', 'setLED', 'led A', 100], 669 | [' ', '%m.leds の明るさを %n% ずつ変える', 'changeLED', 'led A', 20], 670 | ['-'], 671 | [' ', '%m.servos を %n 度へ向ける', 'rotateServo', 'servo A', 180], 672 | [' ', '%m.servos を %n 度ずつ回す', 'changeServo', 'servo A', 20], 673 | ['-'], 674 | ['h', '%m.buttons が %m.btnStates とき', 'whenButton', 'ボタン A', '押された'], 675 | ['b', '%m.buttons 押された', 'isButtonPressed', 'ボタン A'], 676 | ['-'], 677 | ['h', '%m.hwIn が %m.ops %n% になったとき', 'whenInput', '回転つまみ', '>', 50], 678 | ['r', '%m.hwIn の値', 'readInput', '回転つまみ'], 679 | ['-'], 680 | [' ', 'デジタル出力 %n を %m.outputs にする', 'digitalWrite', 1, 'on'], 681 | [' ', 'アナログ出力 %n を %n% にする', 'analogWrite', 3, 100], 682 | ['-'], 683 | ['h', 'デジタル入力 %n が %m.outputs になったとき', 'whenDigitalRead', 1, 'on'], 684 | ['b', 'デジタル入力 %n はオン', 'digitalRead', 1], 685 | ['-'], 686 | ['h', 'アナログ入力 %n が %m.ops %n% になったとき', 'whenAnalogRead', 1, '>', 50], 687 | ['r', 'アナログ入力 %n の値', 'analogRead', 0], 688 | ['-'], 689 | ['r', '%n を %n ... %n から %n ... %n へ変換', 'mapValues', 50, 0, 100, -240, 240] 690 | ], 691 | ko: [ 692 | ['h', '아두이노가 연결됐을 때', 'whenConnected'], 693 | [' ', '%m.hwOut 를 %n 번 핀에 연결하기', 'connectHW', 'led A', 3], 694 | [' ', '%m.hwIn 를 아날로그 %n 번 핀에 연결하기', 'connectHW', '회전 손잡이', 0], 695 | ['-'], 696 | [' ', '%m.leds 를 %m.outputs', 'digitalLED', 'led A', '켜기'], 697 | [' ', '%m.leds 의 밝기를 %n% 로 설정하기', 'setLED', 'led A', 100], 698 | [' ', '%m.leds 의 밝기를 %n% 만큼 바꾸기', 'changeLED', 'led A', 20], 699 | ['-'], 700 | [' ', '%m.servos 를 %n 도로 회전하기', 'rotateServo', '서보모터 A', 180], 701 | [' ', '%m.servos 를 %n 도 만큼 회전하기', 'changeServo', '서보모터 A', 20], 702 | ['-'], 703 | ['h', '%m.buttons 의 상태가 %m.btnStates 일 때', 'whenButton', '버튼 A', '눌림'], 704 | ['b', '%m.buttons 가 눌려져 있는가?', 'isButtonPressed', '버튼 A'], 705 | ['-'], 706 | ['h', '%m.hwIn 의 값이 %m.ops %n% 일 때', 'whenInput', '회전 손잡이', '>', 50], 707 | ['r', '%m.hwIn 의 값', 'readInput', '회전 손잡이'], 708 | ['-'], 709 | [' ', '%n 번 핀을 %m.outputs', 'digitalWrite', 1, '켜기'], 710 | [' ', '%n 번 핀의 값을 %n% 로 설정하기', 'analogWrite', 3, 100], 711 | ['-'], 712 | ['h', '%n 번 핀의 상태가 %m.outputs 일 때', 'whenDigitalRead', 1, '켜기'], 713 | ['b', '%n 번 핀이 켜져있는가?', 'digitalRead', 1], 714 | ['-'], 715 | ['h', '아날로그 %n 번 핀의 값이 %m.ops %n% 일 때', 'whenAnalogRead', 1, '>', 50], 716 | ['r', '아날로그 %n 번 핀의 값', 'analogRead', 0], 717 | ['-'], 718 | ['r', '%n 을(를) %n ~ %n 에서 %n ~ %n 의 범위로 바꾸기', 'mapValues', 50, 0, 100, -240, 240] 719 | ], 720 | nb: [ 721 | ['h', 'når enheten tilkobles', 'whenConnected'], 722 | [' ', 'koble %m.hwOut til digital %n', 'connectHW', 'LED A', 3], 723 | [' ', 'koble %m.hwIn til analog %n', 'connectHW', 'dreieknapp', 0], 724 | ['-'], 725 | [' ', 'sett %m.leds %m.outputs', 'digitalLED', 'LED A', 'på'], 726 | [' ', 'sett %m.leds styrke til %n%', 'setLED', 'LED A', 100], 727 | [' ', 'endre %m.leds styrke med %n%', 'changeLED', 'LED A', 20], 728 | ['-'], 729 | [' ', 'rotér %m.servos til %n grader', 'rotateServo', 'servo A', 180], 730 | [' ', 'rotér %m.servos med %n grader', 'changeServo', 'servo A', 20], 731 | ['-'], 732 | ['h', 'når %m.buttons %m.btnStates', 'whenButton', 'knapp A', 'trykkes'], 733 | ['b', '%m.buttons trykket?', 'isButtonPressed', 'knapp A'], 734 | ['-'], 735 | ['h', 'når %m.hwIn %m.ops %n%', 'whenInput', 'dreieknapp', '>', 50], 736 | ['r', '%m.hwIn verdi', 'readInput', 'dreieknapp'], 737 | ['-'], 738 | [' ', 'sett digital %n %m.outputs', 'digitalWrite', 1, 'på'], 739 | [' ', 'set utgang %n til %n%', 'analogWrite', 3, 100], 740 | ['-'], 741 | ['h', 'når digital %n er %m.outputs', 'whenDigitalRead', 1, 'på'], 742 | ['b', 'digital %n på?', 'digitalRead', 1], 743 | ['-'], 744 | ['h', 'når analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 745 | ['r', 'analog %n verdi', 'analogRead', 0], 746 | ['-'], 747 | ['r', 'skalér %n fra %n %n til %n %n', 'mapValues', 50, 0, 100, -240, 240] 748 | ], 749 | nl: [ 750 | ['h', 'als het apparaat verbonden is', 'whenConnected'], 751 | [' ', 'verbind %m.hwOut met pin %n', 'connectHW', 'led A', 3], 752 | [' ', 'verbind %m.hwIn met analoog %n', 'connectHW', 'draaiknop', 0], 753 | ['-'], 754 | [' ', 'schakel %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 755 | [' ', 'schakel %m.leds helderheid tot %n%', 'setLED', 'led A', 100], 756 | [' ', 'verander %m.leds helderheid met %n%', 'changeLED', 'led A', 20], 757 | ['-'], 758 | [' ', 'draai %m.servos tot %n graden', 'rotateServo', 'servo A', 180], 759 | [' ', 'draai %m.servos met %n graden', 'changeServo', 'servo A', 20], 760 | ['-'], 761 | ['h', 'wanneer %m.buttons is %m.btnStates', 'whenButton', 'knop A', 'in gedrukt'], 762 | ['b', '%m.buttons ingedrukt?', 'isButtonPressed', 'knop A'], 763 | ['-'], 764 | ['h', 'wanneer%m.hwIn %m.ops %n%', 'whenInput', 'draaiknop', '>', 50], 765 | ['r', 'read %m.hwIn', 'readInput', 'draaiknop'], 766 | ['-'], 767 | [' ', 'schakel pin %n %m.outputs', 'digitalWrite', 1, 'on'], 768 | [' ', 'schakel pin %n tot %n%', 'analogWrite', 3, 100], 769 | ['-'], 770 | ['h', 'wanneer pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 771 | ['b', 'pin %n aan?', 'digitalRead', 1], 772 | ['-'], 773 | ['h', 'wanneer analoge %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 774 | ['r', 'lees analoge %n', 'analogRead', 0], 775 | ['-'], 776 | ['r', 'zet %n van %n %n tot %n %n', 'mapValues', 50, 0, 100, -240, 240] 777 | ], 778 | pl: [ 779 | ['h', 'kiedy urządzenie jest podłączone', 'whenConnected'], 780 | [' ', 'podłącz %m.hwOut do pinu %n', 'connectHW', 'led A', 3], 781 | [' ', 'podłącz %m.hwIn do we analogowego %n', 'connectHW', 'pokrętło', 0], 782 | ['-'], 783 | [' ', 'ustaw %m.leds na %m.outputs', 'digitalLED', 'led A', 'włączony'], 784 | [' ', 'ustaw jasność %m.leds na %n%', 'setLED', 'led A', 100], 785 | [' ', 'zmień jasność %m.leds o %n%', 'changeLED', 'led A', 20], 786 | ['-'], 787 | [' ', 'obróć %m.servos w położenie %n degrees', 'rotateServo', 'serwo A', 180], 788 | [' ', 'obróć %m.servos o %n degrees', 'changeServo', 'serwo A', 20], 789 | ['-'], 790 | ['h', 'kiedy %m.buttons jest %m.btnStates', 'whenButton', 'przycisk A', 'wciśnięty'], 791 | ['b', 'czy %m.buttons jest wciśnięty?', 'isButtonPressed', 'przycisk A'], 792 | ['-'], 793 | ['h', 'kiedy %m.hwIn jest w położeniu %m.ops %n%', 'whenInput', 'pokrętło', '>', 50], 794 | ['r', 'odczytaj ustawienie %m.hwIn', 'readInput', 'pokrętła'], 795 | ['-'], 796 | [' ', 'ustaw pin %n jako %m.outputs', 'digitalWrite', 1, 'włączony'], 797 | [' ', 'ustaw pin %n na %n%', 'analogWrite', 3, 100], 798 | ['-'], 799 | ['h', 'kiedy pin %n jest %m.outputs', 'whenDigitalRead', 1, 'włączony'], 800 | ['b', 'czy pin %n jest włączony?', 'digitalRead', 1], 801 | ['-'], 802 | ['h', 'kiedy we analogowe %n jest w położeniu %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 803 | ['r', 'odczytaj we analogowe %n', 'analogRead', 0], 804 | ['-'], 805 | ['r', 'przekształć wartość %n z zakresu %n %n na %n %n', 'mapValues', 50, 0, 100, -240, 240] 806 | ], 807 | pt: [ 808 | ['h', 'Quando dispositivo estiver conectado', 'whenConnected'], 809 | [' ', 'conectar%m.hwOut para pino %n', 'connectHW', 'led A', 3], 810 | [' ', 'conectar %m.hwIn para analogico %n', 'connectHW', 'potenciometro', 0], 811 | ['-'], 812 | [' ', 'estado %m.leds %m.outputs', 'digitalLED', 'led A', 'ligado'], 813 | [' ', 'estado %m.leds brilho to %n%', 'setLED', 'led A', 100], 814 | [' ', 'mudar %m.leds brilho em %n%', 'changeLED', 'led A', 20], 815 | ['-'], 816 | [' ', 'girar %m.servos para %n graus', 'rotateServo', 'servo A', 180], 817 | [' ', 'girar %m.servos em %n graus', 'changeServo', 'servo A', 20], 818 | ['-'], 819 | ['h', 'quando %m.buttons is %m.btnStates', 'whenButton', 'botao A', 'pressionado'], 820 | ['b', '%m.buttons pressionado?', 'isButtonPressed', 'botao A'], 821 | ['-'], 822 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenciometro', '>', 50], 823 | ['r', 'read %m.hwIn', 'readInput', 'potenciometro'], 824 | ['-'], 825 | [' ', 'estado digital pino %n %m.outputs', 'digitalWrite', 1, 'ligado'], 826 | [' ', 'estado analogico pino %n to %n%', 'analogWrite', 3, 100], 827 | ['-'], 828 | ['h', 'quando pino %n is %m.outputs', 'whenDigitalRead', 1, 'ligado'], 829 | ['b', 'pino %n ligado?', 'digitalRead', 1], 830 | ['-'], 831 | ['h', 'quando valor analogico %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 832 | ['r', 'ler valor analogico %n', 'analogRead', 0], 833 | ['-'], 834 | ['r', 'mapear %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 835 | ], 836 | ru: [ 837 | ['h', 'когда устройство подключено', 'whenConnected'], 838 | [' ', 'подключить %m.hwOut к выводу %n', 'connectHW', 'светодиод A', 3], 839 | [' ', 'подключить %m.hwIn к ан. входу %n', 'connectHW', 'потенциометр', 0], 840 | ['-'], 841 | [' ', 'установить %m.leds в %m.outputs', 'digitalLED', 'светодиод A', 'включен'], 842 | [' ', 'установить яркость %m.leds в %n%', 'setLED', 'светодиод A', 100], 843 | [' ', 'изменить яркость %m.leds на %n%', 'changeLED', 'светодиод A', 20], 844 | ['-'], 845 | [' ', 'установить %m.servos в позицию %n °', 'rotateServo', 'серво A', 180], 846 | [' ', 'повернуть %m.servos на %n °', 'changeServo', 'серво A', 20], 847 | ['-'], 848 | ['h', 'когда %m.buttons %m.btnStates', 'whenButton', 'кнопка A', 'нажата'], 849 | ['b', '%m.buttons нажата?', 'isButtonPressed', 'кнопка A'], 850 | ['-'], 851 | ['h', 'когда %m.hwIn %m.ops %n%', 'whenInput', 'потенциометр', '>', 50], 852 | ['r', 'значение %m.hwIn', 'readInput', 'потенциометр'], 853 | ['-'], 854 | [' ', 'установить выход %n в %m.outputs', 'digitalWrite', 1, 'включен'], 855 | [' ', 'установить ан. выход %n в %n%', 'analogWrite', 3, 100], 856 | ['-'], 857 | ['h', 'когда вход %n %m.outputs', 'whenDigitalRead', 1, 'включен'], 858 | ['b', 'вход %n вкл?', 'digitalRead', 1], 859 | ['-'], 860 | ['h', 'когда ан. вход %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 861 | ['r', 'значение ан. входа %n', 'analogRead', 0], 862 | ['-'], 863 | ['r', 'отобразить %n из %n %n в %n %n', 'mapValues', 50, 0, 100, -240, 240] 864 | ], 865 | el: [ 866 | ['h', 'Όταν η συσκευή είναι συνδεδεμένη', 'whenConnected'], 867 | [' ', 'σύνδεσε το %m.hwOut στο pin %n', 'connectHW', 'led A', 3], 868 | [' ', 'σύνδεσε το %m.hwIn στο αναλογικό %n', 'connectHW', 'ποντεσιόμετρο', 0], 869 | ['-'], 870 | [' ', 'άλλαξε το %m.leds σε %m.outputs', 'digitalLED', 'led A', 'ενεργοποιημένο'], 871 | [' ', 'όρισε στο %m.leds τη φωτεινότητα ίση με %n%', 'setLED', 'led A', 100], 872 | [' ', 'άλλαξε στο %m.leds τη φωτεινότητα κατά %n%', 'changeLED', 'led A', 20], 873 | ['-'], 874 | [' ', 'στρίψε το %m.servos στις %n μοίρες', 'rotateServo', 'servo A', 180], 875 | [' ', 'στρίψε το %m.servos κατά %n μοίρες', 'changeServo', 'servo A', 20], 876 | ['-'], 877 | ['h', 'Όταν το %m.buttons είναι %m.btnStates', 'whenButton', 'κουμπί A', 'πατημένο'], 878 | ['b', 'το %m.buttons πατήθηκε;', 'isButtonPressed', 'κουμπί A'], 879 | ['-'], 880 | ['h', 'Όταν το %m.hwIn %m.ops %n%', 'whenInput', 'ποντεσιόμετρο', '>', 50], 881 | ['r', 'διάβασε %m.hwIn', 'readInput', 'ποντεσιόμετρο'], 882 | ['-'], 883 | [' ', 'άλλαξε το pin %n σε %m.outputs', 'digitalWrite', 1, 'ενεργοποιημένο'], 884 | [' ', 'όρισε το pin %n σε %n%', 'analogWrite', 3, 100], 885 | ['-'], 886 | ['h', 'Όταν το pin %n είναι %m.outputs', 'whenDigitalRead', 1, 'ενεργοποιημένο'], 887 | ['b', 'το pin %n είναι ενεργοποιημένο;', 'digitalRead', 1], 888 | ['-'], 889 | ['h', 'Όταν το αναλογικό %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 890 | ['r', 'διάβασε το αναλογικό %n', 'analogRead', 0], 891 | ['-'], 892 | ['r', 'συσχέτισε %n από %n %n έως %n %n', 'mapValues', 50, 0, 100, -240, 240] 893 | ], 894 | es: [ 895 | ['h', 'al conectar el dispositivo', 'whenConnected'], 896 | [' ', 'conectar %m.hwOut al pin %n', 'connectHW', 'led A', 3], 897 | [' ', 'conectar %m.hwIn al pin analógico %n', 'connectHW', 'potenciómetro', 0], 898 | ['-'], 899 | [' ', 'fijar estado de %m.leds a %m.outputs', 'digitalLED', 'led A', 'on'], 900 | [' ', 'fijar brillo de %m.leds a %n%', 'setLED', 'led A', 100], 901 | [' ', 'cambiar brillo de %m.leds por %n%', 'changeLED', 'led A', 20], 902 | ['-'], 903 | [' ', 'apuntar %m.servos en dirección %n grados', 'rotateServo', 'servo A', 180], 904 | [' ', 'girar %m.servos %n grados', 'changeServo', 'servo A', 20], 905 | ['-'], 906 | ['h', 'cuando el %m.buttons esté %m.btnStates', 'whenButton', 'botón A', 'presionado'], 907 | ['b', '¿%m.buttons presionado?', 'isButtonPressed', 'botón A'], 908 | ['-'], 909 | ['h', 'cuando %m.hwIn %m.ops %n%', 'whenInput', 'potenciómetro', '>', 50], 910 | ['r', 'leer %m.hwIn', 'readInput', 'potenciómetro'], 911 | ['-'], 912 | [' ', 'fijar estado de pin %n a %m.outputs', 'digitalWrite', 1, 'on'], 913 | [' ', 'fijar pin analógico %n al %n%', 'analogWrite', 3, 100], 914 | ['-'], 915 | ['h', 'cuando el pin %n esté %m.outputs', 'whenDigitalRead', 1, 'on'], 916 | ['b', '¿pin %n on?', 'digitalRead', 1], 917 | ['-'], 918 | ['h', 'cuando pin analógico %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 919 | ['r', 'leer analógico %n', 'analogRead', 0], 920 | ['-'], 921 | ['r', 'convertir %n de %n %n a %n %n', 'mapValues', 50, 0, 100, -240, 240] 922 | ], 923 | zh: [ 924 | ['h', '當裝置連接時', 'whenConnected'], 925 | [' ', '連接 %m.hwOut 到腳位 %n', 'connectHW', '發光二極體 A', 3], 926 | [' ', '連接 %m.hwIn 到類比 %n', 'connectHW', '旋鈕', 0], 927 | ['-'], 928 | [' ', '設定 %m.leds %m.outputs', 'digitalLED', '發光二極體 A', 'on'], 929 | [' ', '設定 %m.leds 亮度為 %n%', 'setLED', '發光二極體 A', 100], 930 | [' ', '改變 %m.leds 亮度 %n%', 'changeLED', '發光二極體 A', 20], 931 | ['-'], 932 | [' ', '旋轉 %m.servos 到 %n 度', 'rotateServo', '伺服馬達 A', 180], 933 | [' ', '旋轉 %m.servos %n 度', 'changeServo', '伺服馬達 A', 20], 934 | ['-'], 935 | ['h', '當 %m.buttons 為 %m.btnStates', 'whenButton', '按鈕 A', '按下'], 936 | ['b', '%m.buttons 按下?', 'isButtonPressed', '按鈕 A'], 937 | ['-'], 938 | ['h', '當 %m.hwIn %m.ops %n%', 'whenInput', '旋鈕', '>', 50], 939 | ['r', '讀取 %m.hwIn', 'readInput', '旋鈕'], 940 | ['-'], 941 | [' ', '設定腳位 %n %m.outputs', 'digitalWrite', 1, '開'], 942 | [' ', '設定腳位 %n 為 %n%', 'analogWrite', 3, 100], 943 | ['-'], 944 | ['h', '當腳位 %n 為 %m.outputs', 'whenDigitalRead', 1, '開'], 945 | ['b', '腳位 %n 開?', 'digitalRead', 1], 946 | ['-'], 947 | ['h', '當類比 %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 948 | ['r', '讀取類比 %n', 'analogRead', 0], 949 | ['-'], 950 | ['r', '對應 %n 由 %n %n 為 %n %n', 'mapValues', 50, 0, 100, -240, 240] 951 | ] 952 | }; 953 | 954 | var menus = { 955 | en: { 956 | buttons: ['button A', 'button B', 'button C', 'button D'], 957 | btnStates: ['pressed', 'released'], 958 | hwIn: ['rotation knob', 'light sensor', 'temperature sensor'], 959 | hwOut: ['led A', 'led B', 'led C', 'led D', 'button A', 'button B', 'button C', 'button D', 'servo A', 'servo B', 'servo C', 'servo D'], 960 | leds: ['led A', 'led B', 'led C', 'led D'], 961 | outputs: ['on', 'off'], 962 | ops: ['>', '=', '<'], 963 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 964 | }, 965 | de: { 966 | buttons: ['Taste A', 'Taste B', 'Taste C', 'Taste D'], 967 | btnStates: ['gedrückt', 'losgelassen'], 968 | hwIn: ['Drehknopf', 'Lichtsensor', 'Temperatursensor'], 969 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Taste A', 'Taste B', 'Taste C', 'Taste D', 'Servo A', 'Servo B', 'Servo C', 'Servo D'], 970 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 971 | outputs: ['Ein', 'Aus'], 972 | ops: ['>', '=', '<'], 973 | servos: ['Servo A', 'Servo B', 'Servo C', 'Servo D'] 974 | }, 975 | fr: { 976 | buttons: ['Bouton A', 'Bouton B', 'Bouton C', 'Bouton D'], 977 | btnStates: ['Appuyé', 'Relâché'], 978 | hwIn: ['Potentiomètre', 'Capteur de Lumière', 'Capteur de Temperature'], 979 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Bouton A', 'Bouton B', 'Bouton C', 'Bouton D', 'Servo Moteur A', 'Servo Moteur B', 'Servo Moteur C', 'Servo Moteur D'], 980 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 981 | outputs: ['ON', 'OFF'], 982 | ops: ['>', '=', '<'], 983 | servos: ['Servo Moteur A', 'Servo Moteur B', 'Servo Moteur C', 'Servo Moteur D'] 984 | }, 985 | it: { 986 | buttons: ['pulsante A', 'pulsante B', 'pulsante C', 'pulsante D'], 987 | btnStates: ['premuto', 'rilasciato'], 988 | hwIn: ['potenziometro', 'sensore di luce', 'sensore di temperatura'], 989 | hwOut: ['led A', 'led B', 'led C', 'led D', 'pulsante A', 'pulsante B', 'pulsante C', 'pulsante D', 'servo A', 'servo B', 'servo C', 'servo D'], 990 | leds: ['led A', 'led B', 'led C', 'led D'], 991 | outputs: ['acceso', 'spento'], 992 | ops: ['>', '=', '<'], 993 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 994 | }, 995 | ja: { 996 | buttons: ['ボタン A', 'ボタン B', 'ボタン C', 'ボタン D'], 997 | btnStates: ['押された', '放された'], 998 | hwIn: ['回転つまみ', '光センサー', '温度センサー'], 999 | hwOut: ['led A', 'led B', 'led C', 'led D', 'ボタン A', 'ボタン B', 'ボタン C', 'ボタン D', 'サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'], 1000 | leds: ['led A', 'led B', 'led C', 'led D'], 1001 | outputs: ['オン', 'オフ'], 1002 | ops: ['>', '=', '<'], 1003 | servos: ['サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'] 1004 | }, 1005 | ko: { 1006 | buttons: ['버튼 A', '버튼 B', '버튼 C', '버튼 D'], 1007 | btnStates: ['눌림', '떼짐'], 1008 | hwIn: ['회전 손잡이', '조도 센서', '온도 센서'], 1009 | hwOut: ['led A', 'led B', 'led C', 'led D', '버튼 A', '버튼 B', '버튼 C', '버튼 D', '서보모터 A', '서보모터 B', '서보모터 C', '서보모터 D'], 1010 | leds: ['led A', 'led B', 'led C', 'led D'], 1011 | outputs: ['켜기', '끄기'], 1012 | ops: ['>', '=', '<'], 1013 | servos: ['서보모터 A', '서보모터 B', '서보모터 C', '서보모터 D'] 1014 | }, 1015 | nb: { 1016 | buttons: ['knapp A', 'knapp B', 'knapp C', 'knapp D'], 1017 | btnStates: ['trykkes', 'slippes'], 1018 | hwIn: ['dreieknapp', 'lyssensor', 'temperatursensor'], 1019 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'knapp A', 'knapp B', 'knapp C', 'knapp D', 'servo A', 'servo B', 'servo C', 'servo D'], 1020 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 1021 | outputs: ['på', 'av'], 1022 | ops: ['>', '=', '<'], 1023 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 1024 | }, 1025 | nl: { 1026 | buttons: ['knop A', 'knop B', 'knop C', 'knop D'], 1027 | btnStates: ['ingedrukt', 'losgelaten'], 1028 | hwIn: ['draaiknop', 'licht sensor', 'temperatuur sensor'], 1029 | hwOut: ['led A', 'led B', 'led C', 'led D', 'knop A', 'knop B', 'knop C', 'knop D', 'servo A', 'servo B', 'servo C', 'servo D'], 1030 | leds: ['led A', 'led B', 'led C', 'led D'], 1031 | outputs: ['aan', 'uit'], 1032 | ops: ['>', '=', '<'], 1033 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 1034 | }, 1035 | pl: { 1036 | buttons: ['przycisk A', 'przycisk B', 'przycisk C', 'przycisk D'], 1037 | btnStates: ['wciśnięty', 'zwolniony'], 1038 | hwIn: ['pokrętło', 'czujnik światła', 'czujnik temperatury'], 1039 | hwOut: ['led A', 'led B', 'led C', 'led D', 'przycisk A', 'przycisk B', 'przycisk C', 'przycisk D', 'serwo A', 'serwo B', 'serwo C', 'serwo D'], 1040 | leds: ['led A', 'led B', 'led C', 'led D'], 1041 | outputs: ['włączony', 'wyłączony'], 1042 | ops: ['>', '=', '<'], 1043 | servos: ['serwo A', 'serwo B', 'serwo C', 'serwo D'] 1044 | }, 1045 | pt: { 1046 | buttons: ['botao A', 'botao B', 'botao C', 'botao D'], 1047 | btnStates: ['pressionado', 'solto'], 1048 | hwIn: ['potenciometro', 'sensor de luz', 'sensor de temperatura'], 1049 | hwOut: ['led A', 'led B', 'led C', 'led D', 'botao A', 'botao B', 'botao C', 'botao D', 'servo A', 'servo B', 'servo C', 'servo D'], 1050 | leds: ['led A', 'led B', 'led C', 'led D'], 1051 | outputs: ['ligado', 'desligado'], 1052 | ops: ['>', '=', '<'], 1053 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 1054 | }, 1055 | ru: { 1056 | buttons: ['кнопка A', 'кнопка B', 'кнопка C', 'кнопка D'], 1057 | btnStates: ['нажата', 'отпущена'], 1058 | hwIn: ['потенциометр', 'датчик света', 'датчик температуры'], 1059 | hwOut: ['светодиод A', 'светодиод B', 'светодиод C', 'светодиод D', 'кнопка A', 'кнопка B', 'кнопка C', 'кнопка D', 'серво A', 'серво B', 'серво C', 'серво D'], 1060 | leds: ['светодиод A', 'светодиод B', 'светодиод C', 'светодиод D'], 1061 | outputs: ['включен', 'выключен'], 1062 | ops: ['>', '=', '<'], 1063 | servos: ['серво A', 'серво B', 'серво C', 'серво D'] 1064 | }, 1065 | el: { 1066 | buttons: ['κουμπί A', 'κουμπί B', 'κουμπί C', 'κουμπί D'], 1067 | btnStates: ['πατημένο', 'ελεύθερο'], 1068 | hwIn: ['ποντεσιόμετρο', 'φωτοαισθητήρα', 'θερμοαισθητήρα'], 1069 | hwOut: ['led A', 'led B', 'led C', 'led D', 'κουμπί A', 'κουμπί B', 'κουμπί C', 'κουμπί D', 'servo A', 'servo B', 'servo C', 'servo D'], 1070 | leds: ['led A', 'led B', 'led C', 'led D'], 1071 | outputs: ['ενεργοποιημένο', 'απενεργοποιημένο'], 1072 | ops: ['>', '=', '<'], 1073 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 1074 | }, 1075 | es: { 1076 | buttons: ['botón A', 'botón B', 'botón C', 'botón D'], 1077 | btnStates: ['pulsado', 'liberado'], 1078 | hwIn: ['potenciómetro', 'sensor de luz', 'sensor de temperatura'], 1079 | hwOut: ['led A', 'led B', 'led C', 'led D', 'botón A', 'botón B', 'botón C', 'botón D', 'servo A', 'servo B', 'servo C', 'servo D'], 1080 | leds: ['led A', 'led B', 'led C', 'led D'], 1081 | outputs: ['on', 'off'], 1082 | ops: ['>', '=', '<'], 1083 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 1084 | }, 1085 | zh: { 1086 | buttons: ['按鈕 A', '按鈕 B', '按鈕 C', '按鈕 D'], 1087 | btnStates: ['按下', '放開'], 1088 | hwIn: ['旋鈕', '光感應器', '溫度感應器'], 1089 | hwOut: ['發光二極體 A', '發光二極體 B', '發光二極體 C', '發光二極體 D', '按鈕 A', '按鈕 B', '按鈕 C', '按鈕 D', '伺服馬達 A', '伺服馬達 B', '伺服馬達 C', '伺服馬達 D'], 1090 | leds: ['發光二極體 A', '發光二極體 B', '發光二極體 C', '發光二極體 D'], 1091 | outputs: ['開', '關'], 1092 | ops: ['>', '=', '<'], 1093 | servos: ['伺服馬達 A', '伺服馬達 B', '伺服馬達 C', '伺服馬達 D'] 1094 | } 1095 | }; 1096 | 1097 | var descriptor = { 1098 | blocks: blocks[lang], 1099 | menus: menus[lang], 1100 | url: 'http://khanning.github.io/scratch-arduino-extension' 1101 | }; 1102 | 1103 | ScratchExtensions.register('Arduino', descriptor, ext, {type:'serial'}); 1104 | 1105 | })({}); 1106 | -------------------------------------------------------------------------------- /arduino_extension_debug.js: -------------------------------------------------------------------------------- 1 | /* 2 | *This program is free software: you can redistribute it and/or modify 3 | *it under the terms of the GNU General Public License as published by 4 | *the Free Software Foundation, either version 3 of the License, or 5 | *(at your option) any later version. 6 | * 7 | *This program is distributed in the hope that it will be useful, 8 | *but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | *GNU General Public License for more details. 11 | * 12 | *You should have received a copy of the GNU General Public License 13 | *along with this program. If not, see . 14 | */ 15 | 16 | (function(ext) { 17 | 18 | var PIN_MODE = 0xF4, 19 | REPORT_DIGITAL = 0xD0, 20 | REPORT_ANALOG = 0xC0, 21 | DIGITAL_MESSAGE = 0x90, 22 | START_SYSEX = 0xF0, 23 | END_SYSEX = 0xF7, 24 | QUERY_FIRMWARE = 0x79, 25 | REPORT_VERSION = 0xF9, 26 | ANALOG_MESSAGE = 0xE0, 27 | ANALOG_MAPPING_QUERY = 0x69, 28 | ANALOG_MAPPING_RESPONSE = 0x6A, 29 | CAPABILITY_QUERY = 0x6B, 30 | CAPABILITY_RESPONSE = 0x6C; 31 | 32 | var INPUT = 0x00, 33 | OUTPUT = 0x01, 34 | ANALOG = 0x02, 35 | PWM = 0x03, 36 | SERVO = 0x04, 37 | SHIFT = 0x05, 38 | I2C = 0x06, 39 | ONEWIRE = 0x07, 40 | STEPPER = 0x08, 41 | ENCODER = 0x09, 42 | IGNORE = 0x7F; 43 | 44 | var LOW = 0, 45 | HIGH = 1; 46 | 47 | var MAX_DATA_BYTES = 4096; 48 | var MAX_PINS = 128; 49 | 50 | var parsingSysex = false, 51 | waitForData = 0, 52 | executeMultiByteCommand = 0, 53 | multiByteChannel = 0, 54 | sysexBytesRead = 0, 55 | storedInputData = new Uint8Array(MAX_DATA_BYTES); 56 | 57 | var digitalOutputData = new Uint8Array(16), 58 | digitalInputData = new Uint8Array(16), 59 | analogInputData = new Uint16Array(16); 60 | 61 | var analogChannel = new Uint8Array(MAX_PINS); 62 | var pinModes = []; 63 | for (var i = 0; i < 11; i++) pinModes[i] = []; 64 | 65 | var majorVersion = 0, 66 | minorVersion = 0; 67 | 68 | var connected = false; 69 | var notifyConnection = false; 70 | var device = null; 71 | var inputData = null; 72 | 73 | // TEMPORARY WORKAROUND 74 | // Since _deviceRemoved is not used with Serial devices 75 | // ping device regularly to check connection 76 | var pinging = false; 77 | var pingCount = 0; 78 | var pinger = null; 79 | 80 | var hwList = new HWList(); 81 | 82 | function HWList() { 83 | this.devices = []; 84 | 85 | this.add = function(dev, pin) { 86 | var device = this.search(dev); 87 | if (!device) { 88 | device = {name: dev, pin: pin, val: 0}; 89 | this.devices.push(device); 90 | } else { 91 | device.pin = pin; 92 | device.val = 0; 93 | } 94 | }; 95 | 96 | this.search = function(dev) { 97 | for (var i=0; i 6) { 120 | clearInterval(pinger); 121 | pinger = null; 122 | connected = false; 123 | if (device) device.close(); 124 | device = null; 125 | return; 126 | } 127 | } else { 128 | if (!device) { 129 | clearInterval(pinger); 130 | pinger = null; 131 | return; 132 | } 133 | queryFirmware(); 134 | pinging = true; 135 | } 136 | }, 100); 137 | } 138 | 139 | function hasCapability(pin, mode) { 140 | if (pinModes[mode].indexOf(pin) > -1) 141 | return true; 142 | else 143 | return false; 144 | } 145 | 146 | function queryFirmware() { 147 | var output = new Uint8Array([START_SYSEX, QUERY_FIRMWARE, END_SYSEX]); 148 | device.send(output.buffer); 149 | } 150 | 151 | function queryCapabilities() { 152 | console.log('Querying ' + device.id + ' capabilities'); 153 | var msg = new Uint8Array([ 154 | START_SYSEX, CAPABILITY_QUERY, END_SYSEX]); 155 | device.send(msg.buffer); 156 | } 157 | 158 | function queryAnalogMapping() { 159 | console.log('Querying ' + device.id + ' analog mapping'); 160 | var msg = new Uint8Array([ 161 | START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX]); 162 | device.send(msg.buffer); 163 | } 164 | 165 | function setDigitalInputs(portNum, portData) { 166 | digitalInputData[portNum] = portData; 167 | } 168 | 169 | function setAnalogInput(pin, val) { 170 | analogInputData[pin] = val; 171 | } 172 | 173 | function setVersion(major, minor) { 174 | majorVersion = major; 175 | minorVersion = minor; 176 | } 177 | 178 | function processSysexMessage() { 179 | console.log("Sysex Message:"); 180 | console.log(storedInputData); 181 | switch(storedInputData[0]) { 182 | case CAPABILITY_RESPONSE: 183 | for (var i = 1, pin = 0; pin < MAX_PINS; pin++) { 184 | while (storedInputData[i++] != 0x7F) { 185 | pinModes[storedInputData[i-1]].push(pin); 186 | i++; //Skip mode resolution 187 | } 188 | if (i == sysexBytesRead) break; 189 | } 190 | queryAnalogMapping(); 191 | break; 192 | case ANALOG_MAPPING_RESPONSE: 193 | for (var pin = 0; pin < analogChannel.length; pin++) 194 | analogChannel[pin] = 127; 195 | for (var i = 1; i < sysexBytesRead; i++) 196 | analogChannel[i-1] = storedInputData[i]; 197 | for (var pin = 0; pin < analogChannel.length; pin++) { 198 | if (analogChannel[pin] != 127) { 199 | var out = new Uint8Array([ 200 | REPORT_ANALOG | analogChannel[pin], 0x01]); 201 | device.send(out.buffer); 202 | } 203 | } 204 | notifyConnection = true; 205 | setTimeout(function() { 206 | notifyConnection = false; 207 | }, 100); 208 | break; 209 | case QUERY_FIRMWARE: 210 | if (!connected) { 211 | clearInterval(poller); 212 | poller = null; 213 | clearTimeout(watchdog); 214 | watchdog = null; 215 | connected = true; 216 | setTimeout(init, 200); 217 | } 218 | pinging = false; 219 | pingCount = 0; 220 | break; 221 | } 222 | } 223 | 224 | function processInput(inputData) { 225 | for (var i=0; i < inputData.length; i++) { 226 | 227 | if (parsingSysex) { 228 | if (inputData[i] == END_SYSEX) { 229 | parsingSysex = false; 230 | processSysexMessage(); 231 | } else { 232 | storedInputData[sysexBytesRead++] = inputData[i]; 233 | } 234 | } else if (waitForData > 0 && inputData[i] < 0x80) { 235 | storedInputData[--waitForData] = inputData[i]; 236 | if (executeMultiByteCommand !== 0 && waitForData === 0) { 237 | switch(executeMultiByteCommand) { 238 | case DIGITAL_MESSAGE: 239 | setDigitalInputs(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 240 | break; 241 | case ANALOG_MESSAGE: 242 | setAnalogInput(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 243 | break; 244 | case REPORT_VERSION: 245 | setVersion(storedInputData[1], storedInputData[0]); 246 | break; 247 | } 248 | } 249 | } else { 250 | if (inputData[i] < 0xF0) { 251 | command = inputData[i] & 0xF0; 252 | multiByteChannel = inputData[i] & 0x0F; 253 | } else { 254 | command = inputData[i]; 255 | } 256 | switch(command) { 257 | case DIGITAL_MESSAGE: 258 | case ANALOG_MESSAGE: 259 | case REPORT_VERSION: 260 | waitForData = 2; 261 | executeMultiByteCommand = command; 262 | break; 263 | case START_SYSEX: 264 | parsingSysex = true; 265 | sysexBytesRead = 0; 266 | break; 267 | } 268 | } 269 | } 270 | } 271 | 272 | function pinMode(pin, mode) { 273 | var msg = new Uint8Array([PIN_MODE, pin, mode]); 274 | device.send(msg.buffer); 275 | } 276 | 277 | function analogRead(pin) { 278 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 279 | return Math.round((analogInputData[pin] * 100) / 1023); 280 | } else { 281 | var valid = []; 282 | for (var i = 0; i < pinModes[ANALOG].length; i++) 283 | valid.push(i); 284 | console.log('ERROR: valid analog pins are ' + valid.join(', ')); 285 | return; 286 | } 287 | } 288 | 289 | function digitalRead(pin) { 290 | if (!hasCapability(pin, INPUT)) { 291 | console.log('ERROR: valid input pins are ' + pinModes[INPUT].join(', ')); 292 | return; 293 | } 294 | pinMode(pin, INPUT); 295 | return (digitalInputData[pin >> 3] >> (pin & 0x07)) & 0x01; 296 | } 297 | 298 | function analogWrite(pin, val) { 299 | if (!hasCapability(pin, PWM)) { 300 | console.log('ERROR: valid PWM pins are ' + pinModes[PWM].join(', ')); 301 | return; 302 | } 303 | if (val < 0) val = 0; 304 | else if (val > 100) val = 100; 305 | val = Math.round((val / 100) * 255); 306 | pinMode(pin, PWM); 307 | var msg = new Uint8Array([ 308 | ANALOG_MESSAGE | (pin & 0x0F), 309 | val & 0x7F, 310 | val >> 7]); 311 | device.send(msg.buffer); 312 | } 313 | 314 | function digitalWrite(pin, val) { 315 | if (!hasCapability(pin, OUTPUT)) { 316 | console.log('ERROR: valid output pins are ' + pinModes[OUTPUT].join(', ')); 317 | return; 318 | } 319 | var portNum = (pin >> 3) & 0x0F; 320 | if (val == LOW) 321 | digitalOutputData[portNum] &= ~(1 << (pin & 0x07)); 322 | else 323 | digitalOutputData[portNum] |= (1 << (pin & 0x07)); 324 | pinMode(pin, OUTPUT); 325 | var msg = new Uint8Array([ 326 | DIGITAL_MESSAGE | portNum, 327 | digitalOutputData[portNum] & 0x7F, 328 | digitalOutputData[portNum] >> 0x07]); 329 | device.send(msg.buffer); 330 | } 331 | 332 | function rotateServo(pin, deg) { 333 | if (!hasCapability(pin, SERVO)) { 334 | console.log('ERROR: valid servo pins are ' + pinModes[SERVO].join(', ')); 335 | return; 336 | } 337 | pinMode(pin, SERVO); 338 | var msg = new Uint8Array([ 339 | ANALOG_MESSAGE | (pin & 0x0F), 340 | deg & 0x7F, 341 | deg >> 0x07]); 342 | device.send(msg.buffer); 343 | } 344 | 345 | ext.whenConnected = function() { 346 | if (notifyConnection) return true; 347 | return false; 348 | }; 349 | 350 | ext.analogWrite = function(pin, val) { 351 | analogWrite(pin, val); 352 | }; 353 | 354 | ext.digitalWrite = function(pin, val) { 355 | if (val == 'on') 356 | digitalWrite(pin, HIGH); 357 | else if (val == 'off') 358 | digitalWrite(pin, LOW); 359 | }; 360 | 361 | ext.analogRead = function(pin) { 362 | return analogRead(pin); 363 | }; 364 | 365 | ext.digitalRead = function(pin) { 366 | return digitalRead(pin); 367 | }; 368 | 369 | ext.whenAnalogRead = function(pin, op, val) { 370 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 371 | if (op == '>') 372 | return analogRead(pin) > val; 373 | else if (op == '<') 374 | return analogRead(pin) < val; 375 | else if (op == '=') 376 | return analogRead(pin) == val; 377 | else 378 | return false; 379 | } 380 | }; 381 | 382 | ext.whenDigitalRead = function(pin, val) { 383 | if (hasCapability(pin, INPUT)) { 384 | if (val == 'on') 385 | return digitalRead(pin); 386 | else if (val == 'off') 387 | return digitalRead(pin) === false; 388 | } 389 | }; 390 | 391 | ext.connectHW = function(hw, pin) { 392 | hwList.add(hw, pin); 393 | }; 394 | 395 | ext.rotateServo = function(servo, deg) { 396 | var hw = hwList.search(servo); 397 | if (!hw) return; 398 | if (deg < 0) deg = 0; 399 | else if (deg > 180) deg = 180; 400 | rotateServo(hw.pin, deg); 401 | hw.val = deg; 402 | }; 403 | 404 | ext.changeServo = function(servo, change) { 405 | var hw = hwList.search(servo); 406 | if (!hw) return; 407 | var deg = hw.val + change; 408 | if (deg < 0) deg = 0; 409 | else if (deg > 180) deg = 180; 410 | rotateServo(hw.pin, deg); 411 | hw.val = deg; 412 | }; 413 | 414 | ext.setLED = function(led, val) { 415 | var hw = hwList.search(led); 416 | if (!hw) return; 417 | analogWrite(hw.pin, val); 418 | hw.val = val; 419 | }; 420 | 421 | ext.changeLED = function(led, val) { 422 | var hw = hwList.search(led); 423 | if (!hw) return; 424 | var b = hw.val + val; 425 | if (b < 0) b = 0; 426 | else if (b > 100) b = 100; 427 | analogWrite(hw.pin, b); 428 | hw.val = b; 429 | }; 430 | 431 | ext.digitalLED = function(led, val) { 432 | var hw = hwList.search(led); 433 | if (!hw) return; 434 | if (val == 'on') { 435 | digitalWrite(hw.pin, HIGH); 436 | hw.val = 255; 437 | } else if (val == 'off') { 438 | digitalWrite(hw.pin, LOW); 439 | hw.val = 0; 440 | } 441 | }; 442 | 443 | ext.readInput = function(name) { 444 | var hw = hwList.search(name); 445 | if (!hw) return; 446 | return analogRead(hw.pin); 447 | }; 448 | 449 | ext.whenButton = function(btn, state) { 450 | var hw = hwList.search(btn); 451 | if (!hw) return; 452 | if (state === 'pressed') 453 | return digitalRead(hw.pin); 454 | else if (state === 'released') 455 | return !digitalRead(hw.pin); 456 | }; 457 | 458 | ext.isButtonPressed = function(btn) { 459 | var hw = hwList.search(btn); 460 | if (!hw) return; 461 | return digitalRead(hw.pin); 462 | }; 463 | 464 | ext.whenInput = function(name, op, val) { 465 | var hw = hwList.search(name); 466 | if (!hw) return; 467 | if (op == '>') 468 | return analogRead(hw.pin) > val; 469 | else if (op == '<') 470 | return analogRead(hw.pin) < val; 471 | else if (op == '=') 472 | return analogRead(hw.pin) == val; 473 | else 474 | return false; 475 | }; 476 | 477 | ext.mapValues = function(val, aMin, aMax, bMin, bMax) { 478 | var output = (((bMax - bMin) * (val - aMin)) / (aMax - aMin)) + bMin; 479 | return Math.round(output); 480 | }; 481 | 482 | ext._getStatus = function() { 483 | if (!connected) 484 | return { status:1, msg:'Disconnected' }; 485 | else 486 | return { status:2, msg:'Connected' }; 487 | }; 488 | 489 | ext._deviceRemoved = function(dev) { 490 | console.log('Device removed'); 491 | // Not currently implemented with serial devices 492 | }; 493 | 494 | var potentialDevices = []; 495 | ext._deviceConnected = function(dev) { 496 | potentialDevices.push(dev); 497 | if (!device) 498 | tryNextDevice(); 499 | }; 500 | 501 | var poller = null; 502 | var watchdog = null; 503 | function tryNextDevice() { 504 | device = potentialDevices.shift(); 505 | if (!device) return; 506 | 507 | device.open({ stopBits: 0, bitRate: 57600, ctsFlowControl: 0 }); 508 | console.log('Attempting connection with ' + device.id); 509 | device.set_receive_handler(function(data) { 510 | var inputData = new Uint8Array(data); 511 | console.log("Input Data:"); 512 | console.log(inputData); 513 | processInput(inputData); 514 | }); 515 | 516 | poller = setInterval(function() { 517 | queryFirmware(); 518 | }, 1000); 519 | 520 | watchdog = setTimeout(function() { 521 | clearInterval(poller); 522 | poller = null; 523 | device.set_receive_handler(null); 524 | device.close(); 525 | device = null; 526 | tryNextDevice(); 527 | }, 5000); 528 | } 529 | 530 | ext._shutdown = function() { 531 | // TODO: Bring all pins down 532 | if (device) device.close(); 533 | if (poller) clearInterval(poller); 534 | device = null; 535 | }; 536 | 537 | // Check for GET param 'lang' 538 | var paramString = window.location.search.replace(/^\?|\/$/g, ''); 539 | var vars = paramString.split("&"); 540 | var lang = 'en'; 541 | for (var i=0; i 1 && pair[0]=='lang') 544 | lang = pair[1]; 545 | } 546 | 547 | var blocks = { 548 | en: [ 549 | ['h', 'when device is connected', 'whenConnected'], 550 | [' ', 'connect %m.hwOut to pin %n', 'connectHW', 'led A', 3], 551 | [' ', 'connect %m.hwIn to analog %n', 'connectHW', 'rotation knob', 0], 552 | ['-'], 553 | [' ', 'set %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 554 | [' ', 'set %m.leds brightness to %n%', 'setLED', 'led A', 100], 555 | [' ', 'change %m.leds brightness by %n%', 'changeLED', 'led A', 20], 556 | ['-'], 557 | [' ', 'rotate %m.servos to %n degrees', 'rotateServo', 'servo A', 180], 558 | [' ', 'rotate %m.servos by %n degrees', 'changeServo', 'servo A', 20], 559 | ['-'], 560 | ['h', 'when %m.buttons is %m.btnStates', 'whenButton', 'button A', 'pressed'], 561 | ['b', '%m.buttons pressed?', 'isButtonPressed', 'button A'], 562 | ['-'], 563 | ['h', 'when %m.hwIn %m.ops %n%', 'whenInput', 'rotation knob', '>', 50], 564 | ['r', 'read %m.hwIn', 'readInput', 'rotation knob'], 565 | ['-'], 566 | [' ', 'set pin %n %m.outputs', 'digitalWrite', 1, 'on'], 567 | [' ', 'set pin %n to %n%', 'analogWrite', 3, 100], 568 | ['-'], 569 | ['h', 'when pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 570 | ['b', 'pin %n on?', 'digitalRead', 1], 571 | ['-'], 572 | ['h', 'when analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 573 | ['r', 'read analog %n', 'analogRead', 0], 574 | ['-'], 575 | ['r', 'map %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 576 | ], 577 | de: [ 578 | ['h', 'Wenn Arduino verbunden ist', 'whenConnected'], 579 | [' ', 'Verbinde %m.hwOut mit Pin %n', 'connectHW', 'LED A', 3], 580 | [' ', 'Verbinde %m.hwIn mit Analog %n', 'connectHW', 'Drehknopf', 0], 581 | ['-'], 582 | [' ', 'Schalte %m.leds %m.outputs', 'digitalLED', 'LED A', 'Ein'], 583 | [' ', 'Setze %m.leds Helligkeit auf %n%', 'setLED', 'LED A', 100], 584 | [' ', 'Ändere %m.leds Helligkeit um %n%', 'changeLED', 'LED A', 20], 585 | ['-'], 586 | [' ', 'Drehe %m.servos auf %n Grad', 'rotateServo', 'Servo A', 180], 587 | [' ', 'Drehe %m.servos um %n Grad', 'changeServo', 'Servo A', 20], 588 | ['-'], 589 | ['h', 'Wenn %m.buttons ist %m.btnStates', 'whenButton', 'Taste A', 'gedrückt'], 590 | ['b', '%m.buttons gedrückt?', 'isButtonPressed', 'Taste A'], 591 | ['-'], 592 | ['h', 'Wenn %m.hwIn %m.ops %n%', 'whenInput', 'Drehknopf', '>', 50], 593 | ['r', 'Wert von %m.hwIn', 'readInput', 'Drehknopf'], 594 | ['-'], 595 | [' ', 'Schalte Pin %n %m.outputs', 'digitalWrite', 1, 'Ein'], 596 | [' ', 'Setze Pin %n auf %n%', 'analogWrite', 3, 100], 597 | ['-'], 598 | ['h', 'Wenn Pin %n ist %m.outputs', 'whenDigitalRead', 1, 'Ein'], 599 | ['b', 'Pin %n ein?', 'digitalRead', 1], 600 | ['-'], 601 | ['h', 'Wenn Analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 602 | ['r', 'Wert von Analog %n', 'analogRead', 0], 603 | ['-'], 604 | ['r', 'Setze %n von %n %n auf %n %n', 'mapValues', 50, 0, 100, -240, 240] 605 | ], 606 | it: [ 607 | ['h', 'quando Arduino è connesso', 'whenConnected'], 608 | [' ', 'connetti il %m.hwOut al pin %n', 'connectHW', 'led A', 3], 609 | [' ', 'connetti il %m.hwIn ad analog %n', 'connectHW', 'potenziometro', 0], 610 | ['-'], 611 | [' ', '%m.outputs il %m.leds', 'digitalLED', 'led A', 'on'], 612 | [' ', 'porta luminosità di %m.leds a %n%', 'setLED', 'led A', 100], 613 | [' ', 'cambia luminosità di %m.leds a %n%', 'changeLED', 'led A', 20], 614 | ['-'], 615 | [' ', 'ruota %m.servos fino a %n gradi', 'rotateServo', 'servo A', 180], 616 | [' ', 'ruota %m.servos di %n gradi', 'changeServo', 'servo A', 20], 617 | ['-'], 618 | ['h', 'quando tasto %m.buttons è %m.btnStates', 'whenButton', 'pulsante A', 'premuto'], 619 | ['b', '%m.buttons premuto?', 'isButtonPressed', 'pulsante A'], 620 | ['-'], 621 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenziometro', '>', 50], 622 | ['r', 'leggi %m.hwIn', 'readInput', 'potenziometro'], 623 | ['-'], 624 | [' ', 'porta pin %n a %m.outputs', 'digitalWrite', 1, 'acceso'], 625 | [' ', 'porta pin %n al %n%', 'analogWrite', 3, 100], 626 | ['-'], 627 | ['h', 'quando pin %n è %m.outputs', 'whenDigitalRead', 1, 'acceso'], 628 | ['b', 'pin %n acceso?', 'digitalRead', 1], 629 | ['-'], 630 | ['h', 'quando analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 631 | ['r', 'leggi analog %n', 'analogRead', 0], 632 | ['-'], 633 | ['r', 'porta %n da %n %n a %n %n', 'mapValues', 50, 0, 100, -240, 240] 634 | ], 635 | ja: [ 636 | ['h', 'デバイスがつながったとき', 'whenConnected'], 637 | [' ', '%m.hwOut を %n ピンへつなぐ', 'connectHW', 'led A', 3], 638 | [' ', '%m.hwIn をアナログ入力 %n ピンへつなぐ', 'connectHW', 'rotation knob', 0], 639 | ['-'], 640 | [' ', '%m.leds を %m.outputs にする', 'digitalLED', 'led A', 'on'], 641 | [' ', '%m.leds の明るさを %n% にする', 'setLED', 'led A', 100], 642 | [' ', '%m.leds の明るさを %n% ずつ変える', 'changeLED', 'led A', 20], 643 | ['-'], 644 | [' ', '%m.servos を %n 度へ向ける', 'rotateServo', 'servo A', 180], 645 | [' ', '%m.servos を %n 度ずつ回す', 'changeServo', 'servo A', 20], 646 | ['-'], 647 | ['h', '%m.buttons が %m.btnStates とき', 'whenButton', 'ボタン A', '押された'], 648 | ['b', '%m.buttons 押された', 'isButtonPressed', 'ボタン A'], 649 | ['-'], 650 | ['h', '%m.hwIn が %m.ops %n% になったとき', 'whenInput', '回転つまみ', '>', 50], 651 | ['r', '%m.hwIn の値', 'readInput', '回転つまみ'], 652 | ['-'], 653 | [' ', 'デジタル出力 %n を %m.outputs にする', 'digitalWrite', 1, 'on'], 654 | [' ', 'アナログ出力 %n を %n% にする', 'analogWrite', 3, 100], 655 | ['-'], 656 | ['h', 'デジタル入力 %n が %m.outputs になったとき', 'whenDigitalRead', 1, 'on'], 657 | ['b', 'デジタル入力 %n はオン', 'digitalRead', 1], 658 | ['-'], 659 | ['h', 'アナログ入力 %n が %m.ops %n% になったとき', 'whenAnalogRead', 1, '>', 50], 660 | ['r', 'アナログ入力 %n の値', 'analogRead', 0], 661 | ['-'], 662 | ['r', '%n を %n ... %n から %n ... %n へ変換', 'mapValues', 50, 0, 100, -240, 240] 663 | ], 664 | nb: [ 665 | ['h', 'når enheten tilkobles', 'whenConnected'], 666 | [' ', 'koble %m.hwOut til digital %n', 'connectHW', 'LED A', 3], 667 | [' ', 'koble %m.hwIn til analog %n', 'connectHW', 'dreieknapp', 0], 668 | ['-'], 669 | [' ', 'sett %m.leds %m.outputs', 'digitalLED', 'LED A', 'på'], 670 | [' ', 'sett %m.leds styrke til %n%', 'setLED', 'LED A', 100], 671 | [' ', 'endre %m.leds styrke med %n%', 'changeLED', 'LED A', 20], 672 | ['-'], 673 | [' ', 'rotér %m.servos til %n grader', 'rotateServo', 'servo A', 180], 674 | [' ', 'rotér %m.servos med %n grader', 'changeServo', 'servo A', 20], 675 | ['-'], 676 | ['h', 'når %m.buttons %m.btnStates', 'whenButton', 'knapp A', 'trykkes'], 677 | ['b', '%m.buttons trykket?', 'isButtonPressed', 'knapp A'], 678 | ['-'], 679 | ['h', 'når %m.hwIn %m.ops %n%', 'whenInput', 'dreieknapp', '>', 50], 680 | ['r', '%m.hwIn verdi', 'readInput', 'dreieknapp'], 681 | ['-'], 682 | [' ', 'sett digital %n %m.outputs', 'digitalWrite', 1, 'på'], 683 | [' ', 'set utgang %n til %n%', 'analogWrite', 3, 100], 684 | ['-'], 685 | ['h', 'når digital %n er %m.outputs', 'whenDigitalRead', 1, 'på'], 686 | ['b', 'digital %n på?', 'digitalRead', 1], 687 | ['-'], 688 | ['h', 'når analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 689 | ['r', 'analog %n verdi', 'analogRead', 0], 690 | ['-'], 691 | ['r', 'skalér %n fra %n %n til %n %n', 'mapValues', 50, 0, 100, -240, 240] 692 | ], 693 | nl: [ 694 | ['h', 'als het apparaat verbonden is', 'whenConnected'], 695 | [' ', 'verbindt %m.hwOut met pin %n', 'connectHW', 'led A', 3], 696 | [' ', 'verbindt %m.hwIn met analoog %n', 'connectHW', 'draaiknop', 0], 697 | ['-'], 698 | [' ', 'schakel %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 699 | [' ', 'schakel %m.leds helderheid tot %n%', 'setLED', 'led A', 100], 700 | [' ', 'verander %m.leds helderheid met %n%', 'changeLED', 'led A', 20], 701 | ['-'], 702 | [' ', 'draai %m.servos tot %n graden', 'rotateServo', 'servo A', 180], 703 | [' ', 'draai %m.servos met %n graden', 'changeServo', 'servo A', 20], 704 | ['-'], 705 | ['h', 'wanneer %m.buttons is %m.btnStates', 'whenButton', 'knop A', 'in gedrukt'], 706 | ['b', '%m.knoppen in gedrukt?', 'isButtonPressed', 'knoppen A'], 707 | ['-'], 708 | ['h', 'wanneer%m.hwIn %m.ops %n%', 'whenInput', 'draaiknop', '>', 50], 709 | ['r', 'read %m.hwIn', 'readInput', 'draaiknop'], 710 | ['-'], 711 | [' ', 'schakel pin %n %m.outputs', 'digitalWrite', 1, 'on'], 712 | [' ', 'schakel pin %n tot %n%', 'analogWrite', 3, 100], 713 | ['-'], 714 | ['h', 'wanneer pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 715 | ['b', 'pin %n aan?', 'digitalRead', 1], 716 | ['-'], 717 | ['h', 'wanneer analoge %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 718 | ['r', 'lees analoge %n', 'analogRead', 0], 719 | ['-'], 720 | ['r', 'zet %n van %n %n tot %n %n', 'mapValues', 50, 0, 100, -240, 240] 721 | ], 722 | pt: [ 723 | ['h', 'Quando dispositivo estiver conectado', 'whenConnected'], 724 | [' ', 'conectar%m.hwOut para pino %n', 'connectHW', 'led A', 3], 725 | [' ', 'conectar %m.hwIn para analogico %n', 'connectHW', 'potenciometro', 0], 726 | ['-'], 727 | [' ', 'estado %m.leds %m.outputs', 'digitalLED', 'led A', 'ligado'], 728 | [' ', 'estado %m.leds brilho to %n%', 'setLED', 'led A', 100], 729 | [' ', 'mudar %m.leds brilho em %n%', 'changeLED', 'led A', 20], 730 | ['-'], 731 | [' ', 'girar %m.servos para %n graus', 'rotateServo', 'servo A', 180], 732 | [' ', 'girar %m.servos em %n graus', 'changeServo', 'servo A', 20], 733 | ['-'], 734 | ['h', 'quando %m.buttons is %m.btnStates', 'whenButton', 'botao A', 'pressionado'], 735 | ['b', '%m.buttons pressionado?', 'isButtonPressed', 'botao A'], 736 | ['-'], 737 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenciometro', '>', 50], 738 | ['r', 'read %m.hwIn', 'readInput', 'potenciometro'], 739 | ['-'], 740 | [' ', 'estado digital pino %n %m.outputs', 'digitalWrite', 1, 'ligado'], 741 | [' ', 'estado analogico pino %n to %n%', 'analogWrite', 3, 100], 742 | ['-'], 743 | ['h', 'quando pino %n is %m.outputs', 'whenDigitalRead', 1, 'ligado'], 744 | ['b', 'pino %n ligado?', 'digitalRead', 1], 745 | ['-'], 746 | ['h', 'quando valor analogico %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 747 | ['r', 'ler valor analogico %n', 'analogRead', 0], 748 | ['-'], 749 | ['r', 'mapear %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 750 | ] 751 | }; 752 | 753 | var menus = { 754 | en: { 755 | buttons: ['button A', 'button B', 'button C', 'button D'], 756 | btnStates: ['pressed', 'released'], 757 | hwIn: ['rotation knob', 'light sensor', 'temperature sensor'], 758 | hwOut: ['led A', 'led B', 'led C', 'led D', 'button A', 'button B', 'button C', 'button D', 'servo A', 'servo B', 'servo C', 'servo D'], 759 | leds: ['led A', 'led B', 'led C', 'led D'], 760 | outputs: ['on', 'off'], 761 | ops: ['>', '=', '<'], 762 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 763 | }, 764 | de: { 765 | buttons: ['Taste A', 'Taste B', 'Taste C', 'Taste D'], 766 | btnStates: ['gedrückt', 'losgelassen'], 767 | hwIn: ['Drehknopf', 'Lichtsensor', 'Temperatursensor'], 768 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Taste A', 'Taste B', 'Taste C', 'Taste D', 'Servo A', 'Servo B', 'Servo C', 'Servo D'], 769 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 770 | outputs: ['Ein', 'Aus'], 771 | ops: ['>', '=', '<'], 772 | servos: ['Servo A', 'Servo B', 'Servo C', 'Servo D'] 773 | }, 774 | it: { 775 | buttons: ['pulsante A', 'pulsante B', 'pulsante C', 'pulsante D'], 776 | btnStates: ['premuto', 'rilasciato'], 777 | hwIn: ['potenziometro', 'sensore di luce', 'sensore di temperatura'], 778 | hwOut: ['led A', 'led B', 'led C', 'led D', 'pulsante A', 'pulsante B', 'pulsante C', 'pulsante D', 'servo A', 'servo B', 'servo C', 'servo D'], 779 | leds: ['led A', 'led B', 'led C', 'led D'], 780 | outputs: ['acceso', 'spento'], 781 | ops: ['>', '=', '<'], 782 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 783 | }, 784 | ja: { 785 | buttons: ['ボタン A', 'ボタン B', 'ボタン C', 'ボタン D'], 786 | btnStates: ['押された', '放された'], 787 | hwIn: ['回転つまみ', '光センサー', '温度センサー'], 788 | hwOut: ['led A', 'led B', 'led C', 'led D', 'ボタン A', 'ボタン B', 'ボタン C', 'ボタン D', 'サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'], 789 | leds: ['led A', 'led B', 'led C', 'led D'], 790 | outputs: ['オン', 'オフ'], 791 | ops: ['>', '=', '<'], 792 | servos: ['サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'] 793 | }, 794 | nb: { 795 | buttons: ['knapp A', 'knapp B', 'knapp C', 'knapp D'], 796 | btnStates: ['trykkes', 'slippes'], 797 | hwIn: ['dreieknapp', 'lyssensor', 'temperatursensor'], 798 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'knapp A', 'knapp B', 'knapp C', 'knapp D', 'servo A', 'servo B', 'servo C', 'servo D'], 799 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 800 | outputs: ['på', 'av'], 801 | ops: ['>', '=', '<'], 802 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 803 | }, 804 | nl: { 805 | buttons: ['knop A', 'knop B', 'knop C', 'knop D'], 806 | btnStates: ['ingedrukt', 'losgelaten'], 807 | hwIn: ['draaiknop', 'licht sensor', 'temperatuur sensor'], 808 | hwOut: ['led A', 'led B', 'led C', 'led D', 'knop A', 'knop B', 'knop C', 'knop D', 'servo A', 'servo B', 'servo C', 'servo D'], 809 | leds: ['led A', 'led B', 'led C', 'led D'], 810 | outputs: ['aan', 'uit'], 811 | ops: ['>', '=', '<'], 812 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 813 | }, 814 | pt: { 815 | buttons: ['botao A', 'botao B', 'botao C', 'botao D'], 816 | btnStates: ['pressionado', 'solto'], 817 | hwIn: ['potenciometro', 'sensor de luz', 'sensor de temperatura'], 818 | hwOut: ['led A', 'led B', 'led C', 'led D', 'botao A', 'botao B', 'botao C', 'botao D', 'servo A', 'servo B', 'servo C', 'servo D'], 819 | leds: ['led A', 'led B', 'led C', 'led D'], 820 | outputs: ['ligado', 'desligado'], 821 | ops: ['>', '=', '<'], 822 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 823 | } 824 | }; 825 | 826 | var descriptor = { 827 | blocks: blocks[lang], 828 | menus: menus[lang], 829 | url: 'http://khanning.github.io/scratch-arduino-extension' 830 | }; 831 | 832 | ScratchExtensions.register('Arduino Debug', descriptor, ext, {type:'serial'}); 833 | 834 | })({}); 835 | -------------------------------------------------------------------------------- /arduino_extension_simple.js: -------------------------------------------------------------------------------- 1 | /* 2 | *This program is free software: you can redistribute it and/or modify 3 | *it under the terms of the GNU General Public License as published by 4 | *the Free Software Foundation, either version 3 of the License, or 5 | *(at your option) any later version. 6 | * 7 | *This program is distributed in the hope that it will be useful, 8 | *but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | *GNU General Public License for more details. 11 | * 12 | *You should have received a copy of the GNU General Public License 13 | *along with this program. If not, see . 14 | */ 15 | 16 | (function(ext) { 17 | 18 | var PIN_MODE = 0xF4, 19 | REPORT_DIGITAL = 0xD0, 20 | REPORT_ANALOG = 0xC0, 21 | DIGITAL_MESSAGE = 0x90, 22 | START_SYSEX = 0xF0, 23 | END_SYSEX = 0xF7, 24 | QUERY_FIRMWARE = 0x79, 25 | REPORT_VERSION = 0xF9, 26 | ANALOG_MESSAGE = 0xE0, 27 | ANALOG_MAPPING_QUERY = 0x69, 28 | ANALOG_MAPPING_RESPONSE = 0x6A, 29 | CAPABILITY_QUERY = 0x6B, 30 | CAPABILITY_RESPONSE = 0x6C; 31 | 32 | var INPUT = 0x00, 33 | OUTPUT = 0x01, 34 | ANALOG = 0x02, 35 | PWM = 0x03, 36 | SERVO = 0x04, 37 | SHIFT = 0x05, 38 | I2C = 0x06, 39 | ONEWIRE = 0x07, 40 | STEPPER = 0x08, 41 | ENCODER = 0x09, 42 | SERIAL = 0x0A, 43 | PULLUP = 0x0B, 44 | IGNORE = 0x7F, 45 | TOTAL_PIN_MODES = 13; 46 | 47 | var LOW = 0, 48 | HIGH = 1; 49 | 50 | var MAX_DATA_BYTES = 4096; 51 | var MAX_PINS = 128; 52 | 53 | var parsingSysex = false, 54 | waitForData = 0, 55 | executeMultiByteCommand = 0, 56 | multiByteChannel = 0, 57 | sysexBytesRead = 0, 58 | storedInputData = new Uint8Array(MAX_DATA_BYTES); 59 | 60 | var digitalOutputData = new Uint8Array(16), 61 | digitalInputData = new Uint8Array(16), 62 | analogInputData = new Uint16Array(16), 63 | servoVals = new Uint8Array(MAX_PINS); 64 | 65 | var analogChannel = new Uint8Array(MAX_PINS); 66 | var pinModes = []; 67 | for (var i = 0; i < TOTAL_PIN_MODES; i++) pinModes[i] = []; 68 | 69 | var majorVersion = 0, 70 | minorVersion = 0; 71 | 72 | var connected = false; 73 | var notifyConnection = false; 74 | var device = null; 75 | var inputData = null; 76 | 77 | // TEMPORARY WORKAROUND 78 | // Since _deviceRemoved is not used with Serial devices 79 | // ping device regularly to check connection 80 | var pinging = false; 81 | var pingCount = 0; 82 | var pinger = null; 83 | 84 | function init() { 85 | 86 | for (var i = 0; i < 16; i++) { 87 | var output = new Uint8Array([REPORT_DIGITAL | i, 0x01]); 88 | device.send(output.buffer); 89 | } 90 | 91 | queryCapabilities(); 92 | 93 | // TEMPORARY WORKAROUND 94 | // Since _deviceRemoved is not used with Serial devices 95 | // ping device regularly to check connection 96 | pinger = setInterval(function() { 97 | if (pinging) { 98 | if (++pingCount > 6) { 99 | clearInterval(pinger); 100 | pinger = null; 101 | connected = false; 102 | if (device) device.close(); 103 | device = null; 104 | return; 105 | } 106 | } else { 107 | if (!device) { 108 | clearInterval(pinger); 109 | pinger = null; 110 | return; 111 | } 112 | queryFirmware(); 113 | pinging = true; 114 | } 115 | }, 100); 116 | } 117 | 118 | function hasCapability(pin, mode) { 119 | if (pinModes[mode].indexOf(pin) > -1) 120 | return true; 121 | else 122 | return false; 123 | } 124 | 125 | function queryFirmware() { 126 | var output = new Uint8Array([START_SYSEX, QUERY_FIRMWARE, END_SYSEX]); 127 | device.send(output.buffer); 128 | } 129 | 130 | function queryCapabilities() { 131 | console.log('Querying ' + device.id + ' capabilities'); 132 | var msg = new Uint8Array([ 133 | START_SYSEX, CAPABILITY_QUERY, END_SYSEX]); 134 | device.send(msg.buffer); 135 | } 136 | 137 | function queryAnalogMapping() { 138 | console.log('Querying ' + device.id + ' analog mapping'); 139 | var msg = new Uint8Array([ 140 | START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX]); 141 | device.send(msg.buffer); 142 | } 143 | 144 | function setDigitalInputs(portNum, portData) { 145 | digitalInputData[portNum] = portData; 146 | } 147 | 148 | function setAnalogInput(pin, val) { 149 | analogInputData[pin] = val; 150 | } 151 | 152 | function setVersion(major, minor) { 153 | majorVersion = major; 154 | minorVersion = minor; 155 | } 156 | 157 | function processSysexMessage() { 158 | switch(storedInputData[0]) { 159 | case CAPABILITY_RESPONSE: 160 | for (var i = 1, pin = 0; pin < MAX_PINS; pin++) { 161 | while (storedInputData[i++] != 0x7F) { 162 | pinModes[storedInputData[i-1]].push(pin); 163 | i++; //Skip mode resolution 164 | } 165 | if (i == sysexBytesRead) break; 166 | } 167 | queryAnalogMapping(); 168 | break; 169 | case ANALOG_MAPPING_RESPONSE: 170 | for (var pin = 0; pin < analogChannel.length; pin++) 171 | analogChannel[pin] = 127; 172 | for (var i = 1; i < sysexBytesRead; i++) 173 | analogChannel[i-1] = storedInputData[i]; 174 | for (var pin = 0; pin < analogChannel.length; pin++) { 175 | if (analogChannel[pin] != 127) { 176 | var out = new Uint8Array([ 177 | REPORT_ANALOG | analogChannel[pin], 0x01]); 178 | device.send(out.buffer); 179 | } 180 | } 181 | notifyConnection = true; 182 | setTimeout(function() { 183 | notifyConnection = false; 184 | }, 100); 185 | break; 186 | case QUERY_FIRMWARE: 187 | if (!connected) { 188 | clearInterval(poller); 189 | poller = null; 190 | clearTimeout(watchdog); 191 | watchdog = null; 192 | connected = true; 193 | setTimeout(init, 200); 194 | } 195 | pinging = false; 196 | pingCount = 0; 197 | break; 198 | } 199 | } 200 | 201 | function processInput(inputData) { 202 | for (var i=0; i < inputData.length; i++) { 203 | if (parsingSysex) { 204 | if (inputData[i] == END_SYSEX) { 205 | parsingSysex = false; 206 | processSysexMessage(); 207 | } else { 208 | storedInputData[sysexBytesRead++] = inputData[i]; 209 | } 210 | } else if (waitForData > 0 && inputData[i] < 0x80) { 211 | storedInputData[--waitForData] = inputData[i]; 212 | if (executeMultiByteCommand !== 0 && waitForData === 0) { 213 | switch(executeMultiByteCommand) { 214 | case DIGITAL_MESSAGE: 215 | setDigitalInputs(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 216 | break; 217 | case ANALOG_MESSAGE: 218 | setAnalogInput(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 219 | break; 220 | case REPORT_VERSION: 221 | setVersion(storedInputData[1], storedInputData[0]); 222 | break; 223 | } 224 | } 225 | } else { 226 | if (inputData[i] < 0xF0) { 227 | command = inputData[i] & 0xF0; 228 | multiByteChannel = inputData[i] & 0x0F; 229 | } else { 230 | command = inputData[i]; 231 | } 232 | switch(command) { 233 | case DIGITAL_MESSAGE: 234 | case ANALOG_MESSAGE: 235 | case REPORT_VERSION: 236 | waitForData = 2; 237 | executeMultiByteCommand = command; 238 | break; 239 | case START_SYSEX: 240 | parsingSysex = true; 241 | sysexBytesRead = 0; 242 | break; 243 | } 244 | } 245 | } 246 | } 247 | 248 | function pinMode(pin, mode) { 249 | var msg = new Uint8Array([PIN_MODE, pin, mode]); 250 | device.send(msg.buffer); 251 | } 252 | 253 | function analogRead(pin) { 254 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 255 | return Math.round((analogInputData[pin] * 100) / 1023); 256 | } else { 257 | var valid = []; 258 | for (var i = 0; i < pinModes[ANALOG].length; i++) 259 | valid.push(i); 260 | console.log('ERROR: valid analog pins are ' + valid.join(', ')); 261 | return; 262 | } 263 | } 264 | 265 | function digitalRead(pin) { 266 | if (!hasCapability(pin, INPUT)) { 267 | console.log('ERROR: valid input pins are ' + pinModes[INPUT].join(', ')); 268 | return; 269 | } 270 | pinMode(pin, INPUT); 271 | return (digitalInputData[pin >> 3] >> (pin & 0x07)) & 0x01; 272 | } 273 | 274 | function analogWrite(pin, val) { 275 | if (!hasCapability(pin, PWM)) { 276 | console.log('ERROR: valid PWM pins are ' + pinModes[PWM].join(', ')); 277 | return; 278 | } 279 | if (val < 0) val = 0; 280 | else if (val > 100) val = 100; 281 | val = Math.round((val / 100) * 255); 282 | pinMode(pin, PWM); 283 | var msg = new Uint8Array([ 284 | ANALOG_MESSAGE | (pin & 0x0F), 285 | val & 0x7F, 286 | val >> 7]); 287 | device.send(msg.buffer); 288 | } 289 | 290 | function digitalWrite(pin, val) { 291 | if (!hasCapability(pin, OUTPUT)) { 292 | console.log('ERROR: valid output pins are ' + pinModes[OUTPUT].join(', ')); 293 | return; 294 | } 295 | var portNum = (pin >> 3) & 0x0F; 296 | if (val == LOW) 297 | digitalOutputData[portNum] &= ~(1 << (pin & 0x07)); 298 | else 299 | digitalOutputData[portNum] |= (1 << (pin & 0x07)); 300 | pinMode(pin, OUTPUT); 301 | var msg = new Uint8Array([ 302 | DIGITAL_MESSAGE | portNum, 303 | digitalOutputData[portNum] & 0x7F, 304 | digitalOutputData[portNum] >> 0x07]); 305 | device.send(msg.buffer); 306 | } 307 | 308 | function rotateServo(pin, deg) { 309 | if (!hasCapability(pin, SERVO)) { 310 | console.log('ERROR: valid servo pins are ' + pinModes[SERVO].join(', ')); 311 | return; 312 | } 313 | pinMode(pin, SERVO); 314 | var msg = new Uint8Array([ 315 | ANALOG_MESSAGE | (pin & 0x0F), 316 | deg & 0x7F, 317 | deg >> 0x07]); 318 | device.send(msg.buffer); 319 | servoVals[pin] = deg; 320 | } 321 | 322 | ext.analogWrite = function(pin, val) { 323 | analogWrite(parseInt(pin), val); 324 | }; 325 | 326 | ext.digitalWrite = function(pin, val) { 327 | if (val == menus[lang]['outputs'][0]) 328 | digitalWrite(parseInt(pin), HIGH); 329 | else if (val == menus[lang]['outputs'][1]) 330 | digitalWrite(parseInt(pin), LOW); 331 | }; 332 | 333 | ext.analogRead = function(pin) { 334 | return analogRead(parseInt(pin)); 335 | }; 336 | 337 | ext.digitalRead = function(pin) { 338 | return digitalRead(parseInt(pin)); 339 | }; 340 | 341 | ext.whenAnalogRead = function(p, op, val) { 342 | var pin = parseInt(p); 343 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 344 | if (op == '>') 345 | return analogRead(pin) > val; 346 | else if (op == '<') 347 | return analogRead(pin) < val; 348 | else if (op == '=') 349 | return analogRead(pin) == val; 350 | else 351 | return false; 352 | } 353 | }; 354 | 355 | ext.whenDigitalRead = function(p, val) { 356 | var pin = parseInt(p); 357 | if (hasCapability(pin, INPUT)) { 358 | if (val == menus[lang]['outputs'][0]) 359 | return digitalRead(pin); 360 | else if (val == menus[lang]['outputs'][1]) 361 | return digitalRead(pin) === false; 362 | } 363 | }; 364 | 365 | ext.setServo = function(pin, deg) { 366 | if (deg < 0) deg = 0; 367 | else if (deg > 180) deg = 180; 368 | rotateServo(parseInt(pin), deg); 369 | }; 370 | 371 | ext.getServoPosition = function(pin, change) { 372 | return servoVals[parseInt(pin)]; 373 | }; 374 | 375 | ext._getStatus = function() { 376 | if (!connected) 377 | return { status:1, msg:'Disconnected' }; 378 | else 379 | return { status:2, msg:'Connected' }; 380 | }; 381 | 382 | ext._deviceRemoved = function(dev) { 383 | console.log('Device removed'); 384 | // Not currently implemented with serial devices 385 | }; 386 | 387 | var potentialDevices = []; 388 | ext._deviceConnected = function(dev) { 389 | potentialDevices.push(dev); 390 | if (!device) 391 | tryNextDevice(); 392 | }; 393 | 394 | var poller = null; 395 | var watchdog = null; 396 | function tryNextDevice() { 397 | device = potentialDevices.shift(); 398 | if (!device) return; 399 | 400 | device.open({ stopBits: 0, bitRate: 57600, ctsFlowControl: 0 }, function() { 401 | console.log('Attempting connection with ' + device.id); 402 | device.set_receive_handler(function(data) { 403 | var inputData = new Uint8Array(data); 404 | processInput(inputData); 405 | }); 406 | 407 | poller = setInterval(function() { 408 | queryFirmware(); 409 | }, 1000); 410 | 411 | watchdog = setTimeout(function() { 412 | clearInterval(poller); 413 | poller = null; 414 | device.set_receive_handler(null); 415 | device.close(); 416 | device = null; 417 | tryNextDevice(); 418 | }, 5000); 419 | }); 420 | } 421 | 422 | ext._shutdown = function() { 423 | // TODO: Bring all pins down 424 | if (device) device.close(); 425 | if (poller) clearInterval(poller); 426 | device = null; 427 | }; 428 | 429 | // Check for GET param 'lang' 430 | var paramString = window.location.search.replace(/^\?|\/$/g, ''); 431 | var vars = paramString.split("&"); 432 | var lang = 'en'; 433 | for (var i=0; i 1 && pair[0]=='lang') 436 | lang = pair[1]; 437 | } 438 | 439 | var blocks = { 440 | en: [ 441 | [' ', 'set pin %n %m.outputs', 'digitalWrite', 13, 'on'], 442 | [' ', 'set pin %n to %n%', 'analogWrite', 9, 100], 443 | ['h', 'when pin %n is %m.outputs', 'whenDigitalRead', 9, 'on'], 444 | ['b', 'pin %n on?', 'digitalRead', 9], 445 | ['-'], 446 | ['h', 'when analog pin %n %m.ops %n%', 'whenAnalogRead', 0, '>', 50], 447 | ['r', 'read analog pin %n', 'analogRead', 0], 448 | ['-'], 449 | [' ', 'set pin %n servo to %n degrees', 'setServo', 7, 180], 450 | ['r', 'pin %n servo position', 'getServoPosition', 7], 451 | ], 452 | zh: [ 453 | [' ', '設定腳位 %n %m.outputs', 'digitalWrite', 13, '開'], 454 | [' ', '設定腳位 %n 為 %n%', 'analogWrite', 9, 100], 455 | ['h', '當腳位 %n 為 %m.outputs', 'whenDigitalRead', 9, '開'], 456 | ['b', '腳位 %n 開?', 'digitalRead', 9], 457 | ['-'], 458 | ['h', '當類比 %n %m.ops %n%', 'whenAnalogRead', 0, '>', 50], 459 | ['r', '讀取類比 %n', 'analogRead', 0], 460 | ['-'], 461 | [' ', '旋轉 %n 到 %n 度', 'setServo', 7, 180], 462 | [' ', '旋轉 %n 度', 'getServoPosition', 7], 463 | ] 464 | /*de: [ 465 | ['h', 'Wenn Arduino verbunden ist', 'whenConnected'], 466 | [' ', 'Verbinde %m.hwOut mit Pin %n', 'connectHW', 'LED A', 3], 467 | [' ', 'Verbinde %m.hwIn mit Analog %n', 'connectHW', 'Drehknopf', 0], 468 | ['-'], 469 | [' ', 'Schalte %m.leds %m.outputs', 'digitalLED', 'LED A', 'Ein'], 470 | [' ', 'Setze %m.leds Helligkeit auf %n%', 'setLED', 'LED A', 100], 471 | [' ', 'Ändere %m.leds Helligkeit um %n%', 'changeLED', 'LED A', 20], 472 | ['-'], 473 | [' ', 'Drehe %m.servos auf %n Grad', 'rotateServo', 'Servo A', 180], 474 | [' ', 'Drehe %m.servos um %n Grad', 'changeServo', 'Servo A', 20], 475 | ['-'], 476 | ['h', 'Wenn %m.buttons ist %m.btnStates', 'whenButton', 'Taste A', 'gedrückt'], 477 | ['b', '%m.buttons gedrückt?', 'isButtonPressed', 'Taste A'], 478 | ['-'], 479 | ['h', 'Wenn %m.hwIn %m.ops %n%', 'whenInput', 'Drehknopf', '>', 50], 480 | ['r', 'Wert von %m.hwIn', 'readInput', 'Drehknopf'], 481 | ['-'], 482 | [' ', 'Schalte Pin %n %m.outputs', 'digitalWrite', 1, 'Ein'], 483 | [' ', 'Setze Pin %n auf %n%', 'analogWrite', 3, 100], 484 | ['-'], 485 | ['h', 'Wenn Pin %n ist %m.outputs', 'whenDigitalRead', 1, 'Ein'], 486 | ['b', 'Pin %n ein?', 'digitalRead', 1], 487 | ['-'], 488 | ['h', 'Wenn Analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 489 | ['r', 'Wert von Analog %n', 'analogRead', 0], 490 | ['-'], 491 | ['r', 'Setze %n von %n %n auf %n %n', 'mapValues', 50, 0, 100, -240, 240] 492 | ], 493 | fr: [ 494 | ['h', "Quand l'appareil est connecté", 'whenConnected'], 495 | [' ', 'Connecté %m.hwOut au pin %n', 'connectHW', 'LED A', 3], 496 | [' ', 'Connecté %m.hwIn au pin analogue %n', 'connectHW', 'Potentiomètre', 0], 497 | ['-'], 498 | [' ', 'Régler %m.leds LED %m.output Sortie', 'digitalLED', 'LED A', 'ON'], 499 | [' ', 'Régler %m.leds Luminosité de la LED à %n%', 'setLED', 'LED A', 100], 500 | [' ', 'Changer %m.leds Luminosité de la LED de %n%', 'changeLED', 'LED A', 20], 501 | ['-'], 502 | [' ', 'Tourner %m.servos Servo Moteur à %n degrés', 'rotateServo', 'Servo Moteur A', 180], 503 | [' ', 'Tourner %m.servos Servo Moteur de %n degrés', 'changeServo', 'Servo Moteur A', 20], 504 | ['-'], 505 | ['h', 'Quand %m.buttons Bouton est %m.btnStates', 'whenButton', 'Bouton A', 'Appuyé'], 506 | ['b', 'Le %m.buttons est-il pressé?', 'isButtonPressed', 'Bouton A'], 507 | ['-'], 508 | ['h', 'Quand %m.hwIn %m.ops %n%', 'whenInput', 'Potentiomètre', '>', 50], 509 | ['r', 'Lire %m.hwIn', 'readInput', 'Potentiomètre'], 510 | ['-'], 511 | [' ', 'Régler le Pin %n %m.outputs Sortie', 'digitalWrite', 1, 'ON'], 512 | [' ', 'Régler le Pin %n à %n%', 'analogWrite', 3, 100], 513 | ['-'], 514 | ['h', 'Quand le Pin %n est %m.outputs Sortie', 'whenDigitalRead', 1, 'ON'], 515 | ['b', 'Le Pin %n est-il démarré?', 'digitalRead', 1], 516 | ['-'], 517 | ['h', 'Quand le Pin analogique est %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 518 | ['r', 'Lire le Pin Analogique %n', 'analogRead', 0], 519 | ['-'], 520 | ['r', 'Mapper %n de %n %n à %n %n', 'mapValues', 50, 0, 100, -240, 240] 521 | ], 522 | it: [ 523 | ['h', 'quando Arduino è connesso', 'whenConnected'], 524 | [' ', 'connetti il %m.hwOut al pin %n', 'connectHW', 'led A', 3], 525 | [' ', 'connetti il %m.hwIn ad analog %n', 'connectHW', 'potenziometro', 0], 526 | ['-'], 527 | [' ', 'imposta %m.leds a %m.outputs', 'digitalLED', 'led A', 'acceso'], 528 | [' ', 'porta luminosità di %m.leds a %n%', 'setLED', 'led A', 100], 529 | [' ', 'cambia luminosità di %m.leds a %n%', 'changeLED', 'led A', 20], 530 | ['-'], 531 | [' ', 'ruota %m.servos fino a %n gradi', 'rotateServo', 'servo A', 180], 532 | [' ', 'ruota %m.servos di %n gradi', 'changeServo', 'servo A', 20], 533 | ['-'], 534 | ['h', 'quando tasto %m.buttons è %m.btnStates', 'whenButton', 'pulsante A', 'premuto'], 535 | ['b', '%m.buttons premuto?', 'isButtonPressed', 'pulsante A'], 536 | ['-'], 537 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenziometro', '>', 50], 538 | ['r', 'leggi %m.hwIn', 'readInput', 'potenziometro'], 539 | ['-'], 540 | [' ', 'imposta pin %n a %m.outputs', 'digitalWrite', 1, 'acceso'], 541 | [' ', 'porta pin %n al %n%', 'analogWrite', 3, 100], 542 | ['-'], 543 | ['h', 'quando pin %n è %m.outputs', 'whenDigitalRead', 1, 'acceso'], 544 | ['b', 'pin %n acceso?', 'digitalRead', 1], 545 | ['-'], 546 | ['h', 'quando analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 547 | ['r', 'leggi analog %n', 'analogRead', 0], 548 | ['-'], 549 | ['r', 'porta %n da %n %n a %n %n', 'mapValues', 50, 0, 100, -240, 240] 550 | ], 551 | ja: [ 552 | ['h', 'デバイスがつながったとき', 'whenConnected'], 553 | [' ', '%m.hwOut を %n ピンへつなぐ', 'connectHW', 'led A', 3], 554 | [' ', '%m.hwIn をアナログ入力 %n ピンへつなぐ', 'connectHW', 'rotation knob', 0], 555 | ['-'], 556 | [' ', '%m.leds を %m.outputs にする', 'digitalLED', 'led A', 'on'], 557 | [' ', '%m.leds の明るさを %n% にする', 'setLED', 'led A', 100], 558 | [' ', '%m.leds の明るさを %n% ずつ変える', 'changeLED', 'led A', 20], 559 | ['-'], 560 | [' ', '%m.servos を %n 度へ向ける', 'rotateServo', 'servo A', 180], 561 | [' ', '%m.servos を %n 度ずつ回す', 'changeServo', 'servo A', 20], 562 | ['-'], 563 | ['h', '%m.buttons が %m.btnStates とき', 'whenButton', 'ボタン A', '押された'], 564 | ['b', '%m.buttons 押された', 'isButtonPressed', 'ボタン A'], 565 | ['-'], 566 | ['h', '%m.hwIn が %m.ops %n% になったとき', 'whenInput', '回転つまみ', '>', 50], 567 | ['r', '%m.hwIn の値', 'readInput', '回転つまみ'], 568 | ['-'], 569 | [' ', 'デジタル出力 %n を %m.outputs にする', 'digitalWrite', 1, 'on'], 570 | [' ', 'アナログ出力 %n を %n% にする', 'analogWrite', 3, 100], 571 | ['-'], 572 | ['h', 'デジタル入力 %n が %m.outputs になったとき', 'whenDigitalRead', 1, 'on'], 573 | ['b', 'デジタル入力 %n はオン', 'digitalRead', 1], 574 | ['-'], 575 | ['h', 'アナログ入力 %n が %m.ops %n% になったとき', 'whenAnalogRead', 1, '>', 50], 576 | ['r', 'アナログ入力 %n の値', 'analogRead', 0], 577 | ['-'], 578 | ['r', '%n を %n ... %n から %n ... %n へ変換', 'mapValues', 50, 0, 100, -240, 240] 579 | ], 580 | ko: [ 581 | ['h', '아두이노가 연결됐을 때', 'whenConnected'], 582 | [' ', '%m.hwOut 를 %n 번 핀에 연결하기', 'connectHW', 'led A', 3], 583 | [' ', '%m.hwIn 를 아날로그 %n 번 핀에 연결하기', 'connectHW', '회전 손잡이', 0], 584 | ['-'], 585 | [' ', '%m.leds 를 %m.outputs', 'digitalLED', 'led A', '켜기'], 586 | [' ', '%m.leds 의 밝기를 %n% 로 설정하기', 'setLED', 'led A', 100], 587 | [' ', '%m.leds 의 밝기를 %n% 만큼 바꾸기', 'changeLED', 'led A', 20], 588 | ['-'], 589 | [' ', '%m.servos 를 %n 도로 회전하기', 'rotateServo', '서보모터 A', 180], 590 | [' ', '%m.servos 를 %n 도 만큼 회전하기', 'changeServo', '서보모터 A', 20], 591 | ['-'], 592 | ['h', '%m.buttons 의 상태가 %m.btnStates 일 때', 'whenButton', '버튼 A', '눌림'], 593 | ['b', '%m.buttons 가 눌려져 있는가?', 'isButtonPressed', '버튼 A'], 594 | ['-'], 595 | ['h', '%m.hwIn 의 값이 %m.ops %n% 일 때', 'whenInput', '회전 손잡이', '>', 50], 596 | ['r', '%m.hwIn 의 값', 'readInput', '회전 손잡이'], 597 | ['-'], 598 | [' ', '%n 번 핀을 %m.outputs', 'digitalWrite', 1, '켜기'], 599 | [' ', '%n 번 핀의 값을 %n% 로 설정하기', 'analogWrite', 3, 100], 600 | ['-'], 601 | ['h', '%n 번 핀의 상태가 %m.outputs 일 때', 'whenDigitalRead', 1, '켜기'], 602 | ['b', '%n 번 핀이 켜져있는가?', 'digitalRead', 1], 603 | ['-'], 604 | ['h', '아날로그 %n 번 핀의 값이 %m.ops %n% 일 때', 'whenAnalogRead', 1, '>', 50], 605 | ['r', '아날로그 %n 번 핀의 값', 'analogRead', 0], 606 | ['-'], 607 | ['r', '%n 을(를) %n ~ %n 에서 %n ~ %n 의 범위로 바꾸기', 'mapValues', 50, 0, 100, -240, 240] 608 | ], 609 | nb: [ 610 | ['h', 'når enheten tilkobles', 'whenConnected'], 611 | [' ', 'koble %m.hwOut til digital %n', 'connectHW', 'LED A', 3], 612 | [' ', 'koble %m.hwIn til analog %n', 'connectHW', 'dreieknapp', 0], 613 | ['-'], 614 | [' ', 'sett %m.leds %m.outputs', 'digitalLED', 'LED A', 'på'], 615 | [' ', 'sett %m.leds styrke til %n%', 'setLED', 'LED A', 100], 616 | [' ', 'endre %m.leds styrke med %n%', 'changeLED', 'LED A', 20], 617 | ['-'], 618 | [' ', 'rotér %m.servos til %n grader', 'rotateServo', 'servo A', 180], 619 | [' ', 'rotér %m.servos med %n grader', 'changeServo', 'servo A', 20], 620 | ['-'], 621 | ['h', 'når %m.buttons %m.btnStates', 'whenButton', 'knapp A', 'trykkes'], 622 | ['b', '%m.buttons trykket?', 'isButtonPressed', 'knapp A'], 623 | ['-'], 624 | ['h', 'når %m.hwIn %m.ops %n%', 'whenInput', 'dreieknapp', '>', 50], 625 | ['r', '%m.hwIn verdi', 'readInput', 'dreieknapp'], 626 | ['-'], 627 | [' ', 'sett digital %n %m.outputs', 'digitalWrite', 1, 'på'], 628 | [' ', 'set utgang %n til %n%', 'analogWrite', 3, 100], 629 | ['-'], 630 | ['h', 'når digital %n er %m.outputs', 'whenDigitalRead', 1, 'på'], 631 | ['b', 'digital %n på?', 'digitalRead', 1], 632 | ['-'], 633 | ['h', 'når analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 634 | ['r', 'analog %n verdi', 'analogRead', 0], 635 | ['-'], 636 | ['r', 'skalér %n fra %n %n til %n %n', 'mapValues', 50, 0, 100, -240, 240] 637 | ], 638 | nl: [ 639 | ['h', 'als het apparaat verbonden is', 'whenConnected'], 640 | [' ', 'verbind %m.hwOut met pin %n', 'connectHW', 'led A', 3], 641 | [' ', 'verbind %m.hwIn met analoog %n', 'connectHW', 'draaiknop', 0], 642 | ['-'], 643 | [' ', 'schakel %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 644 | [' ', 'schakel %m.leds helderheid tot %n%', 'setLED', 'led A', 100], 645 | [' ', 'verander %m.leds helderheid met %n%', 'changeLED', 'led A', 20], 646 | ['-'], 647 | [' ', 'draai %m.servos tot %n graden', 'rotateServo', 'servo A', 180], 648 | [' ', 'draai %m.servos met %n graden', 'changeServo', 'servo A', 20], 649 | ['-'], 650 | ['h', 'wanneer %m.buttons is %m.btnStates', 'whenButton', 'knop A', 'in gedrukt'], 651 | ['b', '%m.buttons ingedrukt?', 'isButtonPressed', 'knop A'], 652 | ['-'], 653 | ['h', 'wanneer%m.hwIn %m.ops %n%', 'whenInput', 'draaiknop', '>', 50], 654 | ['r', 'read %m.hwIn', 'readInput', 'draaiknop'], 655 | ['-'], 656 | [' ', 'schakel pin %n %m.outputs', 'digitalWrite', 1, 'on'], 657 | [' ', 'schakel pin %n tot %n%', 'analogWrite', 3, 100], 658 | ['-'], 659 | ['h', 'wanneer pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 660 | ['b', 'pin %n aan?', 'digitalRead', 1], 661 | ['-'], 662 | ['h', 'wanneer analoge %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 663 | ['r', 'lees analoge %n', 'analogRead', 0], 664 | ['-'], 665 | ['r', 'zet %n van %n %n tot %n %n', 'mapValues', 50, 0, 100, -240, 240] 666 | ], 667 | pl: [ 668 | ['h', 'kiedy urządzenie jest podłączone', 'whenConnected'], 669 | [' ', 'podłącz %m.hwOut do pinu %n', 'connectHW', 'led A', 3], 670 | [' ', 'podłącz %m.hwIn do we analogowego %n', 'connectHW', 'pokrętło', 0], 671 | ['-'], 672 | [' ', 'ustaw %m.leds na %m.outputs', 'digitalLED', 'led A', 'włączony'], 673 | [' ', 'ustaw jasność %m.leds na %n%', 'setLED', 'led A', 100], 674 | [' ', 'zmień jasność %m.leds o %n%', 'changeLED', 'led A', 20], 675 | ['-'], 676 | [' ', 'obróć %m.servos w położenie %n degrees', 'rotateServo', 'serwo A', 180], 677 | [' ', 'obróć %m.servos o %n degrees', 'changeServo', 'serwo A', 20], 678 | ['-'], 679 | ['h', 'kiedy %m.buttons jest %m.btnStates', 'whenButton', 'przycisk A', 'wciśnięty'], 680 | ['b', 'czy %m.buttons jest wciśnięty?', 'isButtonPressed', 'przycisk A'], 681 | ['-'], 682 | ['h', 'kiedy %m.hwIn jest w położeniu %m.ops %n%', 'whenInput', 'pokrętło', '>', 50], 683 | ['r', 'odczytaj ustawienie %m.hwIn', 'readInput', 'pokrętła'], 684 | ['-'], 685 | [' ', 'ustaw pin %n jako %m.outputs', 'digitalWrite', 1, 'włączony'], 686 | [' ', 'ustaw pin %n na %n%', 'analogWrite', 3, 100], 687 | ['-'], 688 | ['h', 'kiedy pin %n jest %m.outputs', 'whenDigitalRead', 1, 'włączony'], 689 | ['b', 'czy pin %n jest włączony?', 'digitalRead', 1], 690 | ['-'], 691 | ['h', 'kiedy we analogowe %n jest w położeniu %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 692 | ['r', 'odczytaj we analogowe %n', 'analogRead', 0], 693 | ['-'], 694 | ['r', 'przekształć wartość %n z zakresu %n %n na %n %n', 'mapValues', 50, 0, 100, -240, 240] 695 | ], 696 | pt: [ 697 | ['h', 'Quando dispositivo estiver conectado', 'whenConnected'], 698 | [' ', 'conectar%m.hwOut para pino %n', 'connectHW', 'led A', 3], 699 | [' ', 'conectar %m.hwIn para analogico %n', 'connectHW', 'potenciometro', 0], 700 | ['-'], 701 | [' ', 'estado %m.leds %m.outputs', 'digitalLED', 'led A', 'ligado'], 702 | [' ', 'estado %m.leds brilho to %n%', 'setLED', 'led A', 100], 703 | [' ', 'mudar %m.leds brilho em %n%', 'changeLED', 'led A', 20], 704 | ['-'], 705 | [' ', 'girar %m.servos para %n graus', 'rotateServo', 'servo A', 180], 706 | [' ', 'girar %m.servos em %n graus', 'changeServo', 'servo A', 20], 707 | ['-'], 708 | ['h', 'quando %m.buttons is %m.btnStates', 'whenButton', 'botao A', 'pressionado'], 709 | ['b', '%m.buttons pressionado?', 'isButtonPressed', 'botao A'], 710 | ['-'], 711 | ['h', 'quando %m.hwIn %m.ops %n%', 'whenInput', 'potenciometro', '>', 50], 712 | ['r', 'read %m.hwIn', 'readInput', 'potenciometro'], 713 | ['-'], 714 | [' ', 'estado digital pino %n %m.outputs', 'digitalWrite', 1, 'ligado'], 715 | [' ', 'estado analogico pino %n to %n%', 'analogWrite', 3, 100], 716 | ['-'], 717 | ['h', 'quando pino %n is %m.outputs', 'whenDigitalRead', 1, 'ligado'], 718 | ['b', 'pino %n ligado?', 'digitalRead', 1], 719 | ['-'], 720 | ['h', 'quando valor analogico %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 721 | ['r', 'ler valor analogico %n', 'analogRead', 0], 722 | ['-'], 723 | ['r', 'mapear %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 724 | ], 725 | ru: [ 726 | ['h', 'когда устройство подключено', 'whenConnected'], 727 | [' ', 'подключить %m.hwOut к выводу %n', 'connectHW', 'светодиод A', 3], 728 | [' ', 'подключить %m.hwIn к ан. входу %n', 'connectHW', 'потенциометр', 0], 729 | ['-'], 730 | [' ', 'установить %m.leds в %m.outputs', 'digitalLED', 'светодиод A', 'включен'], 731 | [' ', 'установить яркость %m.leds в %n%', 'setLED', 'светодиод A', 100], 732 | [' ', 'изменить яркость %m.leds на %n%', 'changeLED', 'светодиод A', 20], 733 | ['-'], 734 | [' ', 'установить %m.servos в позицию %n °', 'rotateServo', 'серво A', 180], 735 | [' ', 'повернуть %m.servos на %n °', 'changeServo', 'серво A', 20], 736 | ['-'], 737 | ['h', 'когда %m.buttons %m.btnStates', 'whenButton', 'кнопка A', 'нажата'], 738 | ['b', '%m.buttons нажата?', 'isButtonPressed', 'кнопка A'], 739 | ['-'], 740 | ['h', 'когда %m.hwIn %m.ops %n%', 'whenInput', 'потенциометр', '>', 50], 741 | ['r', 'значение %m.hwIn', 'readInput', 'потенциометр'], 742 | ['-'], 743 | [' ', 'установить выход %n в %m.outputs', 'digitalWrite', 1, 'включен'], 744 | [' ', 'установить ан. выход %n в %n%', 'analogWrite', 3, 100], 745 | ['-'], 746 | ['h', 'когда вход %n %m.outputs', 'whenDigitalRead', 1, 'включен'], 747 | ['b', 'вход %n вкл?', 'digitalRead', 1], 748 | ['-'], 749 | ['h', 'когда ан. вход %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 750 | ['r', 'значение ан. входа %n', 'analogRead', 0], 751 | ['-'], 752 | ['r', 'отобразить %n из %n %n в %n %n', 'mapValues', 50, 0, 100, -240, 240] 753 | ], 754 | el: [ 755 | ['h', 'Όταν η συσκευή είναι συνδεδεμένη', 'whenConnected'], 756 | [' ', 'σύνδεσε το %m.hwOut στο pin %n', 'connectHW', 'led A', 3], 757 | [' ', 'σύνδεσε το %m.hwIn στο αναλογικό %n', 'connectHW', 'ποντεσιόμετρο', 0], 758 | ['-'], 759 | [' ', 'άλλαξε το %m.leds σε %m.outputs', 'digitalLED', 'led A', 'ενεργοποιημένο'], 760 | [' ', 'όρισε στο %m.leds τη φωτεινότητα ίση με %n%', 'setLED', 'led A', 100], 761 | [' ', 'άλλαξε στο %m.leds τη φωτεινότητα κατά %n%', 'changeLED', 'led A', 20], 762 | ['-'], 763 | [' ', 'στρίψε το %m.servos στις %n μοίρες', 'rotateServo', 'servo A', 180], 764 | [' ', 'στρίψε το %m.servos κατά %n μοίρες', 'changeServo', 'servo A', 20], 765 | ['-'], 766 | ['h', 'Όταν το %m.buttons είναι %m.btnStates', 'whenButton', 'κουμπί A', 'πατημένο'], 767 | ['b', 'το %m.buttons πατήθηκε;', 'isButtonPressed', 'κουμπί A'], 768 | ['-'], 769 | ['h', 'Όταν το %m.hwIn %m.ops %n%', 'whenInput', 'ποντεσιόμετρο', '>', 50], 770 | ['r', 'διάβασε %m.hwIn', 'readInput', 'ποντεσιόμετρο'], 771 | ['-'], 772 | [' ', 'άλλαξε το pin %n σε %m.outputs', 'digitalWrite', 1, 'ενεργοποιημένο'], 773 | [' ', 'όρισε το pin %n σε %n%', 'analogWrite', 3, 100], 774 | ['-'], 775 | ['h', 'Όταν το pin %n είναι %m.outputs', 'whenDigitalRead', 1, 'ενεργοποιημένο'], 776 | ['b', 'το pin %n είναι ενεργοποιημένο;', 'digitalRead', 1], 777 | ['-'], 778 | ['h', 'Όταν το αναλογικό %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 779 | ['r', 'διάβασε το αναλογικό %n', 'analogRead', 0], 780 | ['-'], 781 | ['r', 'συσχέτισε %n από %n %n έως %n %n', 'mapValues', 50, 0, 100, -240, 240] 782 | ], 783 | es: [ 784 | ['h', 'al conectar el dispositivo', 'whenConnected'], 785 | [' ', 'conectar %m.hwOut al pin %n', 'connectHW', 'led A', 3], 786 | [' ', 'conectar %m.hwIn al pin analógico %n', 'connectHW', 'potenciómetro', 0], 787 | ['-'], 788 | [' ', 'fijar estado de %m.leds a %m.outputs', 'digitalLED', 'led A', 'on'], 789 | [' ', 'fijar brillo de %m.leds a %n%', 'setLED', 'led A', 100], 790 | [' ', 'cambiar brillo de %m.leds por %n%', 'changeLED', 'led A', 20], 791 | ['-'], 792 | [' ', 'apuntar %m.servos en dirección %n grados', 'rotateServo', 'servo A', 180], 793 | [' ', 'girar %m.servos %n grados', 'changeServo', 'servo A', 20], 794 | ['-'], 795 | ['h', 'cuando el %m.buttons esté %m.btnStates', 'whenButton', 'botón A', 'presionado'], 796 | ['b', '¿%m.buttons presionado?', 'isButtonPressed', 'botón A'], 797 | ['-'], 798 | ['h', 'cuando %m.hwIn %m.ops %n%', 'whenInput', 'potenciómetro', '>', 50], 799 | ['r', 'leer %m.hwIn', 'readInput', 'potenciómetro'], 800 | ['-'], 801 | [' ', 'fijar estado de pin %n a %m.outputs', 'digitalWrite', 1, 'on'], 802 | [' ', 'fijar pin analógico %n al %n%', 'analogWrite', 3, 100], 803 | ['-'], 804 | ['h', 'cuando el pin %n esté %m.outputs', 'whenDigitalRead', 1, 'on'], 805 | ['b', '¿pin %n on?', 'digitalRead', 1], 806 | ['-'], 807 | ['h', 'cuando pin analógico %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 808 | ['r', 'leer analógico %n', 'analogRead', 0], 809 | ['-'], 810 | ['r', 'convertir %n de %n %n a %n %n', 'mapValues', 50, 0, 100, -240, 240] 811 | ]*/ 812 | }; 813 | 814 | var menus = { 815 | en: { 816 | outputs: ['on', 'off'], 817 | ops: ['>', '=', '<'] 818 | }, 819 | zh: { 820 | outputs: ['開', '關'], 821 | ops: ['>', '=', '<'] 822 | }, 823 | /*de: { 824 | buttons: ['Taste A', 'Taste B', 'Taste C', 'Taste D'], 825 | btnStates: ['gedrückt', 'losgelassen'], 826 | hwIn: ['Drehknopf', 'Lichtsensor', 'Temperatursensor'], 827 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Taste A', 'Taste B', 'Taste C', 'Taste D', 'Servo A', 'Servo B', 'Servo C', 'Servo D'], 828 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 829 | outputs: ['Ein', 'Aus'], 830 | ops: ['>', '=', '<'], 831 | servos: ['Servo A', 'Servo B', 'Servo C', 'Servo D'] 832 | }, 833 | fr: { 834 | buttons: ['Bouton A', 'Bouton B', 'Bouton C', 'Bouton D'], 835 | btnStates: ['Appuyé', 'Relâché'], 836 | hwIn: ['Potentiomètre', 'Capteur de Lumière', 'Capteur de Temperature'], 837 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Bouton A', 'Bouton B', 'Bouton C', 'Bouton D', 'Servo Moteur A', 'Servo Moteur B', 'Servo Moteur C', 'Servo Moteur D'], 838 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 839 | outputs: ['ON', 'OFF'], 840 | ops: ['>', '=', '<'], 841 | servos: ['Servo Moteur A', 'Servo Moteur B', 'Servo Moteur C', 'Servo Moteur D'] 842 | }, 843 | it: { 844 | buttons: ['pulsante A', 'pulsante B', 'pulsante C', 'pulsante D'], 845 | btnStates: ['premuto', 'rilasciato'], 846 | hwIn: ['potenziometro', 'sensore di luce', 'sensore di temperatura'], 847 | hwOut: ['led A', 'led B', 'led C', 'led D', 'pulsante A', 'pulsante B', 'pulsante C', 'pulsante D', 'servo A', 'servo B', 'servo C', 'servo D'], 848 | leds: ['led A', 'led B', 'led C', 'led D'], 849 | outputs: ['acceso', 'spento'], 850 | ops: ['>', '=', '<'], 851 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 852 | }, 853 | ja: { 854 | buttons: ['ボタン A', 'ボタン B', 'ボタン C', 'ボタン D'], 855 | btnStates: ['押された', '放された'], 856 | hwIn: ['回転つまみ', '光センサー', '温度センサー'], 857 | hwOut: ['led A', 'led B', 'led C', 'led D', 'ボタン A', 'ボタン B', 'ボタン C', 'ボタン D', 'サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'], 858 | leds: ['led A', 'led B', 'led C', 'led D'], 859 | outputs: ['オン', 'オフ'], 860 | ops: ['>', '=', '<'], 861 | servos: ['サーボ A', 'サーボ B', 'サーボ C', 'サーボ D'] 862 | }, 863 | ko: { 864 | buttons: ['버튼 A', '버튼 B', '버튼 C', '버튼 D'], 865 | btnStates: ['눌림', '떼짐'], 866 | hwIn: ['회전 손잡이', '조도 센서', '온도 센서'], 867 | hwOut: ['led A', 'led B', 'led C', 'led D', '버튼 A', '버튼 B', '버튼 C', '버튼 D', '서보모터 A', '서보모터 B', '서보모터 C', '서보모터 D'], 868 | leds: ['led A', 'led B', 'led C', 'led D'], 869 | outputs: ['켜기', '끄기'], 870 | ops: ['>', '=', '<'], 871 | servos: ['서보모터 A', '서보모터 B', '서보모터 C', '서보모터 D'] 872 | }, 873 | nb: { 874 | buttons: ['knapp A', 'knapp B', 'knapp C', 'knapp D'], 875 | btnStates: ['trykkes', 'slippes'], 876 | hwIn: ['dreieknapp', 'lyssensor', 'temperatursensor'], 877 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'knapp A', 'knapp B', 'knapp C', 'knapp D', 'servo A', 'servo B', 'servo C', 'servo D'], 878 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 879 | outputs: ['på', 'av'], 880 | ops: ['>', '=', '<'], 881 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 882 | }, 883 | nl: { 884 | buttons: ['knop A', 'knop B', 'knop C', 'knop D'], 885 | btnStates: ['ingedrukt', 'losgelaten'], 886 | hwIn: ['draaiknop', 'licht sensor', 'temperatuur sensor'], 887 | hwOut: ['led A', 'led B', 'led C', 'led D', 'knop A', 'knop B', 'knop C', 'knop D', 'servo A', 'servo B', 'servo C', 'servo D'], 888 | leds: ['led A', 'led B', 'led C', 'led D'], 889 | outputs: ['aan', 'uit'], 890 | ops: ['>', '=', '<'], 891 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 892 | }, 893 | pl: { 894 | buttons: ['przycisk A', 'przycisk B', 'przycisk C', 'przycisk D'], 895 | btnStates: ['wciśnięty', 'zwolniony'], 896 | hwIn: ['pokrętło', 'czujnik światła', 'czujnik temperatury'], 897 | hwOut: ['led A', 'led B', 'led C', 'led D', 'przycisk A', 'przycisk B', 'przycisk C', 'przycisk D', 'serwo A', 'serwo B', 'serwo C', 'serwo D'], 898 | leds: ['led A', 'led B', 'led C', 'led D'], 899 | outputs: ['włączony', 'wyłączony'], 900 | ops: ['>', '=', '<'], 901 | servos: ['serwo A', 'serwo B', 'serwo C', 'serwo D'] 902 | }, 903 | pt: { 904 | buttons: ['botao A', 'botao B', 'botao C', 'botao D'], 905 | btnStates: ['pressionado', 'solto'], 906 | hwIn: ['potenciometro', 'sensor de luz', 'sensor de temperatura'], 907 | hwOut: ['led A', 'led B', 'led C', 'led D', 'botao A', 'botao B', 'botao C', 'botao D', 'servo A', 'servo B', 'servo C', 'servo D'], 908 | leds: ['led A', 'led B', 'led C', 'led D'], 909 | outputs: ['ligado', 'desligado'], 910 | ops: ['>', '=', '<'], 911 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 912 | }, 913 | ru: { 914 | buttons: ['кнопка A', 'кнопка B', 'кнопка C', 'кнопка D'], 915 | btnStates: ['нажата', 'отпущена'], 916 | hwIn: ['потенциометр', 'датчик света', 'датчик температуры'], 917 | hwOut: ['светодиод A', 'светодиод B', 'светодиод C', 'светодиод D', 'кнопка A', 'кнопка B', 'кнопка C', 'кнопка D', 'серво A', 'серво B', 'серво C', 'серво D'], 918 | leds: ['светодиод A', 'светодиод B', 'светодиод C', 'светодиод D'], 919 | outputs: ['включен', 'выключен'], 920 | ops: ['>', '=', '<'], 921 | servos: ['серво A', 'серво B', 'серво C', 'серво D'] 922 | }, 923 | el: { 924 | buttons: ['κουμπί A', 'κουμπί B', 'κουμπί C', 'κουμπί D'], 925 | btnStates: ['πατημένο', 'ελεύθερο'], 926 | hwIn: ['ποντεσιόμετρο', 'φωτοαισθητήρα', 'θερμοαισθητήρα'], 927 | hwOut: ['led A', 'led B', 'led C', 'led D', 'κουμπί A', 'κουμπί B', 'κουμπί C', 'κουμπί D', 'servo A', 'servo B', 'servo C', 'servo D'], 928 | leds: ['led A', 'led B', 'led C', 'led D'], 929 | outputs: ['ενεργοποιημένο', 'απενεργοποιημένο'], 930 | ops: ['>', '=', '<'], 931 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 932 | }, 933 | es: { 934 | buttons: ['botón A', 'botón B', 'botón C', 'botón D'], 935 | btnStates: ['pulsado', 'liberado'], 936 | hwIn: ['potenciómetro', 'sensor de luz', 'sensor de temperatura'], 937 | hwOut: ['led A', 'led B', 'led C', 'led D', 'botón A', 'botón B', 'botón C', 'botón D', 'servo A', 'servo B', 'servo C', 'servo D'], 938 | leds: ['led A', 'led B', 'led C', 'led D'], 939 | outputs: ['on', 'off'], 940 | ops: ['>', '=', '<'], 941 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 942 | }, 943 | */ 944 | }; 945 | 946 | var descriptor = { 947 | blocks: blocks[lang], 948 | menus: menus[lang], 949 | url: 'http://khanning.github.io/scratch-arduino-extension' 950 | }; 951 | 952 | ScratchExtensions.register('Arduino', descriptor, ext, {type:'serial'}); 953 | 954 | })({}); 955 | -------------------------------------------------------------------------------- /arduino_extension_tone.js: -------------------------------------------------------------------------------- 1 | /* 2 | *This program is free software: you can redistribute it and/or modify 3 | *it under the terms of the GNU General Public License as published by 4 | *the Free Software Foundation, either version 3 of the License, or 5 | *(at your option) any later version. 6 | * 7 | *This program is distributed in the hope that it will be useful, 8 | *but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | *GNU General Public License for more details. 11 | * 12 | *You should have received a copy of the GNU General Public License 13 | *along with this program. If not, see . 14 | */ 15 | 16 | (function(ext) { 17 | 18 | var PIN_MODE = 0xF4, 19 | REPORT_DIGITAL = 0xD0, 20 | REPORT_ANALOG = 0xC0, 21 | DIGITAL_MESSAGE = 0x90, 22 | START_SYSEX = 0xF0, 23 | END_SYSEX = 0xF7, 24 | QUERY_FIRMWARE = 0x79, 25 | REPORT_VERSION = 0xF9, 26 | ANALOG_MESSAGE = 0xE0, 27 | ANALOG_MAPPING_QUERY = 0x69, 28 | ANALOG_MAPPING_RESPONSE = 0x6A, 29 | CAPABILITY_QUERY = 0x6B, 30 | CAPABILITY_RESPONSE = 0x6C; 31 | 32 | var INPUT = 0x00, 33 | OUTPUT = 0x01, 34 | ANALOG = 0x02, 35 | PWM = 0x03, 36 | SERVO = 0x04, 37 | SHIFT = 0x05, 38 | I2C = 0x06, 39 | TONE = 0x0A; 40 | 41 | var TOTAL_PIN_MODES = 11; 42 | 43 | var LOW = 0, 44 | HIGH = 1; 45 | 46 | var TONE_TONE = 0, 47 | TONE_NO_TONE = 1; 48 | 49 | var MAX_DATA_BYTES = 4096; 50 | var MAX_PINS = 128; 51 | 52 | var parsingSysex = false, 53 | waitForData = 0, 54 | executeMultiByteCommand = 0, 55 | multiByteChannel = 0, 56 | sysexBytesRead = 0, 57 | storedInputData = new Uint8Array(MAX_DATA_BYTES); 58 | 59 | var digitalOutputData = new Uint8Array(16), 60 | digitalInputData = new Uint8Array(16), 61 | analogInputData = new Uint16Array(16); 62 | 63 | var analogChannel = new Uint8Array(MAX_PINS); 64 | var pinModes = []; 65 | for (var i = 0; i < TOTAL_PIN_MODES; i++) pinModes[i] = []; 66 | 67 | var majorVersion = 0, 68 | minorVersion = 0; 69 | 70 | var connected = false; 71 | var notifyConnection = false; 72 | var device = null; 73 | var inputData = null; 74 | 75 | // TEMPORARY WORKAROUND 76 | // Since _deviceRemoved is not used with Serial devices 77 | // ping device regularly to check connection 78 | var pinging = false; 79 | var pingCount = 0; 80 | var pinger = null; 81 | 82 | var hwList = new HWList(); 83 | 84 | function HWList() { 85 | this.devices = []; 86 | 87 | this.add = function(dev, pin) { 88 | var device = this.search(dev); 89 | if (!device) { 90 | device = {name: dev, pin: pin, val: 0}; 91 | this.devices.push(device); 92 | } else { 93 | device.pin = pin; 94 | device.val = 0; 95 | } 96 | }; 97 | 98 | this.search = function(dev) { 99 | for (var i=0; i 6) { 122 | clearInterval(pinger); 123 | pinger = null; 124 | connected = false; 125 | if (device) device.close(); 126 | device = null; 127 | return; 128 | } 129 | } else { 130 | if (!device) { 131 | clearInterval(pinger); 132 | pinger = null; 133 | return; 134 | } 135 | queryFirmware(); 136 | pinging = true; 137 | } 138 | }, 100); 139 | } 140 | 141 | function hasCapability(pin, mode) { 142 | if (pinModes[mode].indexOf(pin) > -1) 143 | return true; 144 | else 145 | return false; 146 | } 147 | 148 | function queryFirmware() { 149 | var output = new Uint8Array([START_SYSEX, QUERY_FIRMWARE, END_SYSEX]); 150 | device.send(output.buffer); 151 | } 152 | 153 | function queryCapabilities() { 154 | console.log('Querying ' + device.id + ' capabilities'); 155 | var msg = new Uint8Array([ 156 | START_SYSEX, CAPABILITY_QUERY, END_SYSEX]); 157 | device.send(msg.buffer); 158 | } 159 | 160 | function queryAnalogMapping() { 161 | console.log('Querying ' + device.id + ' analog mapping'); 162 | var msg = new Uint8Array([ 163 | START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX]); 164 | device.send(msg.buffer); 165 | } 166 | 167 | function setDigitalInputs(portNum, portData) { 168 | digitalInputData[portNum] = portData; 169 | } 170 | 171 | function setAnalogInput(pin, val) { 172 | analogInputData[pin] = val; 173 | } 174 | 175 | function setVersion(major, minor) { 176 | majorVersion = major; 177 | minorVersion = minor; 178 | } 179 | 180 | function processSysexMessage() { 181 | switch(storedInputData[0]) { 182 | case CAPABILITY_RESPONSE: 183 | for (var i = 1, pin = 0; pin < MAX_PINS; pin++) { 184 | while (storedInputData[i++] != 0x7F) { 185 | if (storedInputData[i-1] < TOTAL_PIN_MODES) { 186 | pinModes[storedInputData[i-1]].push(pin); 187 | } else { 188 | console.log('Ignoring pin mode ' + storedInputData[i-1] + ' for pin ' + pin); 189 | } 190 | i++; //Skip mode resolution 191 | } 192 | if (i == sysexBytesRead) break; 193 | } 194 | queryAnalogMapping(); 195 | break; 196 | case ANALOG_MAPPING_RESPONSE: 197 | for (var pin = 0; pin < analogChannel.length; pin++) 198 | analogChannel[pin] = 127; 199 | for (var i = 1; i < sysexBytesRead; i++) 200 | analogChannel[i-1] = storedInputData[i]; 201 | for (var pin = 0; pin < analogChannel.length; pin++) { 202 | if (analogChannel[pin] != 127) { 203 | var out = new Uint8Array([ 204 | REPORT_ANALOG | analogChannel[pin], 0x01]); 205 | device.send(out.buffer); 206 | } 207 | } 208 | notifyConnection = true; 209 | setTimeout(function() { 210 | notifyConnection = false; 211 | }, 100); 212 | break; 213 | case QUERY_FIRMWARE: 214 | if (!connected) { 215 | clearInterval(poller); 216 | poller = null; 217 | clearTimeout(watchdog); 218 | watchdog = null; 219 | connected = true; 220 | setTimeout(init, 200); 221 | } 222 | pinging = false; 223 | pingCount = 0; 224 | break; 225 | } 226 | } 227 | 228 | function processInput(inputData) { 229 | for (var i=0; i < inputData.length; i++) { 230 | 231 | if (parsingSysex) { 232 | if (inputData[i] == END_SYSEX) { 233 | parsingSysex = false; 234 | processSysexMessage(); 235 | } else { 236 | storedInputData[sysexBytesRead++] = inputData[i]; 237 | } 238 | } else if (waitForData > 0 && inputData[i] < 0x80) { 239 | storedInputData[--waitForData] = inputData[i]; 240 | if (executeMultiByteCommand !== 0 && waitForData === 0) { 241 | switch(executeMultiByteCommand) { 242 | case DIGITAL_MESSAGE: 243 | setDigitalInputs(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 244 | break; 245 | case ANALOG_MESSAGE: 246 | setAnalogInput(multiByteChannel, (storedInputData[0] << 7) + storedInputData[1]); 247 | break; 248 | case REPORT_VERSION: 249 | setVersion(storedInputData[1], storedInputData[0]); 250 | break; 251 | } 252 | } 253 | } else { 254 | if (inputData[i] < 0xF0) { 255 | command = inputData[i] & 0xF0; 256 | multiByteChannel = inputData[i] & 0x0F; 257 | } else { 258 | command = inputData[i]; 259 | } 260 | switch(command) { 261 | case DIGITAL_MESSAGE: 262 | case ANALOG_MESSAGE: 263 | case REPORT_VERSION: 264 | waitForData = 2; 265 | executeMultiByteCommand = command; 266 | break; 267 | case START_SYSEX: 268 | parsingSysex = true; 269 | sysexBytesRead = 0; 270 | break; 271 | } 272 | } 273 | } 274 | } 275 | 276 | function pinMode(pin, mode) { 277 | var msg = new Uint8Array([PIN_MODE, pin, mode]); 278 | device.send(msg.buffer); 279 | } 280 | 281 | function analogRead(pin) { 282 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 283 | return Math.round((analogInputData[pin] * 100) / 1023); 284 | } else { 285 | var valid = []; 286 | for (var i = 0; i < pinModes[ANALOG].length; i++) 287 | valid.push(i); 288 | console.log('ERROR: valid analog pins are ' + valid.join(', ')); 289 | return; 290 | } 291 | } 292 | 293 | function digitalRead(pin) { 294 | if (!hasCapability(pin, INPUT)) { 295 | console.log('ERROR: valid input pins are ' + pinModes[INPUT].join(', ')); 296 | return; 297 | } 298 | pinMode(pin, INPUT); 299 | return (digitalInputData[pin >> 3] >> (pin & 0x07)) & 0x01; 300 | } 301 | 302 | function analogWrite(pin, val) { 303 | if (!hasCapability(pin, PWM)) { 304 | console.log('ERROR: valid PWM pins are ' + pinModes[PWM].join(', ')); 305 | return; 306 | } 307 | if (val < 0) val = 0; 308 | else if (val > 100) val = 100; 309 | val = Math.round((val / 100) * 255); 310 | pinMode(pin, PWM); 311 | var msg = new Uint8Array([ 312 | ANALOG_MESSAGE | (pin & 0x0F), 313 | val & 0x7F, 314 | val >> 7]); 315 | device.send(msg.buffer); 316 | } 317 | 318 | function digitalWrite(pin, val) { 319 | if (!hasCapability(pin, OUTPUT)) { 320 | console.log('ERROR: valid output pins are ' + pinModes[OUTPUT].join(', ')); 321 | return; 322 | } 323 | var portNum = (pin >> 3) & 0x0F; 324 | if (val == LOW) 325 | digitalOutputData[portNum] &= ~(1 << (pin & 0x07)); 326 | else 327 | digitalOutputData[portNum] |= (1 << (pin & 0x07)); 328 | pinMode(pin, OUTPUT); 329 | var msg = new Uint8Array([ 330 | DIGITAL_MESSAGE | portNum, 331 | digitalOutputData[portNum] & 0x7F, 332 | digitalOutputData[portNum] >> 0x07]); 333 | device.send(msg.buffer); 334 | } 335 | 336 | function rotateServo(pin, deg) { 337 | if (!hasCapability(pin, SERVO)) { 338 | console.log('ERROR: valid servo pins are ' + pinModes[SERVO].join(', ')); 339 | return; 340 | } 341 | pinMode(pin, SERVO); 342 | var msg = new Uint8Array([ 343 | ANALOG_MESSAGE | (pin & 0x0F), 344 | deg & 0x7F, 345 | deg >> 0x07]); 346 | device.send(msg.buffer); 347 | } 348 | 349 | function tone(pin, freq, duration) { 350 | if (!hasCapability(pin, TONE)) { 351 | console.log('ERROR: valid tone pins are ' + pinModes[TONE].join(', ')); 352 | return; 353 | } 354 | var msg = new Uint8Array([ 355 | START_SYSEX, 356 | 0x5F, 357 | pin, 358 | TONE_TONE, 359 | freq & 0x7F, 360 | freq >> 7, 361 | duration & 0x7f, 362 | duration >> 7, 363 | END_SYSEX]); 364 | device.send(msg.buffer); 365 | } 366 | 367 | function noTone(pin) { 368 | if (!hasCapability(pin, TONE)) { 369 | console.log('ERROR: valid tone pins are ' + pinModes[TONE].join(', ')); 370 | return; 371 | } 372 | var msg = new Uint8Array([ 373 | START_SYSEX, 374 | 0x5F, 375 | pin, 376 | TONE_NO_TONE, 377 | END_SYSEX]); 378 | device.send(msg.buffer); 379 | } 380 | 381 | ext.whenConnected = function() { 382 | if (notifyConnection) return true; 383 | return false; 384 | }; 385 | 386 | ext.analogWrite = function(pin, val) { 387 | analogWrite(pin, val); 388 | }; 389 | 390 | ext.digitalWrite = function(pin, val) { 391 | if (val == 'on') 392 | digitalWrite(pin, HIGH); 393 | else if (val == 'off') 394 | digitalWrite(pin, LOW); 395 | }; 396 | 397 | ext.analogRead = function(pin) { 398 | return analogRead(pin); 399 | }; 400 | 401 | ext.digitalRead = function(pin) { 402 | return digitalRead(pin); 403 | }; 404 | 405 | ext.whenAnalogRead = function(pin, op, val) { 406 | if (pin >= 0 && pin < pinModes[ANALOG].length) { 407 | if (op == '>') 408 | return analogRead(pin) > val; 409 | else if (op == '<') 410 | return analogRead(pin) < val; 411 | else if (op == '=') 412 | return analogRead(pin) == val; 413 | else 414 | return false; 415 | } 416 | }; 417 | 418 | ext.whenDigitalRead = function(pin, val) { 419 | if (hasCapability(pin, INPUT)) { 420 | if (val == 'on') 421 | return digitalRead(pin); 422 | else if (val == 'off') 423 | return digitalRead(pin) === false; 424 | } 425 | }; 426 | 427 | ext.connectHW = function(hw, pin) { 428 | hwList.add(hw, pin); 429 | }; 430 | 431 | ext.rotateServo = function(servo, deg) { 432 | var hw = hwList.search(servo); 433 | if (!hw) return; 434 | if (deg < 0) deg = 0; 435 | else if (deg > 180) deg = 180; 436 | rotateServo(hw.pin, deg); 437 | hw.val = deg; 438 | }; 439 | 440 | ext.changeServo = function(servo, change) { 441 | var hw = hwList.search(servo); 442 | if (!hw) return; 443 | var deg = hw.val + change; 444 | if (deg < 0) deg = 0; 445 | else if (deg > 180) deg = 180; 446 | rotateServo(hw.pin, deg); 447 | hw.val = deg; 448 | }; 449 | 450 | ext.tone = function(pin, freq, duration) { 451 | tone(pin, freq, duration); 452 | }; 453 | 454 | ext.noTone = function(pin) { 455 | noTone(pin); 456 | }; 457 | 458 | ext.setLED = function(led, val) { 459 | var hw = hwList.search(led); 460 | if (!hw) return; 461 | analogWrite(hw.pin, val); 462 | hw.val = val; 463 | }; 464 | 465 | ext.changeLED = function(led, val) { 466 | var hw = hwList.search(led); 467 | if (!hw) return; 468 | var b = hw.val + val; 469 | if (b < 0) b = 0; 470 | else if (b > 100) b = 100; 471 | analogWrite(hw.pin, b); 472 | hw.val = b; 473 | }; 474 | 475 | ext.digitalLED = function(led, val) { 476 | var hw = hwList.search(led); 477 | if (!hw) return; 478 | if (val == 'on') { 479 | digitalWrite(hw.pin, HIGH); 480 | hw.val = 255; 481 | } else if (val == 'off') { 482 | digitalWrite(hw.pin, LOW); 483 | hw.val = 0; 484 | } 485 | }; 486 | 487 | ext.readInput = function(name) { 488 | var hw = hwList.search(name); 489 | if (!hw) return; 490 | return analogRead(hw.pin); 491 | }; 492 | 493 | ext.whenButton = function(btn, state) { 494 | var hw = hwList.search(btn); 495 | if (!hw) return; 496 | if (state === 'pressed') 497 | return digitalRead(hw.pin); 498 | else if (state === 'released') 499 | return !digitalRead(hw.pin); 500 | }; 501 | 502 | ext.isButtonPressed = function(btn) { 503 | var hw = hwList.search(btn); 504 | if (!hw) return; 505 | return digitalRead(hw.pin); 506 | }; 507 | 508 | ext.whenInput = function(name, op, val) { 509 | var hw = hwList.search(name); 510 | if (!hw) return; 511 | if (op == '>') 512 | return analogRead(hw.pin) > val; 513 | else if (op == '<') 514 | return analogRead(hw.pin) < val; 515 | else if (op == '=') 516 | return analogRead(hw.pin) == val; 517 | else 518 | return false; 519 | }; 520 | 521 | ext.mapValues = function(val, aMin, aMax, bMin, bMax) { 522 | var output = (((bMax - bMin) * (val - aMin)) / (aMax - aMin)) + bMin; 523 | return Math.round(output); 524 | }; 525 | 526 | ext._getStatus = function() { 527 | if (!connected) 528 | return { status:1, msg:'Disconnected' }; 529 | else 530 | return { status:2, msg:'Connected' }; 531 | }; 532 | 533 | ext._deviceRemoved = function(dev) { 534 | console.log('Device removed'); 535 | // Not currently implemented with serial devices 536 | }; 537 | 538 | var potentialDevices = []; 539 | ext._deviceConnected = function(dev) { 540 | potentialDevices.push(dev); 541 | if (!device) 542 | tryNextDevice(); 543 | }; 544 | 545 | var poller = null; 546 | var watchdog = null; 547 | function tryNextDevice() { 548 | device = potentialDevices.shift(); 549 | if (!device) return; 550 | 551 | device.open({ stopBits: 0, bitRate: 57600, ctsFlowControl: 0 }); 552 | console.log('Attempting connection with ' + device.id); 553 | device.set_receive_handler(function(data) { 554 | var inputData = new Uint8Array(data); 555 | processInput(inputData); 556 | }); 557 | 558 | poller = setInterval(function() { 559 | queryFirmware(); 560 | }, 1000); 561 | 562 | watchdog = setTimeout(function() { 563 | clearInterval(poller); 564 | poller = null; 565 | device.set_receive_handler(null); 566 | device.close(); 567 | device = null; 568 | tryNextDevice(); 569 | }, 5000); 570 | } 571 | 572 | ext._shutdown = function() { 573 | // TODO: Bring all pins down 574 | if (device) device.close(); 575 | if (poller) clearInterval(poller); 576 | device = null; 577 | }; 578 | 579 | // Check for GET param 'lang' 580 | var paramString = window.location.search.replace(/^\?|\/$/g, ''); 581 | var vars = paramString.split("&"); 582 | var lang = 'en'; 583 | for (var i=0; i 1 && pair[0]=='lang') 586 | lang = pair[1]; 587 | } 588 | 589 | var blocks = { 590 | en: [ 591 | ['h', 'when device is connected', 'whenConnected'], 592 | [' ', 'connect %m.hwOut to pin %n', 'connectHW', 'led A', 3], 593 | [' ', 'connect %m.hwIn to analog %n', 'connectHW', 'rotation knob', 0], 594 | ['-'], 595 | [' ', 'set %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 596 | [' ', 'set %m.leds brightness to %n%', 'setLED', 'led A', 100], 597 | [' ', 'change %m.leds brightness by %n%', 'changeLED', 'led A', 20], 598 | ['-'], 599 | [' ', 'rotate %m.servos to %n degrees', 'rotateServo', 'servo A', 180], 600 | [' ', 'rotate %m.servos by %n degrees', 'changeServo', 'servo A', 20], 601 | ['-'], 602 | ['h', 'when %m.buttons is %m.btnStates', 'whenButton', 'button A', 'pressed'], 603 | ['b', '%m.buttons pressed?', 'isButtonPressed', 'button A'], 604 | ['-'], 605 | ['h', 'when %m.hwIn %m.ops %n%', 'whenInput', 'rotation knob', '>', 50], 606 | ['r', 'read %m.hwIn', 'readInput', 'rotation knob'], 607 | ['-'], 608 | [' ', 'set pin %n %m.outputs', 'digitalWrite', 1, 'on'], 609 | [' ', 'set pin %n to %n%', 'analogWrite', 3, 100], 610 | ['-'], 611 | ['h', 'when pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 612 | ['b', 'pin %n on?', 'digitalRead', 1], 613 | ['-'], 614 | ['h', 'when analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 615 | ['r', 'read analog %n', 'analogRead', 0], 616 | ['-'], 617 | [' ', 'tone on pin %n, freq %n, duration %n', 'tone', 3, 440, 1000], 618 | [' ', 'stop tone on pin %n', 'noTone', 3], 619 | ['-'], 620 | ['r', 'map %n from %n %n to %n %n', 'mapValues', 50, 0, 100, -240, 240] 621 | ], 622 | de: [ 623 | ['h', 'Wenn Arduino verbunden ist', 'whenConnected'], 624 | [' ', 'Verbinde %m.hwOut mit Pin %n', 'connectHW', 'LED A', 3], 625 | [' ', 'Verbinde %m.hwIn mit Analog %n', 'connectHW', 'Drehknopf', 0], 626 | ['-'], 627 | [' ', 'Schalte %m.leds %m.outputs', 'digitalLED', 'LED A', 'Ein'], 628 | [' ', 'Setze %m.leds Helligkeit auf %n%', 'setLED', 'LED A', 100], 629 | [' ', 'Ändere %m.leds Helligkeit um %n%', 'changeLED', 'LED A', 20], 630 | ['-'], 631 | [' ', 'Drehe %m.servos auf %n Grad', 'rotateServo', 'Servo A', 180], 632 | [' ', 'Drehe %m.servos um %n Grad', 'changeServo', 'Servo A', 20], 633 | ['-'], 634 | ['h', 'Wenn %m.buttons ist %m.btnStates', 'whenButton', 'Taste A', 'gedrückt'], 635 | ['b', '%m.buttons gedrückt?', 'isButtonPressed', 'Taste A'], 636 | ['-'], 637 | ['h', 'Wenn %m.hwIn %m.ops %n%', 'whenInput', 'Drehknopf', '>', 50], 638 | ['r', 'Wert von %m.hwIn', 'readInput', 'Drehknopf'], 639 | ['-'], 640 | [' ', 'Schalte Pin %n %m.outputs', 'digitalWrite', 1, 'Ein'], 641 | [' ', 'Setze Pin %n auf %n%', 'analogWrite', 3, 100], 642 | ['-'], 643 | ['h', 'Wenn Pin %n ist %m.outputs', 'whenDigitalRead', 1, 'Ein'], 644 | ['b', 'Pin %n ein?', 'digitalRead', 1], 645 | ['-'], 646 | ['h', 'Wenn Analog %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 647 | ['r', 'Wert von Analog %n', 'analogRead', 0], 648 | ['-'], 649 | [' ', 'tone on pin %n, freq %n, duration %n', 'tone', 3, 440, 1000], 650 | [' ', 'stop tone on pin %n', 'noTone', 3], 651 | ['-'], 652 | ['r', 'Setze %n von %n %n auf %n %n', 'mapValues', 50, 0, 100, -240, 240] 653 | ], 654 | nl: [ 655 | ['h', 'als het apparaat verbonden is', 'whenConnected'], 656 | [' ', 'verbindt %m.hwOut met pin %n', 'connectHW', 'led A', 3], 657 | [' ', 'verbindt %m.hwIn met analoog %n', 'connectHW', 'draaiknop', 0], 658 | ['-'], 659 | [' ', 'schakel %m.leds %m.outputs', 'digitalLED', 'led A', 'on'], 660 | [' ', 'schakel %m.leds helderheid tot %n%', 'setLED', 'led A', 100], 661 | [' ', 'verander %m.leds helderheid met %n%', 'changeLED', 'led A', 20], 662 | ['-'], 663 | [' ', 'draai %m.servos tot %n graden', 'rotateServo', 'servo A', 180], 664 | [' ', 'draai %m.servos met %n graden', 'changeServo', 'servo A', 20], 665 | ['-'], 666 | ['h', 'wanneer %m.buttons is %m.btnStates', 'whenButton', 'knop A', 'in gedrukt'], 667 | ['b', '%m.knoppen in gedrukt?', 'isButtonPressed', 'knoppen A'], 668 | ['-'], 669 | ['h', 'wanneer%m.hwIn %m.ops %n%', 'whenInput', 'draaiknop', '>', 50], 670 | ['r', 'read %m.hwIn', 'readInput', 'draaiknop'], 671 | ['-'], 672 | [' ', 'schakel pin %n %m.outputs', 'digitalWrite', 1, 'on'], 673 | [' ', 'schakel pin %n tot %n%', 'analogWrite', 3, 100], 674 | ['-'], 675 | ['h', 'wanneer pin %n is %m.outputs', 'whenDigitalRead', 1, 'on'], 676 | ['b', 'pin %n aan?', 'digitalRead', 1], 677 | ['-'], 678 | ['h', 'wanneer analoge %n %m.ops %n%', 'whenAnalogRead', 1, '>', 50], 679 | ['r', 'lees analoge %n', 'analogRead', 0], 680 | ['-'], 681 | [' ', 'tone on pin %n, freq %n, duration %n', 'tone', 3, 440, 1000], 682 | [' ', 'stop tone on pin %n', 'noTone', 3], 683 | ['-'], 684 | ['r', 'zet %n van %n %n tot %n %n', 'mapValues', 50, 0, 100, -240, 240] 685 | ] 686 | }; 687 | 688 | var menus = { 689 | en: { 690 | buttons: ['button A', 'button B', 'button C', 'button D'], 691 | btnStates: ['pressed', 'released'], 692 | hwIn: ['rotation knob', 'light sensor', 'temperature sensor'], 693 | hwOut: ['led A', 'led B', 'led C', 'led D', 'button A', 'button B', 'button C', 'button D', 'servo A', 'servo B', 'servo C', 'servo D'], 694 | leds: ['led A', 'led B', 'led C', 'led D'], 695 | outputs: ['on', 'off'], 696 | ops: ['>', '=', '<'], 697 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 698 | }, 699 | de: { 700 | buttons: ['Taste A', 'Taste B', 'Taste C', 'Taste D'], 701 | btnStates: ['gedrückt', 'losgelassen'], 702 | hwIn: ['Drehknopf', 'Lichtsensor', 'Temperatursensor'], 703 | hwOut: ['LED A', 'LED B', 'LED C', 'LED D', 'Taste A', 'Taste B', 'Taste C', 'Taste D', 'Servo A', 'Servo B', 'Servo C', 'Servo D'], 704 | leds: ['LED A', 'LED B', 'LED C', 'LED D'], 705 | outputs: ['Ein', 'Aus'], 706 | ops: ['>', '=', '<'], 707 | servos: ['Servo A', 'Servo B', 'Servo C', 'Servo D'] 708 | }, 709 | nl: { 710 | buttons: ['knop A', 'knop B', 'knop C', 'knop D'], 711 | btnStates: ['ingedrukt', 'losgelaten'], 712 | hwIn: ['draaiknop', 'licht sensor', 'temperatuur sensor'], 713 | hwOut: ['led A', 'led B', 'led C', 'led D', 'knop A', 'knop B', 'knop C', 'knop D', 'servo A', 'servo B', 'servo C', 'servo D'], 714 | leds: ['led A', 'led B', 'led C', 'led D'], 715 | outputs: ['aan', 'uit'], 716 | ops: ['>', '=', '<'], 717 | servos: ['servo A', 'servo B', 'servo C', 'servo D'] 718 | } 719 | }; 720 | 721 | var descriptor = { 722 | blocks: blocks[lang], 723 | menus: menus[lang], 724 | url: 'http://khanning.github.io/scratch-arduino-extension' 725 | }; 726 | 727 | ScratchExtensions.register('Arduino', descriptor, ext, {type:'serial'}); 728 | 729 | })({}); 730 | -------------------------------------------------------------------------------- /bin/ScratchDevicePlugin.dmg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/bin/ScratchDevicePlugin.dmg -------------------------------------------------------------------------------- /bin/ScratchDevicePlugin.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/bin/ScratchDevicePlugin.msi -------------------------------------------------------------------------------- /blocks.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scratch Arduino Extension 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |

Scratch Arduino Extension

12 | 19 |
20 | 21 | View project on Github 22 | 23 |
24 | 25 |
26 | 27 | 28 |

Scratch Blocks

29 |

This is a brief description of each of the Scratch blocks included with the Arduino extension.

30 |
31 | 32 |
33 | 34 |

Runs when the device is connected

35 |
36 | 37 |
38 | 39 |
40 | 41 |

Connects an LED, button, or servo to a digital connection.

42 |

See the Hardware page for an explaination of digital vs. analog connections

43 |
44 | 45 |
46 | 47 |
48 | 49 |

Connects a rotation knob, light sensor, or temperature sensor to an analog connection. 50 |

See the Hardware page for an explaination of digital vs. analog connections

51 |
52 | 53 |
54 | 55 |
56 | 57 |

Turns an LED on or off.

58 |
59 | 60 |
61 | 62 |
63 | 64 |

Sets an LED to a specified brightness from 0 - 100%.
If you go above 100, a value of 100 will be used.
If you go below 0, a value of 0 will be used.

65 |
66 | 67 |
68 | 69 |
70 | 71 |

Changes the current LED brightness by a specified amount.
A positive value will make the LED get brighter and a negative value will make it get dimmer.

72 |
73 | 74 |
75 | 76 |
77 | 78 |

Rotates a servo to a specified location from 0 - 180 degrees.
If you go above 180, a value of 180 will be used.
If you go below 0, a value of 0 will be used.

79 |
80 | 81 |
82 | 83 |
84 | 85 |

Changes a servo's current rotation by a specified amount.
A negative value will make the servo rotate in the opposite direction.

86 |
87 | 88 |
89 | 90 |
91 | 92 |

Runs when a button is pressed or released.

93 |
94 | 95 |
96 | 97 |
98 | 99 |

Checks if a button is currently pressed.

100 |
101 | 102 |
103 | 104 |
105 | 106 |

Runs when a rotation knob, light sensor, or temperator sensor meet a certain condition.

107 |

108 | 109 |
110 | 111 |
112 | 113 |

Reads the current value of a rotation knob, light sensor, or temperature sensor. Value will be between 0 - 100.

114 |
115 | 116 |
117 | 118 |
119 | 120 |

Turns a digital connection on or off.

121 |

See the Hardware page for an explaination of digital vs. analog connections

122 |
123 | 124 |
125 | 126 |
127 | 128 |

Sets a capable digital connection to a value from 0 - 100%.
If you go above 100, a value of 100 will be used.
If you go below 0, a value of 0 will be used.

129 |

See the Hardware page for an explaination of digital vs. analog connections

130 |
131 | 132 |
133 | 134 |
135 | 136 |

Runs when a digital connection is turned on or off.

137 |

See the Hardware page for an explaination of digital vs. analog connections

138 |
139 | 140 |
141 | 142 |
143 | 144 |

Checks if a digital connection is on or off.

145 |

See the Hardware page for an explaination of digital vs. analog connections

146 |
147 | 148 |
149 | 150 |
151 | 152 |

Runs when an analog connection meets a certain condition.

153 |

See the Hardware page for an explaination of digital vs. analog connections

154 |
155 | 156 |
157 | 158 |
159 | 160 |

Checks the current value of an analog connection.

161 |

See the Hardware page for an explaination of digital vs. analog connections

162 |
163 | 164 |
165 | 166 |
167 | 168 |

Maps a value between two ranges of numbers. This example might be used to map an analog sensor's value (0 to 100) to a sprite's x position (-240 to 240).

169 |
170 | 171 |
172 | 173 |
174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /examples.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scratch Arduino Extension 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |

Scratch Arduino Extension

12 | 19 |
20 | 21 | View project on Github 22 | 23 |
24 | 25 |
26 | 27 | 28 |

Example Projects

29 | 30 |
31 |
Blink an LED
32 |
Make an LED blink on and off
33 |
34 |
Fade an LED
35 |
Fade an LED brightness
36 |
37 |
Button
38 |
Pressing and releasing a button
39 |
40 |
Rotation Knob
41 |
Reading analog input from a rotation knob
42 |
43 |
Light Sensor
44 |
Reading analog input from a light sensor
45 |
46 |
Adjusting LED with Rotation Knob
47 |
Adjust the brightness of an LED by turning a rotation knob
48 |
49 |
Swing a Servo
50 |
Swinging a servo motor back and forth
51 |
52 |
53 | 54 |
55 | 56 |
57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /examples/Arduino Example - Adjusting LED with Rotation Knob.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Adjusting LED with Rotation Knob.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Blink a LED.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Blink a LED.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Blink an LED.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Blink an LED.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Button.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Button.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Fade a LED.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Fade a LED.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Fade an LED.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Fade an LED.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Light Sensor.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Light Sensor.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Rotation Knob.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Rotation Knob.sbx -------------------------------------------------------------------------------- /examples/Arduino Example - Swing a Servo.sbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/examples/Arduino Example - Swing a Servo.sbx -------------------------------------------------------------------------------- /gettingstarted.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scratch Arduino Extension 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |

Scratch Arduino Extension

12 | 19 |
20 | 21 | View project on Github 22 | 23 |
24 | 25 |
26 | 27 | 28 |

Getting Started

29 | 30 |

1. Upload the StandardFirmata firmware to Arduino

31 |
    32 |
  1. If you haven't already, download and install the Arduino software (Windows or Mac instructions)
  2. 33 |
  3. Connect the Arduino board to your computer's USB port
  4. 34 |
  5. Launch the Arduino software
  6. 35 |
  7. Go to File > Examples > Firmata > Standard Firmata
  8. 36 |
  9. Select your Arduino board from the Tools > Board menu
  10. 37 |
  11. Select your serial port from the Tools > Port menu.
    On Mac, it's something like /dev/tty.usbmodem-1511.
    On Windows, it's probably the highest-numbered COM port.
    (Or unplug the Arduino, check the menu, and then replug your Arduino and see what new port appears.)
  12. 38 |
  13. Click the upload button
  14. 39 |
40 | 41 |

2. Install the Scratch Extensions Browser Plugin

42 |

You will need to use the Firefox web browser for this extension to work

43 |

Download and install the Scratch Extensions Browser Plugin for "other web browsers"

44 |

*There is an issue with the Chrome version of the Scratch Extensions Browser Plugin that is preventing the Arduino extension from working properly in the Chrome web browser

45 | 46 |

3. Load the Arduino extension on ScratchX

47 | 48 |

Launch the extension by going to the following URL:

49 | http://scratchx.org/?url=http://khanning.github.io/scratch-arduino-extension/arduino_extension.js 50 | 51 |

NOTE: On Firefox, you might see "Allow scratchx.org to run "Scratch Device?". Click "Allow...".

52 |

53 |

You might see another message, "Allow scratchx.org to run plugins?". Set both Adobe Flash and Scratch Device to "Allow and Remember" and click okay.

54 |

55 | 56 |

4. Waiting for the green light

57 | 58 |

When you see the indicator light in the "More Blocks" tab turn green your ready to start using the extension!

59 | Green indicator light 60 |

See the section on the homepage for Supported Languages, for information on alternate block tanslations.

61 |

Now take a look at the Scratch Blocks and the example projects to learn how to use the extension. 62 | 63 |

64 | 65 |
66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /hardware.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scratch Arduino Extension 4 | 5 | 6 | 7 | 8 | 9 |
10 |
11 |

Scratch Arduino Extension

12 | 19 |
20 | 21 | View project on Github 22 | 23 |
24 | 25 |
26 | 27 | 28 |

Grove Modules

29 | 30 |

Grove Base Shield

31 | 32 | 33 | 34 |

The Grove Base Shield (V2) connects your Arduino board to the other Grove modules. It has different kinds of connections:

35 |
36 |
A0, A1, A2, A3
37 |
Analog inputs that read from sensors, like the light sensor, temperature sensor, and rotation knob.
38 |
D2, D3, D4, D5, D6, D7, D8
39 |
Digital connections that control LEDs and servo motors and read from push buttons. To fade an LED (not just turn it on and off), use D3, D5, or D6.
40 |
I2C and UART
41 |
These are more complex connections that we don't use in the extension yet.
42 |
43 |

To connect a module to the shield, plug one of the Grove cables into the white connector on the module and one of the connectors on the shield. The cable only goes into the connector one way.

44 | 45 |
46 |

Grove Button

47 | 48 |

A button you can press

49 |
50 | 51 |
52 |

Grove Light Sensor

53 | 54 |

Measures light

55 |
56 | 57 |
58 |

Grove Rotation Knob

59 | 60 |

Control things by rotating the knob

61 |
62 | 63 |
64 |

Grove Temperature Sensor

65 | 66 |

Measures temperature

67 |
68 | 69 |
70 |

Grove LED

71 | 72 |

A small light

73 |
74 | 75 |
76 |

Grove Servo Motor

77 | 78 |

Moves its arm back and forth

79 |
80 | 81 | 82 |

Working w/ Basic Electronic Components

83 | 84 | Arduino Uno 85 |
86 |
A0, A1, A2, A3, A5
87 |
Analog inputs (green arrow) that read from sensors, like the light sensor, temperature sensor, and rotation knob.
88 |
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
89 |
Digital connections (red arrow) that control LEDs and servo motors and read from push buttons. To fade an LED (not just turn it on and off), use D3, D5, or D6.
90 |
91 | 92 |
93 | 94 |
95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /images/ArduinoUnoPins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/ArduinoUnoPins.png -------------------------------------------------------------------------------- /images/arduino-board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/arduino-board.png -------------------------------------------------------------------------------- /images/arduino-port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/arduino-port.png -------------------------------------------------------------------------------- /images/arduino-upload-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/arduino-upload-button.png -------------------------------------------------------------------------------- /images/arduino-upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/arduino-upload.png -------------------------------------------------------------------------------- /images/arduino.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/arduino.png -------------------------------------------------------------------------------- /images/blocks/button-boolean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/button-boolean.png -------------------------------------------------------------------------------- /images/blocks/button-when.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/button-when.png -------------------------------------------------------------------------------- /images/blocks/device-connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/device-connected.png -------------------------------------------------------------------------------- /images/blocks/led-change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/led-change.png -------------------------------------------------------------------------------- /images/blocks/led-connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/led-connect.png -------------------------------------------------------------------------------- /images/blocks/led-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/led-digital.png -------------------------------------------------------------------------------- /images/blocks/led-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/led-set.png -------------------------------------------------------------------------------- /images/blocks/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/map.png -------------------------------------------------------------------------------- /images/blocks/pin-read-analog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-read-analog.png -------------------------------------------------------------------------------- /images/blocks/pin-read-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-read-digital.png -------------------------------------------------------------------------------- /images/blocks/pin-when-analog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-when-analog.png -------------------------------------------------------------------------------- /images/blocks/pin-when-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-when-digital.png -------------------------------------------------------------------------------- /images/blocks/pin-write-analog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-write-analog.png -------------------------------------------------------------------------------- /images/blocks/pin-write-digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/pin-write-digital.png -------------------------------------------------------------------------------- /images/blocks/sensor-connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/sensor-connect.png -------------------------------------------------------------------------------- /images/blocks/sensor-read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/sensor-read.png -------------------------------------------------------------------------------- /images/blocks/sensor-when.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/sensor-when.png -------------------------------------------------------------------------------- /images/blocks/servo-change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/servo-change.png -------------------------------------------------------------------------------- /images/blocks/servo-set.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/blocks/servo-set.png -------------------------------------------------------------------------------- /images/chrome-npapi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/chrome-npapi.png -------------------------------------------------------------------------------- /images/chrome-npapi2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/chrome-npapi2.png -------------------------------------------------------------------------------- /images/chrome-npapi3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/chrome-npapi3.png -------------------------------------------------------------------------------- /images/chrome-plugin-broken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/chrome-plugin-broken.png -------------------------------------------------------------------------------- /images/chrome-plugin-enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/chrome-plugin-enable.png -------------------------------------------------------------------------------- /images/connected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/connected.png -------------------------------------------------------------------------------- /images/disconnected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/disconnected.png -------------------------------------------------------------------------------- /images/firefox-plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/firefox-plugin.png -------------------------------------------------------------------------------- /images/firefox-plugin2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/firefox-plugin2.png -------------------------------------------------------------------------------- /images/firmata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/firmata.png -------------------------------------------------------------------------------- /images/github-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/github-banner.png -------------------------------------------------------------------------------- /images/grove-button.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-button.jpg -------------------------------------------------------------------------------- /images/grove-led.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-led.jpg -------------------------------------------------------------------------------- /images/grove-light-sensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-light-sensor.jpg -------------------------------------------------------------------------------- /images/grove-rotation-knob.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-rotation-knob.jpg -------------------------------------------------------------------------------- /images/grove-servo-motor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-servo-motor.jpg -------------------------------------------------------------------------------- /images/grove-shield.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-shield.jpg -------------------------------------------------------------------------------- /images/grove-temperature-sensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-temperature-sensor.jpg -------------------------------------------------------------------------------- /images/grove-wired.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove-wired.jpg -------------------------------------------------------------------------------- /images/grove.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/grove.jpg -------------------------------------------------------------------------------- /images/moreblocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/moreblocks.png -------------------------------------------------------------------------------- /images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/khanning/scratch-arduino-extension/c7972a4d64428bb2895e935598eae37cf2a163ec/images/upload.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Scratch Arduino Extension 4 | 5 | 6 | 7 | 8 | 9 |
24 | 25 |
26 | 27 | 28 |

Introduction

29 | 30 |

This Scratch extension lets you interact with the physical world using an Arduino board. For example, you can control lights and motors or measure light and temperature. The extension communicates with an Arduino board running the Firmata firmware.

31 | 32 |

The Arduino extension uses ScratchX, which is the Experiemental Extension system for the Scratch programming language.

33 | 34 |
Arduino board with a Grove LED, button, and temperature sensor. 35 | 36 |

Equipment you will need:

37 | 38 |
39 |
Arduino board
40 |
Like the Arduino Uno.
41 |
USB Cable
42 |
Full-sized
43 |
Electronic components
44 |
We recommend the Grove starter kit for Arduino (made by Seeed Studio). You can buy it from Maker Shed in the U.S. For other options, see working with basic electronic components below.
45 | 46 |

Getting Started

47 | 48 |

For full instructions on using the extension, see the Getting Started page.

49 | 50 |

If you run into any problems using the extension, file an issue on Github

51 | 52 |

If you already know what to do you can launch the extension on ScratchX

53 | 54 | 55 |

Supported Languages

56 | 57 |

Block translations have been provided for the following languages:

58 |
79 |

To set the block language, add &lang=XX to the ScratchX URL.
Where XX = one of the two letter language codes above

80 |

Example for German:
http://scratchx.org?url=http://khanning.github.io/scratch-arduino-extension/arduino_extension.js&lang=de

81 |

If you would like to help out by providing block translations for another language, please see the Github issue.

82 | 83 |
84 | 85 |
86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | background-color: #FFF; 5 | font-family: Arial, Helvetica, sans-serif; 6 | line-height: 1.3em; 7 | } 8 | 9 | h1 { 10 | color: #00979D; 11 | } 12 | 13 | li { 14 | padding: 5px 0; 15 | } 16 | 17 | #header-container { 18 | margin: 0 0 50px 0; 19 | background-color: #00979D; 20 | } 21 | 22 | header { 23 | margin: 0 auto; 24 | max-width: 700px; 25 | } 26 | 27 | header h1 { 28 | color: #FFF; 29 | margin: 0; 30 | padding: 30px 0; 31 | } 32 | 33 | header ul { 34 | list-style-type: none; 35 | margin: 0; 36 | padding: 0; 37 | overflow: hidden; 38 | } 39 | 40 | header li { 41 | float: left; 42 | padding: 0; 43 | } 44 | 45 | header li a { 46 | display: block; 47 | color: #FFF; 48 | text-align: center; 49 | padding: 10px 16px; 50 | text-decoration: none; 51 | } 52 | 53 | header a:hover:not(.selected) { 54 | background-color: #008184; 55 | } 56 | 57 | header .selected { 58 | background-color: #008184; 59 | } 60 | 61 | #github-banner { 62 | position: absolute; 63 | top: 0; 64 | right: 0; 65 | border: 0; 66 | } 67 | 68 | #content-container { 69 | margin: 0 auto; 70 | padding-bottom: 50px; 71 | max-width: 700px; 72 | } 73 | 74 | #nav { 75 | list-style-type: none; 76 | padding: 0; 77 | } 78 | 79 | #nav li { 80 | padding: 2px 0 0 0; 81 | } 82 | 83 | #nav a, #langs a { 84 | color: blue; 85 | text-decoration: none; 86 | } 87 | 88 | #nav a:hover, #langs a:hover { 89 | text-decoration: underline; 90 | } 91 | 92 | #nav a:visited, #langs a:visited { 93 | color: blue; 94 | } 95 | 96 | .small-text { 97 | font-size: .8em; 98 | } 99 | 100 | .component { 101 | width: 220px; 102 | display: inline-block; 103 | vertical-align: top; 104 | text-align: center; 105 | } 106 | --------------------------------------------------------------------------------