Compare commits

..

7 Commits

Author SHA1 Message Date
280963d1eb 0.0.67 2018-01-15 23:58:31 -08:00
9fadf49b0e Support for multiple motors in "used" logic. (#238)
* handle registerion of dual / single motors

* updated puppy
2018-01-15 23:57:21 -08:00
3c2be25384 some core set adapted codes 2018-01-15 21:27:19 -08:00
e1f623a94d Added description to timers 2018-01-15 03:41:14 -08:00
cb5f9648f5 fixed sound name 2018-01-14 19:49:40 -08:00
9158cfe4f6 0.0.66 2018-01-13 08:31:38 -08:00
0b763978f2 gyro boy improvements (#236)
gyro boy improvements
2018-01-13 08:31:10 -08:00
21 changed files with 1096 additions and 69 deletions

View File

@ -0,0 +1,215 @@
# Gyroboy LabView
```typescript
let mSum = 0;
let mPos = 0;
let mSpd = 0;
let mD = 0;
let mDP1 = 0;
let mDP2 = 0;
let mDP3 = 0;
let Crdv = 0;
let cLo = 0;
let gAng = 0;
let ok = false;
let pwr = 0;
let Cstr = 0;
let Cdrv = 0;
let gMn = 0;
let gMx = 0;
let gSum = 0;
let gyro = 0;
let gOS = 0;
let gSpd = 0;
let tInt = 0.014;
let lpwr = 0
let rpwr = 0
let tStart = 0
let st = 0
let oldDr = 0
function RST() {
motors.largeA.reset()
motors.largeD.reset()
motors.largeA.setRegulated(false)
motors.largeD.setRegulated(false)
sensors.gyro2.reset()
sensors.gyro2.rate()
control.timer2.reset()
loops.pause(5000)
mSum = 0;
mPos = 0;
mD = 0;
mDP1 = 0;
mDP2 = 0;
mDP3 = 0;
Crdv = 0;
cLo = 0;
gAng = 0;
ok = false;
pwr = 0;
st = 0;
Cstr = 0;
Cdrv = 0;
}
function OS() {
// OSL
do {
gMn = 1000;
gMx = -100;
gSum = 0;
// gChk
for (let i = 0; i < 200; i++) {
gyro = sensors.gyro2.rate()
gSum = gyro;
gMx = Math.max(gMx, gyro)
gMn = Math.min(gMn, gyro)
loops.pause(4);
}
} while (gMx - gMn > 2);
gOS = gSum / 200;
}
function GT() {
if (cLo == 0) {
tInt = 0.014;
control.timer1.reset();
} else {
tInt = control.timer1.seconds() / cLo;
}
cLo++;
}
function GG() {
gyro = sensors.gyro2.rate();
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
gSpd = gyro - gOS;
gAng = gAng + tInt * gSpd;
}
function GM() {
let temp = mSum
mSum = motors.largeD.angle() + motors.largeA.angle();
mD = mSum - temp;
mPos = mPos + mD;
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
mDP3 = mDP2;
mDP2 = mDP1;
mDP1 = mD;
}
function EQ() {
mPos = mPos - Cdrv * tInt;
pwr = (0.8 * gSpd + 15 * gAng) + (0.08 * mSpd + 0.12 * mPos) - 0.01 * Cdrv
if (pwr > 100) pwr = 100
else if (pwr < -100) pwr = -100
}
function cntrl() {
mPos = mPos - tInt * Cdrv
lpwr = (pwr + Cstr * 0.1)
rpwr = (pwr - Cstr * 0.1)
}
function CHK() {
if (Math.abs(pwr) < 100)
control.timer2.reset();
if (control.timer2.seconds() > 2) {
ok = true;
}
}
// M
loops.forever(function () {
RST();
brick.showImage(images.eyesSleeping)
OS()
gAng = -0.25;
music.playSoundEffect(sounds.movementsSpeedUp)
brick.showImage(images.eyesAwake)
st = 1;
// BALANCE
while (!ok) {
GT();
let t1 = control.timer1.millis()
GG();
GM();
EQ();
cntrl();
motors.largeA.setSpeed(lpwr)
motors.largeD.setSpeed(rpwr)
CHK()
let t2 = control.timer1.millis();
let p = 5 - (t2 - t1);
loops.pause(Math.max(1, p))
}
motors.stopAllMotors()
st = 0;
brick.setLight(BrickLight.RedPulse);
brick.showImage(images.eyesKnockedOut)
music.playSoundEffect(sounds.movementsSpeedDown)
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
brick.setLight(BrickLight.Off);
})
// BHV
loops.forever(function () {
switch (st) {
case 0:
Cdrv = 0;
Cstr = 0;
break;
case 1:
Cdrv = 40;
loops.pause(4000);
Cdrv = 0;
music.playTone(1000, 100);
st = 2;
break;
case 2:
switch (sensors.color1.color()) {
case ColorSensorColor.Red:
music.playTone(2000, 100);
Cdrv = 0;
Cstr = 0;
break;
case ColorSensorColor.Green:
music.playTone(2000, 100);
Cdrv = 150;
Cstr = 0;
break;
case ColorSensorColor.Blue:
music.playTone(2000, 100);
Cstr = 70;
break;
case ColorSensorColor.Yellow:
music.playTone(2000, 100);
Cstr = -70;
break;
case ColorSensorColor.White:
music.playTone(2000, 100);
Cdrv = -75;
break;
}
if (sensors.ultrasonic4.distance() < 25) {
Cstr = 0;
oldDr = Cdrv;
Cdrv = -10;
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
if (Math.randomRange(-1, 1) >= 1)
Cstr = 70;
else
Cstr = -70;
loops.pause(4000);
music.playTone(2000, 100)
Cstr = 0;
Cdrv = oldDr;
}
break;
}
loops.pause(80);
})
```

View File

@ -0,0 +1,390 @@
# Puppy
```typescript
let P_T = 0;
let ISS = 0;
let F_T = 0;
let P_C = 0;
let F_C = 0;
let DB_S = 0;
let NS = false;
let IBP = 0;
let IAP = 0;
let C = false;
let TC = false;
let OTC = false;
let COL = 0;
let OCOL = 0;
let _C = false;
let GTO = 0;
function DN() {
motors.largeAD.setBrake(true);
motors.largeAD.tank(50, 50, 1, MoveUnit.Seconds);
loops.pause(100);
motors.largeA.clearCounts()
motors.largeD.clearCounts()
}
function MNRH() {
motors.mediumC.setBrake(true)
brick.showImage(images.legoEv3icon)
brick.setLight(BrickLight.OrangePulse)
while (!brick.buttonEnter.wasPressed()) {
if (brick.buttonUp.wasPressed()) {
motors.mediumC.setSpeed(-100);
} else if (brick.buttonDown.wasPressed()) {
motors.mediumC.setSpeed(100);
} else {
motors.mediumC.stop();
}
}
motors.mediumC.stop();
motors.mediumC.clearCounts();
brick.setLight(BrickLight.Green);
}
function IS(t: number) {
ISS = t;
switch (t) {
case 0:
brick.showImage(images.eyesNeutral);
break;
case 1:
brick.showImage(images.eyesSleeping);
break;
case 2:
brick.showImage(images.eyesTear);
// draw rect...
break;
case 3:
brick.showImage(images.eyesHurt);
break;
case 4:
brick.showImage(images.eyesAngry);
break;
case 5:
brick.showImage(images.eyesTiredMiddle);
break;
case 6:
brick.showImage(images.eyesTiredRight);
break;
case 7:
brick.showImage(images.eyesTiredLeft);
break;
case 8:
brick.showImage(images.eyesLove);
break;
}
}
function UP() {
if (motors.largeA.angle() > -50) {
control.runInBackground(function () {
motors.largeD.clearCounts()
motors.largeD.setSpeed(-35);
pauseUntil(() => motors.largeD.angle() < -25);
motors.largeD.stop();
motors.largeD.setRegulated(false)
motors.largeD.setSpeed(-15)
pauseUntil(() => motors.largeD.angle() < -65);
motors.largeD.stop();
})
motors.largeA.clearCounts()
motors.largeA.setSpeed(-35);
pauseUntil(() => motors.largeA.angle() < -25);
motors.largeA.stop();
motors.largeA.setRegulated(false)
motors.largeA.setSpeed(-15)
pauseUntil(() => motors.largeA.angle() < -65);
motors.largeA.stop();
loops.pause(500);
}
}
function RST() {
P_T = Math.randomRange(3, 6);
F_T = Math.randomRange(2, 4);
P_C = 1;
F_C = 1;
control.timer1.reset();
control.timer2.reset();
control.timer3.reset();
CS(0);
}
function CS(db: number) {
if (DB_S != db) {
DB_S = db;
NS = true;
}
}
function MON() {
if (control.timer2.seconds() > 10) {
control.timer2.reset();
P_C--;
if (P_C < 0) {
P_C = 0;
}
}
if (control.timer1.seconds() > 20) {
control.timer1.reset()
F_C--;
if (F_C < 0) {
F_C = 0;
}
}
if (control.timer3.seconds() > 30) {
control.timer3.reset();
CS(1);
}
}
function UIS() {
if (control.timer5.seconds() > IBP) {
control.timer5.reset();
if (ISS == 1) {
ISS = 6;
IBP = Math.randomRange(1, 5);
} else {
ISS = 1;
IBP = 0.25;
}
IS(ISS);
}
if (control.timer6.seconds() > IAP) {
if (ISS != 1) {
control.timer6.reset();
IAP = Math.randomRange(1, 10)
if (ISS != 7) {
ISS = 7
} else {
ISS = 6;
}
IS(ISS);
}
}
}
function UPDB() {
if ((P_T == P_C) && (F_T == F_C)) {
CS(6);
}
if ((P_T > P_C) && (F_T < F_C)) {
CS(3);
}
if ((P_T < P_C) && (F_T > F_C)) {
CS(5);
}
if ((P_C == 0) && (F_C > 0)) {
CS(2)
}
if (F_C == 0) {
CS(4)
}
}
function PTC() {
C = false;
OTC = TC;
TC = sensors.touch1.isPressed()
if (TC != OTC && TC) {
P_C++;
control.timer3.reset();
if (DB_S != 4) {
IS(2);
music.playSoundEffect(sounds.animalsDogSniff);
C = true;
}
}
return C;
}
function FDC() {
OCOL = COL;
COL = sensors.color4.color();
_C = false;
if ((COL != 0) && (OCOL != COL)) {
F_C++;
_C = true;
control.timer3.reset();
IS(2);
music.playSoundEffect(sounds.expressionsCrunching)
}
return _C;
}
function IDL() {
if (NS) {
NS = false;
UP();
}
UIS();
UPDB();
PTC();
FDC();
}
function MHT(Pos: number) {
let _R = Pos - motors.mediumC.angle();
if (_R >= 0) {
motors.mediumC.setSpeed(100, _R, MoveUnit.Degrees);
} else {
motors.mediumC.setSpeed(-100, Math.abs(_R), MoveUnit.Degrees);
}
}
function SLP() {
if (NS) {
NS = false;
IS(5)
DN()
MHT(3000)
IS(1)
music.playSoundEffect(sounds.expressionsSnoring)
}
if (sensors.touch1.isPressed() || brick.buttonEnter.isPressed()) {
music.stopAllSounds();
control.timer3.reset();
CS(7);
}
}
function PLF() {
if (NS) {
NS = false
IS(0)
UP()
music.playSoundEffect(sounds.animalsDogBark2)
control.timer4.reset()
GTO = Math.randomRange(4, 8);
}
if(PTC()) {
CS(0);
}
if (control.timer4.seconds() > GTO) {
music.playSoundEffect(sounds.animalsDogBark2)
control.timer4.reset();
GTO = Math.randomRange(4, 8);
}
}
function NGR() {
NS = false
IS(4)
music.playSoundEffect(sounds.animalsDogGrowl);
UP();
loops.pause(1500);
music.stopAllSounds()
music.playSoundEffect(sounds.animalsDogBark1)
P_C--;
CS(0);
}
function HNG() {
if (NS) {
NS = false;
IS(3)
DN();
music.playSoundEffect(sounds.animalsDogWhine);
}
if(FDC()) {
CS(0)
}
if (PTC()) {
CS(3);
}
}
function PPP() {
NS = false;
IS(2);
UP();
loops.pause(100)
motors.largeA.setSpeed(-30, 70, MoveUnit.Degrees);
loops.pause(800);
music.playSoundEffect(sounds.mechanicalHorn1);
loops.pause(1000);
for(let i = 0; i < 3; ++i) {
motors.largeA.setSpeed(-30, 20, MoveUnit.Degrees);
motors.largeA.setSpeed(30, 20, MoveUnit.Degrees);
}
motors.largeA.setSpeed(30, 70, MoveUnit.Degrees);
F_C = 1;
CS(0);
}
function HPY() {
IS(8)
MHT(0);
motors.largeAD.setSpeed(10, 0.8, MoveUnit.Seconds);
for(let i = 0; i < 3; ++i) {
music.playSoundEffect(sounds.animalsDogBark1);
motors.largeAD.setSpeed(-100, 0.2, MoveUnit.Seconds);
loops.pause(300)
motors.largeAD.setSpeed(10, 0.3, MoveUnit.Seconds)
}
loops.pause(500);
music.stopAllSounds();
DN();
RST();
}
function STL() {
UP();
motors.largeAD.setSpeed(-20, 60, MoveUnit.Degrees);
music.playSoundEffect(sounds.animalsDogWhine);
motors.largeAD.setSpeed(20, 60, MoveUnit.Degrees);
}
function WKU() {
let stateC = false;
IS(5);
music.playSoundEffect(sounds.animalsDogWhine)
MHT(0)
DN()
STL()
loops.pause(1000);
UP()
CS(0;)
}
DN();
MNRH();
// compare button state???
IS(1);
UP();
RST();
loops.forever(function () {
MON();
switch (DB_S) {
case 0:
IDL();
break;
case 1:
SLP();
break;
case 2:
PLF();
break;
case 3:
NGR();
break;
case 4:
HNG();
break;
case 5:
PPP();
break;
case 6:
HPY();
break;
case 7:
WKU();
break;
}
})
```

View File

@ -0,0 +1,51 @@
# Robot Arm
```typescript
function INI() {
motors.largeB.setBrake(true)
motors.largeC.setBrake(true)
motors.mediumA.setBrake(true)
motors.largeB.setSpeed(-50)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
motors.largeC.setSpeed(50)
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
}
INI()
let down = false;
loops.forever(function () {
brick.showImage(images.informationQuestionMark)
brick.setLight(BrickLight.OrangePulse);
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
brick.setLight(BrickLight.Off)
music.playSoundEffect(sounds.mechanicalAirRelease)
brick.showImage(images.informationAccept)
if (down) {
brick.showImage(images.informationForward)
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
} else {
brick.showImage(images.informationBackward)
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
if (down) {
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
} else {
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop()
})
```

View File

@ -0,0 +1,51 @@
# Crane LabView
```blocks
function INI() {
motors.largeB.setBrake(true)
motors.largeC.setBrake(true)
motors.mediumA.setBrake(true)
motors.largeB.setSpeed(-50)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds);
motors.mediumA.setSpeed(-50, 90, MoveUnit.Degrees);
motors.largeC.setSpeed(50)
sensors.touch1.pauseUntil(TouchSensorEvent.Pressed);
motors.largeC.setSpeed(-50, 0.86, MoveUnit.Rotations);
}
INI()
let down = false;
loops.forever(function () {
brick.showImage(images.informationQuestionMark)
brick.setLight(BrickLight.OrangePulse);
pauseUntil(() => (down = brick.buttonDown.wasPressed()) || brick.buttonUp.wasPressed())
brick.setLight(BrickLight.Off)
music.playSoundEffect(sounds.mechanicalAirRelease)
brick.showImage(images.informationAccept)
if (down) {
brick.showImage(images.informationForward)
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
} else {
brick.showImage(images.informationBackward)
motors.largeC.setSpeed(-65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees)
motors.mediumA.setSpeed(30, 1, MoveUnit.Seconds)
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop();
if (down) {
motors.largeC.setSpeed(-65, 0.86, MoveUnit.Rotations);
} else {
motors.largeC.setSpeed(65, 0.85, MoveUnit.Rotations);
}
motors.largeB.setSpeed(20, 275, MoveUnit.Degrees);
motors.mediumA.setSpeed(-30, 90, MoveUnit.Degrees);
motors.largeB.setSpeed(-55)
pauseUntil(() => sensors.color3.light(LightIntensityMode.Reflected) > 25);
motors.largeB.stop()
})
```

View File

@ -0,0 +1,215 @@
# Gyro Boy LabView
```blocks
let mSum = 0;
let mPos = 0;
let mSpd = 0;
let mD = 0;
let mDP1 = 0;
let mDP2 = 0;
let mDP3 = 0;
let Crdv = 0;
let cLo = 0;
let gAng = 0;
let ok = false;
let pwr = 0;
let Cstr = 0;
let Cdrv = 0;
let gMn = 0;
let gMx = 0;
let gSum = 0;
let gyro = 0;
let gOS = 0;
let gSpd = 0;
let tInt = 0.014;
let lpwr = 0
let rpwr = 0
let tStart = 0
let st = 0
let oldDr = 0
function RST() {
motors.largeA.reset()
motors.largeD.reset()
motors.largeA.setRegulated(false)
motors.largeD.setRegulated(false)
sensors.gyro2.reset()
sensors.gyro2.rate()
control.timer2.reset()
loops.pause(5000)
mSum = 0;
mPos = 0;
mD = 0;
mDP1 = 0;
mDP2 = 0;
mDP3 = 0;
Crdv = 0;
cLo = 0;
gAng = 0;
ok = false;
pwr = 0;
st = 0;
Cstr = 0;
Cdrv = 0;
}
function OS() {
// OSL
do {
gMn = 1000;
gMx = -100;
gSum = 0;
// gChk
for (let i = 0; i < 200; i++) {
gyro = sensors.gyro2.rate()
gSum = gyro;
gMx = Math.max(gMx, gyro)
gMn = Math.min(gMn, gyro)
loops.pause(4);
}
} while (gMx - gMn > 2);
gOS = gSum / 200;
}
function GT() {
if (cLo == 0) {
tInt = 0.014;
control.timer1.reset();
} else {
tInt = control.timer1.seconds() / cLo;
}
cLo++;
}
function GG() {
gyro = sensors.gyro2.rate();
gOS = 0.0005 * gyro + (1 - 0.0005) * gOS
gSpd = gyro - gOS;
gAng = gAng + tInt * gSpd;
}
function GM() {
let temp = mSum
mSum = motors.largeD.angle() + motors.largeA.angle();
mD = mSum - temp;
mPos = mPos + mD;
mSpd = ((mDP1 + mDP2 + mDP3 + mD) / 4) / tInt;
mDP3 = mDP2;
mDP2 = mDP1;
mDP1 = mD;
}
function EQ() {
mPos = mPos - Cdrv * tInt;
pwr = (0.8 * gSpd + 15 * gAng) + (0.095 * mSpd + 0.13 * mPos) - 0.01 * Cdrv
if (pwr > 100) pwr = 100
else if (pwr < -100) pwr = -100
}
function cntrl() {
mPos = mPos - tInt * Cdrv
lpwr = (pwr + Cstr * 0.1)
rpwr = (pwr - Cstr * 0.1)
}
function CHK() {
if (Math.abs(pwr) < 100)
control.timer2.reset();
if (control.timer2.seconds() > 2) {
ok = true;
}
}
// M
loops.forever(function () {
RST();
brick.showImage(images.eyesSleeping)
OS()
gAng = -0.25;
music.playSoundEffect(sounds.movementsSpeedUp)
brick.showImage(images.eyesAwake)
st = 1;
// BALANCE
while (!ok) {
GT();
let t1 = control.timer1.millis()
GG();
GM();
EQ();
cntrl();
motors.largeA.setSpeed(lpwr)
motors.largeD.setSpeed(rpwr)
CHK()
let t2 = control.timer1.millis();
let p = 5 - (t2 - t1);
loops.pause(Math.max(1, p))
}
motors.stopAllMotors()
st = 0;
brick.setLight(BrickLight.RedPulse);
brick.showImage(images.eyesKnockedOut)
music.playSoundEffect(sounds.movementsSpeedDown)
sensors.touch3.pauseUntil(TouchSensorEvent.Pressed)
brick.setLight(BrickLight.Off);
})
// BHV
loops.forever(function () {
switch (st) {
case 0:
Cdrv = 0;
Cstr = 0;
break;
case 1:
Cdrv = 40;
loops.pause(4000);
Cdrv = 0;
music.playTone(1000, 100);
st = 2;
break;
case 2:
switch (sensors.color1.color()) {
case ColorSensorColor.Red:
music.playTone(2000, 100);
Cdrv = 0;
Cstr = 0;
break;
case ColorSensorColor.Green:
music.playTone(2000, 100);
Cdrv = 150;
Cstr = 0;
break;
case ColorSensorColor.Blue:
music.playTone(2000, 100);
Cstr = 70;
break;
case ColorSensorColor.Yellow:
music.playTone(2000, 100);
Cstr = -70;
break;
case ColorSensorColor.White:
music.playTone(2000, 100);
Cdrv = -75;
break;
}
if (sensors.ultrasonic4.distance() < 25) {
Cstr = 0;
oldDr = Cdrv;
Cdrv = -10;
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
motors.mediumC.setSpeed(-30, 60, MoveUnit.Degrees);
motors.mediumC.setSpeed(30, 30, MoveUnit.Degrees);
if (Math.randomRange(-1, 1) >= 1)
Cstr = 70;
else
Cstr = -70;
loops.pause(4000);
music.playTone(2000, 100)
Cstr = 0;
Cdrv = oldDr;
}
break;
}
loops.pause(80);
})
```

View File

@ -52,9 +52,12 @@
"console.logValue|param|value": "to write", "console.logValue|param|value": "to write",
"console.sendToScreen": "Sends the log messages to the brick screen and uses the brick up and down buttons to scroll.", "console.sendToScreen": "Sends the log messages to the brick screen and uses the brick up and down buttons to scroll.",
"control": "Program controls and events.", "control": "Program controls and events.",
"control.Timer.millis": "Gets the elapsed time in millis", "control.Timer": "A timer",
"control.Timer.millis": "Gets the elapsed time in millis since the last reset",
"control.Timer.pauseUntil": "Pauses until the timer reaches the given amount of milliseconds",
"control.Timer.pauseUntil|param|ms": "how long to pause for, eg: 5, 100, 200, 500, 1000, 2000",
"control.Timer.reset": "Resets the timer", "control.Timer.reset": "Resets the timer",
"control.Timer.seconds": "Gets the elapsed time in seconds", "control.Timer.seconds": "Gets the elapsed time in seconds since the last reset",
"control.allocateNotifyEvent": "Allocates the next user notification event", "control.allocateNotifyEvent": "Allocates the next user notification event",
"control.deviceFirmwareVersion": "Determine the version of system software currently running.", "control.deviceFirmwareVersion": "Determine the version of system software currently running.",
"control.dmesg": "Write data to DMESG debugging buffer.", "control.dmesg": "Write data to DMESG debugging buffer.",

View File

@ -48,6 +48,7 @@
"console.sendToScreen|block": "send console to screen", "console.sendToScreen|block": "send console to screen",
"console|block": "console", "console|block": "console",
"control.Timer.millis|block": "%timer|millis", "control.Timer.millis|block": "%timer|millis",
"control.Timer.pauseUntil|block": "%timer|pause until (ms) %ms",
"control.Timer.reset|block": "%timer|reset", "control.Timer.reset|block": "%timer|reset",
"control.Timer.seconds|block": "%timer|seconds", "control.Timer.seconds|block": "%timer|seconds",
"control.raiseEvent|block": "raise event|from %src|with value %value", "control.raiseEvent|block": "raise event|from %src|with value %value",

View File

@ -312,6 +312,7 @@ namespace sensors.internal {
reset() { reset() {
if (this.isActive()) uartReset(this._port); if (this.isActive()) uartReset(this._port);
this.realmode = 0;
} }
} }

View File

@ -1,4 +1,7 @@
namespace control { namespace control {
/**
* A timer
*/
//% fixedInstances //% fixedInstances
export class Timer { export class Timer {
start: number; start: number;
@ -8,7 +11,7 @@ namespace control {
} }
/** /**
* Gets the elapsed time in millis * Gets the elapsed time in millis since the last reset
*/ */
//% blockId=timerMillis block="%timer|millis" //% blockId=timerMillis block="%timer|millis"
millis(): number { millis(): number {
@ -16,7 +19,7 @@ namespace control {
} }
/** /**
* Gets the elapsed time in seconds * Gets the elapsed time in seconds since the last reset
*/ */
//% blockId=timerSeconds block="%timer|seconds" //% blockId=timerSeconds block="%timer|seconds"
seconds(): number { seconds(): number {
@ -30,6 +33,16 @@ namespace control {
reset() { reset() {
this.start = control.millis(); this.start = control.millis();
} }
/**
* Pauses until the timer reaches the given amount of milliseconds
* @param ms how long to pause for, eg: 5, 100, 200, 500, 1000, 2000
*/
//% blockId=timerPauseUntil block="%timer|pause until (ms) %ms"
pauseUntil(ms: number) {
const remaining = this.millis() - ms;
loops.pause(Math.max(0, remaining));
}
} }
//% whenUsed fixedInstance block="timer 1" //% whenUsed fixedInstance block="timer 1"

View File

@ -3,6 +3,9 @@
"datalog.addValue": "Adds a cell to the row of data", "datalog.addValue": "Adds a cell to the row of data",
"datalog.addValue|param|name": "name of the cell, eg: \"x\"", "datalog.addValue|param|name": "name of the cell, eg: \"x\"",
"datalog.addValue|param|value": "value of the cell, eg: 0", "datalog.addValue|param|value": "value of the cell, eg: 0",
"datalog.flush": "Commits any buffered row to disk",
"datalog.setEnabled": "Turns on or off datalogging",
"datalog.setFile": "Starts a new data logger for the given file", "datalog.setFile": "Starts a new data logger for the given file",
"datalog.setFile|param|filename": "the filename, eg: \"datalog.csv\"",
"datalog.setStorage": "* @param storage custom storage solution" "datalog.setStorage": "* @param storage custom storage solution"
} }

View File

@ -1,6 +1,7 @@
{ {
"datalog.addRow|block": "datalog add row", "datalog.addRow|block": "datalog add row",
"datalog.addValue|block": "datalog add %name|=%value", "datalog.addValue|block": "datalog add %name|=%value",
"datalog.setEnabled|block": "datalog %enabled",
"datalog|block": "datalog", "datalog|block": "datalog",
"{id:category}Datalog": "Datalog" "{id:category}Datalog": "Datalog"
} }

View File

@ -3,13 +3,16 @@ namespace datalog {
let _headers: string[] = undefined; let _headers: string[] = undefined;
let _headersLength: number; let _headersLength: number;
let _values: number[]; let _values: number[];
let _buffer: string = "";
let _start: number; let _start: number;
let _filename = "data.csv"; let _filename = "datalog.csv";
let _storage: storage.Storage = storage.temporary; let _storage: storage.Storage = storage.temporary;
let _enabled = true;
function clear() { function clear() {
_headers = undefined; _headers = undefined;
_values = undefined; _values = undefined;
_buffer = "";
} }
function init() { function init() {
@ -31,7 +34,10 @@ namespace datalog {
_headersLength = _storage.size(_filename); _headersLength = _storage.size(_filename);
} }
// commit row data // commit row data
_storage.appendCSV(_filename, _values); _buffer += storage.toCSV(_values, _storage.csvSeparator);
// buffered writes
if (_buffer.length > 1024)
flush();
} }
// clear values // clear values
@ -44,6 +50,8 @@ namespace datalog {
//% weight=100 //% weight=100
//% blockId=datalogAddRow block="datalog add row" //% blockId=datalogAddRow block="datalog add row"
export function addRow(): void { export function addRow(): void {
if (!_enabled) return;
commit(); commit();
init(); init();
const s = (control.millis() - _start) / 1000; const s = (control.millis() - _start) / 1000;
@ -65,16 +73,16 @@ namespace datalog {
i = _headers.length - 1; i = _headers.length - 1;
} }
_values[i] = value; _values[i] = value;
if (i > 0) // 0 is time
console.logValue(name, value)
} }
/** /**
* Starts a new data logger for the given file * Starts a new data logger for the given file
* @param filename the filename, eg: "datalog.csv"
*/ */
//% //%
export function setFile(fn: string) { export function setFile(filename: string) {
_filename = fn; flush();
_filename = filename;
clear(); clear();
} }
@ -84,7 +92,31 @@ namespace datalog {
*/ */
//% //%
export function setStorage(storage: storage.Storage) { export function setStorage(storage: storage.Storage) {
flush();
_storage = storage; _storage = storage;
clear(); clear();
} }
/**
* Commits any buffered row to disk
*/
//%
export function flush() {
if (_buffer) {
const b = _buffer;
_buffer = "";
_storage.append(_filename, b);
}
}
/**
* Turns on or off datalogging
* @param enabled
*/
//% blockId=datalogEnabled block="datalog %enabled"
//% enabled.fieldEditor=fieldonoff
export function setEnabled(enabled: boolean) {
flush();
_enabled = enabled;
}
} }

View File

@ -1,5 +1,7 @@
{ {
"sensors.GyroSensor.angle": "Get the current angle from the gyroscope.", "sensors.GyroSensor.angle": "Get the current angle from the gyroscope.",
"sensors.GyroSensor.drift": "Gets the computed rate drift",
"sensors.GyroSensor.rate": "Get the current rotation rate from the gyroscope.", "sensors.GyroSensor.rate": "Get the current rotation rate from the gyroscope.",
"sensors.GyroSensor.reset": "Forces a calibration of the gyro. Must be called when the sensor is completely still." "sensors.GyroSensor.reset": "Forces a calibration of the gyro. Must be called when the sensor is completely still.",
"sensors.GyroSensor.setDriftCorrection": "Enables or disable drift correction"
} }

View File

@ -8,16 +8,27 @@ namespace sensors {
//% fixedInstances //% fixedInstances
export class GyroSensor extends internal.UartSensor { export class GyroSensor extends internal.UartSensor {
private calibrating: boolean; private calibrating: boolean;
private _drift: number;
private _drifting: boolean;
constructor(port: number) { constructor(port: number) {
super(port) super(port)
this.calibrating = false; this.calibrating = false;
this._drift = 0;
this._drifting = true;
this.setMode(GyroSensorMode.Rate);
} }
_deviceType() { _deviceType() {
return DAL.DEVICE_TYPE_GYRO return DAL.DEVICE_TYPE_GYRO
} }
_query(): number {
return this.getNumber(NumberFormat.Int16LE, 0);
}
setMode(m: GyroSensorMode) { setMode(m: GyroSensorMode) {
if (m == GyroSensorMode.Rate && this.mode != m)
this._drift = 0;
this._setMode(m) this._setMode(m)
} }
@ -37,8 +48,8 @@ namespace sensors {
if (this.calibrating) if (this.calibrating)
pauseUntil(() => !this.calibrating, 2000); pauseUntil(() => !this.calibrating, 2000);
this.setMode(GyroSensorMode.Angle) this.setMode(GyroSensorMode.Angle);
return this.getNumber(NumberFormat.Int16LE, 0) return this._query();
} }
/** /**
@ -57,8 +68,14 @@ namespace sensors {
if (this.calibrating) if (this.calibrating)
pauseUntil(() => !this.calibrating, 2000); pauseUntil(() => !this.calibrating, 2000);
this.setMode(GyroSensorMode.Rate) this.setMode(GyroSensorMode.Rate);
return this.getNumber(NumberFormat.Int16LE, 0) let curr = this._query();
if (Math.abs(curr) < 20) {
const p = 0.0005;
this._drift = (1 - p) * this._drift + p * curr;
curr -= this._drift;
}
return curr;
} }
/** /**
@ -76,23 +93,45 @@ namespace sensors {
if (this.calibrating) return; // already in calibration mode if (this.calibrating) return; // already in calibration mode
this.calibrating = true; this.calibrating = true;
// may be triggered by a button click, give time to settle // may be triggered by a button click,
loops.pause(500); // give time for robot to settle
loops.pause(700);
// send a reset command // send a reset command
super.reset(); super.reset();
// we need to switch mode twice to perform a calibration // switch back to the desired mode
if (this.mode == GyroSensorMode.Rate) this.setMode(this.mode);
this.setMode(GyroSensorMode.Angle); // wait till sensor is live
else pauseUntil(() => this.isActive());
this.setMode(GyroSensorMode.Rate); // give it a bit of time to init
// switch back and wait loops.pause(1000)
if (this.mode == GyroSensorMode.Rate) // compute drift
this.setMode(GyroSensorMode.Angle); this._drift = 0;
else if (this.mode == GyroSensorMode.Rate) {
this.setMode(GyroSensorMode.Rate); for (let i = 0; i < 200; ++i) {
// give it more time to settle this._drift += this._query();
loops.pause(500); loops.pause(4);
this.calibrating = false; }
this._drift /= 200;
}
// and we're done
this.calibrating = false;
}
/**
* Gets the computed rate drift
*/
//%
drift(): number {
return this._drift;
}
/**
* Enables or disable drift correction
* @param enabled
*/
//%
setDriftCorrection(enabled: boolean) {
this._drifting = enabled;
} }
} }

View File

@ -121,7 +121,7 @@
"sounds.mechanicalMotorStart|block": "mechanical motor start", "sounds.mechanicalMotorStart|block": "mechanical motor start",
"sounds.mechanicalMotorStop|block": "mechanical motor stop", "sounds.mechanicalMotorStop|block": "mechanical motor stop",
"sounds.mechanicalRatchet|block": "mechanical ratchet", "sounds.mechanicalRatchet|block": "mechanical ratchet",
"sounds.mechanicalSonar|block": "\"mechanical sonar\"", "sounds.mechanicalSonar|block": "mechanical sonar",
"sounds.mechanicalTickTack|block": "mechanical tick tack", "sounds.mechanicalTickTack|block": "mechanical tick tack",
"sounds.mechanicalWalk|block": "mechanical walk", "sounds.mechanicalWalk|block": "mechanical walk",
"sounds.movementsArm1|block": "movements arm1", "sounds.movementsArm1|block": "movements arm1",

View File

@ -175,7 +175,7 @@ namespace sounds {
export const mechanicalMotorStop = music.fromWAV(hex``); export const mechanicalMotorStop = music.fromWAV(hex``);
//% fixedInstance jres block="mechanical ratchet" //% fixedInstance jres block="mechanical ratchet"
export const mechanicalRatchet = music.fromWAV(hex``); export const mechanicalRatchet = music.fromWAV(hex``);
//% fixedInstance jres block='"mechanical sonar"' //% fixedInstance jres block="mechanical sonar"
export const mechanicalSonar = music.fromWAV(hex``); export const mechanicalSonar = music.fromWAV(hex``);
//% fixedInstance jres block="mechanical tick tack" //% fixedInstance jres block="mechanical tick tack"
export const mechanicalTickTack = music.fromWAV(hex``); export const mechanicalTickTack = music.fromWAV(hex``);

View File

@ -7,7 +7,7 @@ namespace storage {
//% fixedInstances //% fixedInstances
export class Storage { export class Storage {
csvSeparator: string; csvSeparator: string;
constructor() { constructor() {
this.csvSeparator = ","; this.csvSeparator = ",";
} }
@ -80,18 +80,13 @@ namespace storage {
} }
/** /**
* Append a row of CSV data * Append a row of CSV data
* @param filename the file name to append data, eg: "data.csv" * @param filename the file name to append data, eg: "data.csv"
* @param data the data to append * @param data the data to append
*/ */
//% blockId=storageAppendCSV block="storage %source|%filename|append CSV %data" //% blockId=storageAppendCSV block="storage %source|%filename|append CSV %data"
appendCSV(filename: string, data: number[]) { appendCSV(filename: string, data: number[]) {
let s = "" let s = toCSV(data, this.csvSeparator);
for (const d of data) {
if (s) s += this.csvSeparator;
s = s + d;
}
s += "\r\n"
this.append(filename, s) this.append(filename, s)
} }
@ -167,6 +162,16 @@ namespace storage {
} }
} }
export function toCSV(data: number[], sep: string) {
let s = ""
for (const d of data) {
if (s) s += sep;
s = s + d;
}
s += "\r\n"
return s;
}
class TemporaryStorage extends Storage { class TemporaryStorage extends Storage {
constructor() { constructor() {
super(); super();

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "0.0.65", "version": "0.0.67",
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -44,7 +44,7 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.15.5", "pxt-common-packages": "0.15.6",
"pxt-core": "3.0.11" "pxt-core": "3.0.11"
}, },
"scripts": { "scripts": {

View File

@ -97,28 +97,21 @@ namespace pxsim {
return this.brickNode; return this.brickNode;
} }
motorUsed(port: number, large: boolean) { motorUsed(ports: number, large: boolean): boolean {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) { for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
const p = 1 << i; const p = 1 << i;
if (port & p) { if (ports & p) {
const motorPort = this.motorMap[p];
if (!this.outputNodes[motorPort])
this.outputNodes[motorPort] = new MotorNode(motorPort, large);
}
}
}
hasMotor(port: number) {
for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
const p = 1 << i;
if (port & p) {
const motorPort = this.motorMap[p]; const motorPort = this.motorMap[p];
const outputNode = this.outputNodes[motorPort]; const outputNode = this.outputNodes[motorPort];
if (outputNode) if (!outputNode) {
return true; this.outputNodes[motorPort] = new MotorNode(motorPort, large);
continue;
}
if (outputNode && outputNode.isLarge() != large)
return false;
} }
} }
return false; return true;
} }
getMotor(port: number, large?: boolean): MotorNode[] { getMotor(port: number, large?: boolean): MotorNode[] {

View File

@ -3,15 +3,23 @@
import lf = pxsim.localization.lf; import lf = pxsim.localization.lf;
namespace pxsim.motors { namespace pxsim.motors {
function portsToString(out: number): string {
export function __motorUsed(port: number, large: boolean) { let r = "";
//console.log("MOTOR INIT " + port); for (let i = 0; i < DAL.NUM_OUTPUTS; ++i) {
if (!ev3board().hasMotor(port)) { if (out & (1 << i)) {
ev3board().motorUsed(port, large); if (r.length > 0) r += "+";
runtime.queueDisplayUpdate(); r += "ABCD"[i];
} else { }
U.userError(`${lf("Multiple motors are connected to Port")} ${String.fromCharCode('A'.charCodeAt(0) + ev3board().motorMap[port])}`);
} }
return r;
}
export function __motorUsed(ports: number, large: boolean) {
//console.log("MOTOR INIT " + port);
if (ev3board().motorUsed(ports, large))
runtime.queueDisplayUpdate();
else
U.userError(`${lf("Multiple motors are connected to Port")} ${portsToString(ports)}`);
} }
} }

View File

@ -70,6 +70,10 @@ namespace pxsim {
this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000; this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000;
} }
isLarge(): boolean {
return this.id == NodeType.LargeMotor;
}
setPolarity(polarity: number) { setPolarity(polarity: number) {
// Either 1 or 255 (reverse) // Either 1 or 255 (reverse)
/* /*