Skip to content

Commit 81b2be3

Browse files
committed
first try (but needs windows plugin ...)
1 parent 85d978c commit 81b2be3

File tree

3 files changed

+201
-4
lines changed

3 files changed

+201
-4
lines changed

ArduinoScratch.ino

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
#include <Arduino.h>
22

3+
bool ledState = LOW;
4+
bool buttonState = LOW;
5+
36
void setup(void) {
47
pinMode(13, OUTPUT);
8+
digitalWrite(13, LOW);
9+
10+
// TODO : bind raising interrupt on this digital input
511
pinMode(12, INPUT);
12+
613
Serial.begin(115200);
714
}
815

916
void loop() {
1017
int input = Serial.read();
1118
if (input == '0') {
12-
digitalWrite(13, LOW);
13-
Serial.println("OFF");
19+
ledState = LOW;
1420
} else if (input == '1') {
15-
digitalWrite(13, HIGH);
16-
Serial.println("ON");
21+
ledState = HIGH;
22+
} else if (input == '?') {
23+
Serial.println(ledState ? "1" : "0");
1724
}
25+
digitalWrite(13, ledState);
1826
}

extension/arduino.extension.js

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// See http://llk.github.io/scratch-extension-docs/
2+
// + install http://cdn.scratch.mit.edu/scratchr2/static/__172524edbffb65446b8d280ce8bcec1a__//ext/ScratchDevicePlugin.msi
3+
4+
var myExtension;
5+
6+
new (function() {
7+
var ext = this;
8+
// Currently connected serial device. Undefined if nothing connected. First connected is used.
9+
10+
// current state of arduino when connected
11+
var status = {
12+
led: null,
13+
buttonPressed: null
14+
};
15+
16+
myExtension = {
17+
status: status,
18+
device: null
19+
}
20+
21+
ext.getLed = function() {
22+
if (myExtension.device !== null && status.led !== null) {
23+
return status.led;
24+
} else {
25+
return "???";
26+
}
27+
};
28+
29+
ext.ifLed = function(what) {
30+
if (myExtension.device !== null && status.led !== null) {
31+
return what === status.led;
32+
} else {
33+
return false;
34+
}
35+
};
36+
37+
var ON = new Uint8Array(1), OFF = new Uint8Array(1);
38+
ON[0] = '1';
39+
OFF[0] = '0';
40+
41+
ext.setLed = function(what) {
42+
if (myExtension.device === null) {
43+
return;
44+
}
45+
myExtension.device.send(what === "on" ? ON : OFF);
46+
};
47+
48+
ext.onButton = function() {
49+
if (myExtension.device === null) {
50+
return false;;
51+
}
52+
53+
if (status.buttonPressed === true) {
54+
status.buttonPressed = false;
55+
return true;
56+
} else {
57+
return false;
58+
}
59+
};
60+
61+
// serial dialog methods
62+
function handleData(/*uint8=char ?*/ c) {
63+
if (c == '.') {
64+
// ping => ok
65+
clearWatchDog();
66+
} else if (c == '!') {
67+
status.buttonPressed = true;
68+
} else if (c == '0' || c == '1') {
69+
status.led = c;
70+
} else {
71+
console.Log("bad char '" + c + "' ?");
72+
}
73+
}
74+
75+
// Extension API interactions
76+
// each time a device is connected, it's added to this list
77+
var potentialDevices = [];
78+
// callback on device connection
79+
ext._deviceConnected = function(dev) {
80+
// add it to list
81+
potentialDevices.push(dev);
82+
83+
// and make it current one if none currently affected
84+
if (!myExtension.device) {
85+
tryNextDevice();
86+
}
87+
}
88+
89+
var poller = null;
90+
var watchdog = null;
91+
92+
function tryNextDevice() {
93+
// If potentialDevices is empty, device will be undefined.
94+
// That will get us back here next time a device is connected.
95+
myExtension.device = potentialDevices.shift();
96+
if (!myExtension.device) return;
97+
98+
myExtension.device.open({ stopBits: 0, bitRate: 115200, ctsFlowControl: 0 });
99+
// register a callback for received data
100+
myExtension.device.set_receive_handler(function(data) {
101+
rawData = new Uint8Array(data);
102+
// for the moment, we handle received data byte per byte
103+
// later, will have to handle fixed len or length-data buffers
104+
for(i = 0; i < rawData.length; i++) {
105+
if (rawData[i] === '\n') {
106+
continue;
107+
}
108+
handleData(rawData[i]);
109+
}
110+
console.log('Received: ' + data.byteLength + " : " + data);
111+
});
112+
113+
var pingCmd = new Uint8Array(1);
114+
pingCmd[0] = '?';
115+
poller = setInterval(function() {
116+
myExtension.device.send(pingCmd.buffer);
117+
}, 100);
118+
watchdog = setTimeout(function() {
119+
// This device didn't get good data in time, so give up on it. Clean up and then move on.
120+
// If we get good data then we'll terminate this watchdog.
121+
clearInterval(poller);
122+
poller = null;
123+
myExtension.device.set_receive_handler(null);
124+
myExtension.device.close();
125+
myExtension.device = null;
126+
tryNextDevice();
127+
}, 500);
128+
}
129+
130+
// user may call this method when he verified that connected device is of good type
131+
function clearWatchDog() {
132+
if (watchdog) {
133+
clearTimeout(watchdog);
134+
watchdog = null;
135+
}
136+
}
137+
138+
// callback when a device is disconnected
139+
ext._deviceRemoved = function(dev) {
140+
if(myExtension.device != dev) return;
141+
if(poller) poller = clearInterval(poller);
142+
myExtension.device = null;
143+
// TODO : Should call ? tryNextDevice();
144+
};
145+
146+
// Cleanup function when the extension is unloaded
147+
ext._shutdown = function() {
148+
if(myExtension.device) myExtension.device.close();
149+
if(poller) poller = clearInterval(poller);
150+
myExtension.device = null;
151+
};
152+
153+
// Status reporting code
154+
// Use this to report missing hardware, plugin or unsupported browser
155+
// Value / status light Color / Meaning
156+
// 0 red error
157+
// 1 yellow not ready
158+
// 2 green ready
159+
ext._getStatus = function() {
160+
if(!myExtension.device) return {status: 1, msg: 'Arduino disconnected'};
161+
if(watchdog) return {status: 1, msg: 'Probing for Arduino'};
162+
return {status: 2, msg: 'Arduino connected'};
163+
}
164+
165+
// Block and block menu descriptions
166+
var descriptor = {
167+
// each block begins by a Op Code :
168+
// ' ' (space) Synchronous command
169+
// 'w' Asynchronous command
170+
// 'r' Synchronous reporter
171+
// 'R' Asynchronous reporter
172+
// 'h' Hat block (synchronous, returns boolean, true = run stack)
173+
// then, a description with arguments marked by %... : %n for number, %s for string, and %m.menuName for menu
174+
blocks: [
175+
['', 'set led %m.led', 'setLed', 'on'],
176+
['r', 'led state', 'getLed'],
177+
['r', 'if led is %m.led', 'ifLed', 'on'],
178+
['h', 'when button is pressed', 'onButton'],
179+
],
180+
menus: {
181+
led: ['on', 'off']
182+
}
183+
};
184+
185+
// Register the extension
186+
ScratchExtensions.register('My first extension', descriptor, ext, {type: 'serial'});
187+
})();

run.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
HERE=$(cd $(dirname $0) ; /bin/pwd)
2+
$HERE/../arddude/etc/ad.sh $1 avrdude -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:$HERE/target/Uno/ArduinoScratch.hex:i

0 commit comments

Comments
 (0)