kopia lustrzana https://github.com/backface/turtlestitch
1030 wiersze
28 KiB
JavaScript
1030 wiersze
28 KiB
JavaScript
|
|
window.birdbrain = {};
|
|
window.birdbrain.sensorData = {};
|
|
window.birdbrain.sensorData.A = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
|
window.birdbrain.sensorData.B = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
|
window.birdbrain.sensorData.C = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
|
window.birdbrain.microbitIsV2 = {};
|
|
window.birdbrain.microbitIsV2.A = false;
|
|
window.birdbrain.microbitIsV2.B = false;
|
|
window.birdbrain.microbitIsV2.C = false;
|
|
window.birdbrain.currentBeak = {};
|
|
window.birdbrain.currentBeak.A = [0,0,0];
|
|
window.birdbrain.currentBeak.B = [0,0,0];
|
|
window.birdbrain.currentBeak.C = [0,0,0];
|
|
window.birdbrain.robotType = {
|
|
FINCH: 1,
|
|
HUMMINGBIRDBIT: 2,
|
|
MICROBIT: 3,
|
|
GLOWBOARD: 4,
|
|
//connected robots default to type MICROBIT
|
|
A: 3,
|
|
B: 3,
|
|
C: 3
|
|
};
|
|
|
|
//For the old style robots that connect over hid.
|
|
window.bbtLegacy = {};
|
|
window.bbtLegacy.sensorData = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
|
|
|
|
console.log("setting up message channel")
|
|
window.birdbrain.messageChannel = new MessageChannel();
|
|
window.birdbrain.messageChannel.port1.onmessage = function (e) {
|
|
//console.log("Got a message: ");
|
|
//console.log(e.data);
|
|
if (e.data.sensorData != null && e.data.robot != null) {
|
|
let robot = e.data.robot;
|
|
window.birdbrain.sensorData[robot] = e.data.sensorData;
|
|
window.birdbrain.robotType[robot] = e.data.robotType;
|
|
window.birdbrain.microbitIsV2[robot] = e.data.hasV2Microbit;
|
|
}
|
|
|
|
if (e.data.hidSensorData != null ) {
|
|
window.bbtLegacy.sensorData = e.data.hidSensorData;
|
|
}
|
|
}
|
|
window.parent.postMessage("hello from snap", "*", [window.birdbrain.messageChannel.port2]);
|
|
|
|
window.birdbrain.sendCommand = function(command) {
|
|
window.parent.postMessage(command, "*");
|
|
}
|
|
|
|
// Converts byte range 0 - 255 to -127 - 127 represented as a 32 bit signe int
|
|
function byteToSignedInt8 (byte) {
|
|
var sign = (byte & (1 << 7));
|
|
var value = byte & 0x7F;
|
|
if (sign) { value = byte | 0xFFFFFF00; }
|
|
return value;
|
|
}
|
|
|
|
// Converts byte range 0 - 255 to -127 - 127 represented as a 32 bit signe int
|
|
function byteToSignedInt16 (msb, lsb) {
|
|
var sign = msb & (1 << 7);
|
|
var value = (((msb & 0xFF) << 8) | (lsb & 0xFF));
|
|
if (sign) {
|
|
value = 0xFFFF0000 | value; // fill in most significant bits with 1's
|
|
}
|
|
return value;
|
|
}
|
|
|
|
window.birdbrain.getMicrobitAcceleration = function(axis, robot) {
|
|
const rawToMperS = 196/1280; //convert to meters per second squared
|
|
let sensorData = window.birdbrain.sensorData[robot];
|
|
let accVal = 0;
|
|
switch (axis) {
|
|
case 'X':
|
|
accVal = byteToSignedInt8(sensorData[4]);
|
|
break;
|
|
case 'Y':
|
|
accVal = byteToSignedInt8(sensorData[5]);
|
|
break;
|
|
case 'Z':
|
|
accVal = byteToSignedInt8(sensorData[6]);
|
|
break;
|
|
}
|
|
return (accVal * rawToMperS);
|
|
}
|
|
|
|
window.birdbrain.getMicrobitMagnetometer = function(axis, finch) {
|
|
const rawToUT = 1/10; //convert to uT
|
|
let sensorData = window.birdbrain.sensorData[finch];
|
|
let msb = 0;
|
|
let lsb = 0;
|
|
switch (axis) {
|
|
case 'X':
|
|
msb = sensorData[8];
|
|
lsb = sensorData[9];
|
|
break;
|
|
case 'Y':
|
|
msb = sensorData[10];
|
|
lsb = sensorData[11];
|
|
break;
|
|
case 'Z':
|
|
msb = sensorData[12];
|
|
lsb = sensorData[13];
|
|
break;
|
|
}
|
|
let magVal = byteToSignedInt16(msb, lsb);
|
|
return Math.round(magVal * rawToUT);
|
|
}
|
|
|
|
window.birdbrain.getFinchAcceleration = function(axis, finch) {
|
|
let sensorData = window.birdbrain.sensorData[finch];
|
|
let accVal = 0;
|
|
switch (axis) {
|
|
case 'X':
|
|
accVal = byteToSignedInt8(sensorData[13]);
|
|
break;
|
|
case 'Y':
|
|
case 'Z':
|
|
const rawY = byteToSignedInt8(sensorData[14]);
|
|
const rawZ = byteToSignedInt8(sensorData[15]);
|
|
const rad = 40 * Math.PI / 180; //40° in radians
|
|
|
|
switch(axis) {
|
|
case 'Y':
|
|
accVal = (rawY*Math.cos(rad) - rawZ*Math.sin(rad));
|
|
break;
|
|
case 'Z':
|
|
accVal = (rawY*Math.sin(rad) + rawZ*Math.cos(rad));
|
|
break;
|
|
}
|
|
}
|
|
return (accVal * 196/1280);
|
|
}
|
|
|
|
window.birdbrain.getFinchMagnetometer = function(axis, finch) {
|
|
let sensorData = window.birdbrain.sensorData[finch];
|
|
switch (axis) {
|
|
case 'X':
|
|
return byteToSignedInt8(sensorData[17]);
|
|
case 'Y':
|
|
case 'Z':
|
|
const rawY = byteToSignedInt8(sensorData[18]);
|
|
const rawZ = byteToSignedInt8(sensorData[19]);
|
|
const rad = 40 * Math.PI / 180 //40° in radians
|
|
|
|
let magVal = 0;
|
|
switch(axis) {
|
|
case 'Y':
|
|
magVal = (rawY*Math.cos(rad) + rawZ*Math.sin(rad));
|
|
break;
|
|
case 'Z':
|
|
magVal = (rawZ*Math.cos(rad) - rawY*Math.sin(rad));
|
|
break;
|
|
}
|
|
return Math.round(magVal);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
//// Motion Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_bitpositionservo(robot, port, position)',
|
|
function (robot, port, position) {
|
|
position = Math.max(0, Math.min(180, position));
|
|
position = Math.round(1.41 * position);//254/180 Scaling Factor
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "servo",
|
|
port: port,
|
|
value: position
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_bitrotationservo(robot, port, speed)',
|
|
function (robot, port, speed) {
|
|
speed = Math.max(-100, Math.min(100, speed));
|
|
if (speed < 10 && speed > -10) {
|
|
speed = 255;
|
|
} else {
|
|
speed = Math.round((speed * 23/100) + 122)
|
|
}
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "servo",
|
|
port: port,
|
|
value: speed
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchismoving(robot)',
|
|
function (robot) {
|
|
return (window.birdbrain.sensorData[robot][4] > 127);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchmove(robot, direction, distance, speed)',
|
|
function (robot, direction, distance, speed) {
|
|
distance = Math.max(-10000, Math.min(10000, distance));
|
|
speed = Math.max(0, Math.min(100, speed));
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "move",
|
|
direction: direction,
|
|
distance: distance,
|
|
speed: speed
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchstop(robot)',
|
|
function (robot) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "stopFinch"
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchturn(robot, direction, angle, speed)',
|
|
function (robot, direction, angle, speed) {
|
|
angle = Math.max(-360000, Math.min(360000, angle));
|
|
speed = Math.max(0, Math.min(100, speed));
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "turn",
|
|
direction: direction,
|
|
angle: angle,
|
|
speed: speed
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchwheels(robot, left, right)',
|
|
function (robot, left, right) {
|
|
left = Math.max(-100, Math.min(100, left));
|
|
right = Math.max(-100, Math.min(100, right));
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "wheels",
|
|
speedL: left,
|
|
speedR: right
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
//// Looks Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_display(robot, symbol)',
|
|
function (robot, symbolString) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "symbol",
|
|
symbolString: symbolString
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_led(robot, port, intensity)',
|
|
function (robot, port, intensity) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "led",
|
|
port: port,
|
|
intensity: Math.floor(Math.max(Math.min(intensity*2.55, 255), 0))
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_print(robot, string)',
|
|
function (robot, string) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "print",
|
|
printString: string
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_triled(robot, port, red, green, blue)',
|
|
function (robot, port, red, green, blue) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "triled",
|
|
port: port,
|
|
red: Math.floor(Math.max(Math.min(red*2.55, 255), 0)),
|
|
green: Math.floor(Math.max(Math.min(green*2.55, 255), 0)),
|
|
blue: Math.floor(Math.max(Math.min(blue*2.55, 255), 0))
|
|
}
|
|
if (port == 1) {
|
|
window.birdbrain.currentBeak[robot] = [thisCommand.red, thisCommand.green, thisCommand.blue];
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
//// Control Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_stop(robot)',
|
|
function (robot) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "stopAll"
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
//// Sound Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_playnote(robot, note, duration)',
|
|
function (robot, note, duration) {
|
|
note = Math.round(Math.max(32, Math.min(135, note)));
|
|
console.log("playing note " + note);
|
|
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "playNote",
|
|
note: note,
|
|
duration: duration
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
//// Sensing Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_accelerometer(robot, dimension)',
|
|
function (robot, dim) {
|
|
let acc = window.birdbrain.getMicrobitAcceleration(dim, robot);
|
|
return Math.round(acc * 10) / 10;
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_bitsensor(robot, sensor, port)',
|
|
function (robot, sensor, port) {
|
|
const distanceScaling = 117/100;
|
|
const dialScaling = 100/230;
|
|
const lightScaling = 100/255;
|
|
const soundScaling = 200/255;
|
|
const voltageScaling = 3.3/255;
|
|
|
|
let value = window.birdbrain.sensorData[robot][port - 1];
|
|
|
|
switch(sensor) {
|
|
case "Distance (cm)":
|
|
return Math.round(value * distanceScaling);
|
|
case "Dial":
|
|
if (value > 230) { value = 230; }
|
|
return Math.round(value * dialScaling);
|
|
case "Light":
|
|
return Math.round(value * lightScaling);
|
|
case "Sound":
|
|
return Math.round(value * soundScaling);
|
|
case "Other (V)":
|
|
return Math.round(value * voltageScaling * 100) / 100;
|
|
default:
|
|
console.log("Unknown sensor: " + sensor);
|
|
return 0;
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_button(robot, button)',
|
|
function (robot, button) {
|
|
const type = window.birdbrain.robotType[robot];
|
|
const index = (type == window.birdbrain.robotType.FINCH) ? 16 : 7;
|
|
var buttonState = window.birdbrain.sensorData[robot][index] & 0xF0; //Button Byte position = 7, clear LS Bits as it is for shake and calibrate
|
|
|
|
switch (button) {
|
|
case 'A':
|
|
return (buttonState == 0x00 || buttonState == 0x20)
|
|
case 'B':
|
|
return (buttonState == 0x00 || buttonState == 0x10)
|
|
case 'Logo (V2)':
|
|
if(window.birdbrain.microbitIsV2[robot]) {
|
|
return (((window.birdbrain.sensorData[robot][index] >> 1) & 0x1) == 0x0)
|
|
} else {
|
|
return "micro:bit V2 required";
|
|
}
|
|
default:
|
|
console.log("unknown button " + button);
|
|
return false;
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_compass(robot)',
|
|
function (robot) {
|
|
const ax = window.birdbrain.getMicrobitAcceleration('X', robot);
|
|
const ay = window.birdbrain.getMicrobitAcceleration('Y', robot);
|
|
const az = window.birdbrain.getMicrobitAcceleration('Z', robot);
|
|
const mx = window.birdbrain.getMicrobitMagnetometer('X', robot);
|
|
const my = window.birdbrain.getMicrobitMagnetometer('Y', robot);
|
|
const mz = window.birdbrain.getMicrobitMagnetometer('Z', robot);
|
|
|
|
const phi = Math.atan(-ay / az)
|
|
const theta = Math.atan(ax / (ay * Math.sin(phi) + az * Math.cos(phi)))
|
|
|
|
const xp = mx
|
|
const yp = my * Math.cos(phi) - mz * Math.sin(phi)
|
|
const zp = my * Math.sin(phi) + mz * Math.cos(phi)
|
|
|
|
const xpp = xp * Math.cos(theta) + zp * Math.sin(theta)
|
|
const ypp = yp
|
|
|
|
const angle = 180.0 + ((Math.atan2(xpp, ypp)) * (180 / Math.PI)) //convert result to degrees
|
|
|
|
return Math.round(angle)
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchaccelerometer(robot, dimension)',
|
|
function (robot, dim) {
|
|
let acc = window.birdbrain.getFinchAcceleration(dim, robot);
|
|
return Math.round(acc * 10) / 10;
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchcompass(robot)',
|
|
function (robot) {
|
|
const ax = window.birdbrain.getFinchAcceleration('X', robot);
|
|
const ay = window.birdbrain.getFinchAcceleration('Y', robot);
|
|
const az = window.birdbrain.getFinchAcceleration('Z', robot);
|
|
const mx = window.birdbrain.getFinchMagnetometer('X', robot);
|
|
const my = window.birdbrain.getFinchMagnetometer('Y', robot);
|
|
const mz = window.birdbrain.getFinchMagnetometer('Z', robot);
|
|
|
|
const phi = Math.atan(-ay / az)
|
|
const theta = Math.atan(ax / (ay * Math.sin(phi) + az * Math.cos(phi)))
|
|
|
|
const xp = mx
|
|
const yp = my * Math.cos(phi) - mz * Math.sin(phi)
|
|
const zp = my * Math.sin(phi) + mz * Math.cos(phi)
|
|
|
|
const xpp = xp * Math.cos(theta) + zp * Math.sin(theta)
|
|
const ypp = yp
|
|
|
|
const angle = 180.0 + ((Math.atan2(xpp, ypp)) * (180 / Math.PI)) //convert result to degrees
|
|
|
|
return ((Math.round(angle) + 180) % 360) //turn so that beak points north
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchdistance(robot)',
|
|
function (robot) {
|
|
if (window.birdbrain.microbitIsV2[robot]) {
|
|
return window.birdbrain.sensorData[robot][1];
|
|
} else {
|
|
const cmPerDistance = 0.0919;
|
|
const msb = window.birdbrain.sensorData[robot][0];
|
|
const lsb = window.birdbrain.sensorData[robot][1];
|
|
|
|
const distance = msb << 8 | lsb;
|
|
return Math.round(distance * cmPerDistance);
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchencoder(robot, port)',
|
|
function (robot, port) {
|
|
let TICKS_PER_ROTATION = 792
|
|
var msb = 0;
|
|
var ssb = 0;
|
|
var lsb = 0;
|
|
switch (port) {
|
|
case 'Right':
|
|
msb = window.birdbrain.sensorData[robot][10];
|
|
ssb = window.birdbrain.sensorData[robot][11];
|
|
lsb = window.birdbrain.sensorData[robot][12];
|
|
break;
|
|
case 'Left':
|
|
msb = window.birdbrain.sensorData[robot][7];
|
|
ssb = window.birdbrain.sensorData[robot][8];
|
|
lsb = window.birdbrain.sensorData[robot][9];
|
|
break;
|
|
default:
|
|
console.log("unknown encoder port " + port);
|
|
}
|
|
var encoder = msb << 16 | ssb << 8 | lsb
|
|
if (encoder >= 0x800000) {
|
|
encoder = encoder | 0xFF000000;
|
|
}
|
|
return Math.round( encoder * 10 / TICKS_PER_ROTATION ) / 10
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchencoderreset(robot)',
|
|
function (robot) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "resetEncoders"
|
|
}
|
|
window.birdbrain.sendCommand(thisCommand)
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchlight(robot, port)',
|
|
function (robot, port) {
|
|
const beak = window.birdbrain.currentBeak[robot] || [0,0,0];
|
|
const R = beak[0]*100/255;
|
|
const G = beak[1]*100/255;
|
|
const B = beak[2]*100/255;
|
|
var raw = 0;
|
|
var correction = 0;
|
|
switch (port) {
|
|
case 'Right':
|
|
raw = window.birdbrain.sensorData[robot][3];
|
|
correction = 6.40473070e-03*R + 1.41015162e-02*G + 5.05547817e-02*B + 3.98301391e-04*R*G + 4.41091223e-04*R*B + 6.40756862e-04*G*B + -4.76971242e-06*R*G*B;
|
|
break;
|
|
case 'Left':
|
|
raw = window.birdbrain.sensorData[robot][2];
|
|
correction = 1.06871493e-02*R + 1.94526614e-02*G + 6.12409825e-02*B + 4.01343475e-04*R*G + 4.25761981e-04*R*B + 6.46091068e-04*G*B + -4.41056971e-06*R*G*B;
|
|
break;
|
|
default:
|
|
console.log("unknown light port " + port);
|
|
return 0;
|
|
}
|
|
|
|
return Math.round(Math.max(0, Math.min(100, (raw - correction))));
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchline(robot, port)',
|
|
function (robot, port) {
|
|
var rawVal = 0;
|
|
switch (port) {
|
|
case 'Right':
|
|
rawVal = window.birdbrain.sensorData[robot][5];
|
|
break;
|
|
case 'Left':
|
|
rawVal = window.birdbrain.sensorData[robot][4];
|
|
//first bit is for position control
|
|
rawVal = (0x7F & rawVal)
|
|
break;
|
|
default:
|
|
console.log("unknown line port " + port);
|
|
}
|
|
var returnVal = 100 - ((rawVal - 6) * 100/121);
|
|
return Math.min(100, Math.max(0, Math.round(returnVal)));
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchmagnetometer(robot, dimension)',
|
|
function (robot, dim) {
|
|
return window.birdbrain.getFinchMagnetometer(dim, robot);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_finchorientation(robot, dimension)',
|
|
function (robot, dim) {
|
|
if (dim == "Shake") {
|
|
let shake = window.birdbrain.sensorData[robot][16];
|
|
return ((shake & 0x01) > 0);
|
|
}
|
|
const threshold = 7.848;
|
|
let acceleration = 0;
|
|
switch(dim) {
|
|
case "Tilt Left":
|
|
case "Tilt Right":
|
|
acceleration = window.birdbrain.getFinchAcceleration('X', robot);
|
|
break;
|
|
case "Beak Up":
|
|
case "Beak Down":
|
|
acceleration = window.birdbrain.getFinchAcceleration('Y', robot);
|
|
break;
|
|
case "Level":
|
|
case "Upside Down":
|
|
acceleration = window.birdbrain.getFinchAcceleration('Z', robot);
|
|
break;
|
|
}
|
|
switch(dim) {
|
|
case "Tilt Right":
|
|
case "Beak Up":
|
|
case "Upside Down":
|
|
return (acceleration > threshold);
|
|
case "Tilt Left":
|
|
case "Beak Down":
|
|
case "Level":
|
|
return (acceleration < -threshold);
|
|
}
|
|
|
|
console.log("Unknown dimension " + dim);
|
|
return false;
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_magnetometer(robot, dimension)',
|
|
function (robot, dim) {
|
|
return window.birdbrain.getMicrobitMagnetometer(dim, robot);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_orientation(robot, dimension)',
|
|
function (robot, dim) {
|
|
if (dim == "Shake") {
|
|
const index = 7;
|
|
let shake = window.birdbrain.sensorData[robot][index];
|
|
return ((shake & 0x01) > 0);
|
|
}
|
|
const threshold = 7.848;
|
|
let acceleration = 0;
|
|
switch(dim) {
|
|
case "Tilt Left":
|
|
case "Tilt Right":
|
|
acceleration = window.birdbrain.getMicrobitAcceleration('X', robot);
|
|
break;
|
|
case "Logo Up":
|
|
case "Logo Down":
|
|
acceleration = window.birdbrain.getMicrobitAcceleration('Y', robot);
|
|
break;
|
|
case "Screen Up":
|
|
case "Screen Down":
|
|
acceleration = window.birdbrain.getMicrobitAcceleration('Z', robot);
|
|
break;
|
|
}
|
|
switch(dim) {
|
|
case "Tilt Left":
|
|
case "Logo Down":
|
|
case "Screen Down":
|
|
return (acceleration > threshold);
|
|
case "Tilt Right":
|
|
case "Logo Up":
|
|
case "Screen Up":
|
|
return (acceleration < -threshold);
|
|
}
|
|
|
|
console.log("Unknown dimension " + dim);
|
|
return false;
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_sound(robot)',
|
|
function (robot) {
|
|
if (window.birdbrain.microbitIsV2[robot]) {
|
|
const type = window.birdbrain.robotType[robot];
|
|
if (type == window.birdbrain.robotType.FINCH) {
|
|
return window.birdbrain.sensorData[robot][0];
|
|
} else {
|
|
return window.birdbrain.sensorData[robot][14];
|
|
}
|
|
} else {
|
|
return "micro:bit V2 required"
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_temperature(robot)',
|
|
function (robot) {
|
|
if (window.birdbrain.microbitIsV2[robot]) {
|
|
const type = window.birdbrain.robotType[robot];
|
|
if (type == window.birdbrain.robotType.FINCH) {
|
|
return (window.birdbrain.sensorData[robot][6] >> 2);
|
|
} else {
|
|
return window.birdbrain.sensorData[robot][15];
|
|
}
|
|
} else {
|
|
return "micro:bit V2 required"
|
|
}
|
|
}
|
|
);
|
|
|
|
//// GlowBoard Blocks ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_gbbutton(robot, button)',
|
|
function (robot, button) {
|
|
var buttonState = window.birdbrain.sensorData[robot][5] & 0xF0; //Button Byte position = 7, clear LS Bits as it is for shake and calibrate
|
|
|
|
switch (button) {
|
|
case 'right':
|
|
return (buttonState == 0x00 || buttonState == 0x20)
|
|
case 'left':
|
|
return (buttonState == 0x00 || buttonState == 0x10)
|
|
default:
|
|
console.log("unknown button " + button);
|
|
return false;
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_gbdial(robot, dial)',
|
|
function (robot, sensor) {
|
|
let index = 1
|
|
if (sensor == "Right") { index = 3 }
|
|
const msb = window.birdbrain.sensorData[robot][index];
|
|
const lsb = window.birdbrain.sensorData[robot][index + 1];
|
|
const value = msb << 8 | lsb;
|
|
return value;
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_gbdisplay(robot, color, brightness, symbol)',
|
|
function (robot, color, brightness, symbolString) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "glowboard",
|
|
color: color,
|
|
brightness: brightness,
|
|
symbolString: symbolString
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_gbsetpoint(robot, X, Y, color, brightness)',
|
|
function (robot, xPos, yPos, color, brightness) {
|
|
var thisCommand = {
|
|
robot: robot,
|
|
cmd: "setPoint",
|
|
xPos: Math.round(Math.max(Math.min(xPos, 12), 1)),
|
|
yPos: Math.round(Math.max(Math.min(yPos, 12), 1)),
|
|
color: color,
|
|
brightness: brightness
|
|
}
|
|
|
|
window.birdbrain.sendCommand(thisCommand);
|
|
}
|
|
);
|
|
|
|
//// Blocks for old style robots ////
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyled(port, intensity)',
|
|
function (portnum, intensitynum) {
|
|
var realPort = portnum-1;
|
|
var realIntensity = Math.floor(intensitynum*2.55);
|
|
|
|
var report = {
|
|
message:"L".charCodeAt(0),
|
|
port: realPort.toString().charCodeAt(0),
|
|
intensity: realIntensity
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacytriled(port, red, green, blue)',
|
|
function (portnum, rednum, greennum, bluenum) {
|
|
var realPort = portnum-1;
|
|
var realIntensities = [rednum, greennum, bluenum].map(function(intensity) {
|
|
return Math.floor(Math.max(Math.min(intensity*2.55, 255), 0));
|
|
});
|
|
|
|
var report = {
|
|
message:"O".charCodeAt(0),
|
|
port: realPort.toString().charCodeAt(0),
|
|
red: realIntensities[0],
|
|
green: realIntensities[1],
|
|
blue: realIntensities[2]
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyservo(port, position)',
|
|
function (portnum, ang) {
|
|
var realPort = portnum-1;
|
|
var realAngle = Math.floor(ang*1.25);
|
|
realAngle = Math.max(Math.min(realAngle,225.0),0.0);
|
|
|
|
var report = {
|
|
message: "S".charCodeAt(0),
|
|
port: realPort.toString().charCodeAt(0),
|
|
angle: realAngle
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacymotor(port, speed)',
|
|
function (portnum, velocity) {
|
|
var realPort = portnum-1;
|
|
var realVelocity = Math.floor(velocity*2.55);
|
|
realVelocity = Math.max(Math.min(realVelocity,255), -255);
|
|
|
|
var report = {
|
|
message: "M".charCodeAt(0),
|
|
port: realPort.toString().charCodeAt(0),
|
|
direction: (realVelocity < 0 ? 1 : 0).toString().charCodeAt(0),
|
|
velocity: Math.abs(realVelocity)
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyvibration(port, intensity)',
|
|
function (portnum, intensitynum) {
|
|
var realPort = portnum-1;
|
|
var realIntensity = Math.floor(intensitynum*2.55);
|
|
realIntensity = Math.max(Math.min(realIntensity,255.0),0.0);
|
|
|
|
var report = {
|
|
message: "V".charCodeAt(0),
|
|
port: realPort.toString().charCodeAt(0),
|
|
intensity: realIntensity
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacysaythis(phrase)',
|
|
function (phrase) {
|
|
var report = { message: "SPEAK", val: phrase};
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyhbsensor(sensor, port)',
|
|
function (sensor, port) {
|
|
var realport = port - 1;
|
|
var sensorvalue = window.bbtLegacy.sensorData[realport]
|
|
|
|
switch(sensor) {
|
|
case "Light":
|
|
return parseInt(sensorvalue / 2.55);
|
|
case "Temperature": //Celsius
|
|
return Math.floor(((sensorvalue-127)/2.4+25)*100/100);
|
|
case "Distance": //cm
|
|
var reading = sensorvalue*4;
|
|
if (reading < 130) {
|
|
sensorvalue = 100;
|
|
} else { //formula based on mathematical regression
|
|
reading = reading - 120;
|
|
var distance;
|
|
if (reading > 680) {
|
|
distance = 5.0;
|
|
} else {
|
|
var sensor_val_square = reading*reading;
|
|
distance = sensor_val_square*sensor_val_square*reading*-0.000000000004789
|
|
+ sensor_val_square*sensor_val_square*0.000000010057143
|
|
- sensor_val_square*reading*0.000008279033021
|
|
+ sensor_val_square*0.003416264518201
|
|
- reading*0.756893112198934
|
|
+ 90.707167605683000;
|
|
}
|
|
sensorvalue = parseInt(distance);
|
|
}
|
|
return sensorvalue;
|
|
case "Dial":
|
|
return parseInt(sensorvalue / 2.55);
|
|
case "Sound":
|
|
if (sensorvalue > 14) {
|
|
return (sensorvalue - 15) * 3/2
|
|
} else {
|
|
return 0
|
|
}
|
|
case "Raw":
|
|
return parseInt(sensorvalue / 2.55);
|
|
default:
|
|
console.log("Unknown sensor: " + sensor);
|
|
return 0;
|
|
}
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyfinchmove(left, right)',
|
|
function (left, right) {
|
|
function constrain(n) {
|
|
return Math.max(Math.min(n, 255), -255);
|
|
}
|
|
var speeds = [constrain(Math.round(left * 2.55)), constrain(Math.round(right * 2.55))];
|
|
|
|
var report = {
|
|
message: "M".charCodeAt(0),
|
|
leftDirection: speeds[0] < 0 ? 1 : 0,
|
|
leftSpeed: Math.abs(speeds[0]),
|
|
rightDirection: speeds[1] < 0 ? 1 : 0,
|
|
rightSpeed: Math.abs(speeds[1]),
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyfinchled(red, green, blue)',
|
|
function (red, green, blue) {
|
|
// constrain n to the range [0..255]
|
|
function constrain(n) {
|
|
return Math.max(Math.min(n, 255), 0);
|
|
}
|
|
|
|
var values = [constrain(Math.round(red * 2.55)), constrain(Math.round(green * 2.55)), constrain(Math.round(blue * 2.55))];
|
|
|
|
var report = {
|
|
message: "O".charCodeAt(0),
|
|
red: values[0],
|
|
green: values[1],
|
|
blue: values[2]
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyfinchbuzzer(frequency, duration)',
|
|
function (freq, time) {
|
|
//constrain n to the range [0..65535]
|
|
function constrain(n) {
|
|
return Math.max(Math.min(n, 0xFFFF), 0);
|
|
}
|
|
var value = {
|
|
freq: constrain(Math.round(freq)),
|
|
time: constrain(Math.round(time))
|
|
};
|
|
|
|
var report = {
|
|
message: "B".charCodeAt(0),
|
|
timeHigh: value.time >> 8, // Since the report must be in bytes
|
|
timeLow: value.time & 0xFF, // and these values are bigger than a byte
|
|
freqHigh: value.freq >> 8, // they are split into two bytes
|
|
freqLow: value.freq & 0xFF
|
|
};
|
|
|
|
window.birdbrain.sendCommand( report );
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyfinchsensor(port)',
|
|
function (port) {
|
|
//Ports: Left Light = 0; Right Light = 1;
|
|
// Acceleration (X, Y, Z) = (2, 3, 4);
|
|
// Left Obstacle = 5; Right Obstacle = 6;
|
|
// Temperature C = 7;
|
|
return window.bbtLegacy.sensorData[port];
|
|
}
|
|
);
|
|
|
|
SnapExtensions.primitives.set(
|
|
'bbt_legacyfinchorientation()',
|
|
function () {
|
|
var acceleration = Array(3);
|
|
acceleration[0] = window.bbtLegacy.sensorData[2]
|
|
acceleration[1] = window.bbtLegacy.sensorData[3]
|
|
acceleration[2] = window.bbtLegacy.sensorData[4]
|
|
|
|
var orientation;
|
|
|
|
if(acceleration[0] > -0.5 && acceleration[0] < 0.5 && acceleration[1] < 0.5 && acceleration[1] > -0.5 && acceleration[2] > 0.65 && acceleration[2] < 1.5)
|
|
orientation = "level";
|
|
else if(acceleration[0] > -0.5 && acceleration[0] < 0.5 && acceleration[1] < 0.5 && acceleration[1] > -0.5 && acceleration[2] > -1.5 && acceleration[2] < -0.65)
|
|
orientation = "upside down";
|
|
else if(acceleration[0] < 1.5 && acceleration[0] > 0.8 && acceleration[1] > -0.3 && acceleration[1] < 0.3 && acceleration[2] > -0.3 && acceleration[2] < 0.3)
|
|
orientation = "beak down";
|
|
else if(acceleration[0] < -0.8 && acceleration[0] > -1.5 && acceleration[1] > -0.3 && acceleration[1] < 0.3 && acceleration[2] > -0.3 && acceleration[2] < 0.3)
|
|
orientation = "beak up";
|
|
else if(acceleration[0] > -0.5 && acceleration[0] < 0.5 && acceleration[1] > 0.7 && acceleration[1] < 1.5 && acceleration[2] > -0.5 && acceleration[2] < 0.5)
|
|
orientation = "left wing down";
|
|
else if(acceleration[0] > -0.5 && acceleration[0] < 0.5 && acceleration[1] > -1.5 && acceleration[1] < -0.7 && acceleration[2] > -0.5 && acceleration[2] < 0.5)
|
|
orientation = "right wing down";
|
|
else
|
|
orientation = "in between";
|
|
|
|
return orientation
|
|
}
|
|
);
|