Compare commits

..

2 Commits

Author SHA1 Message Date
Michal Moskal
e0aad7227f Add file listing and delete apis 2019-09-03 16:00:46 -07:00
Michal Moskal
aca1b4a764 Improve naming of command line programs 2019-09-03 16:00:33 -07:00
9 changed files with 98 additions and 222 deletions

Binary file not shown.

View File

@@ -89,11 +89,18 @@ Sharing programs is also shown in the [Tips and Tricks](https://legoeducation.vi
### Why can't I delete my program (*.uf2) files from the Brick? ### Why can't I delete my program (*.uf2) files from the Brick?
There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet. There's a bug in the firmware which prevents you from deleting the programs (``*.uf2`` files) from your EV3 Brick. There isn't a firmware update to fix this yet. As a workaround, you can temporarily downgrade your firmware version, delete the files, and then upgrade back to the version that works with MakeCode.
We have prepared a special program that lets you delete UF2 files from the brick. Follow these steps to downgrade your firmware version, delete the files, and uprgade back again:
Download [these PDF instructions](/file-manager.pdf) and drop the PDF on the brick drive.
This will present you with an menu for deleting files. 1. Go into **EV3 LabVIEW** - if it's not installed get it [here](https://education.lego.com/en-us/downloads/mindstorms-ev3/software)
2. Plug in your EV3 Brick and start a new project
3. Go to the **Tools** menu in the upper right corner, select **Firmware Update**
4. In the **Firmware Update** dialog box, click on the **Show Details** button
5. From the **Available Firmware Files** list, select **EV3 Firmware V1.09E**
6. Click the **Update Firmware** button and wait for the update to complete
Now the firmware version on the EV3 Brick will be **V1.09E**. Also, in the process, the downgrade deleted all of the saved programs from the EV3 Brick. To continue to use MakeCode, the firmware version must be at **V1.10E** or above. So, the Brick firmware needs to be upgraded again. If you don't know or do remember how to do this, see the **Upgrade your @drivename@** section in the [troubleshooting](/troubleshoot) page.
For other common questions, try the FAQ page https://makecode.mindstorms.com/faq. For other common questions, try the FAQ page https://makecode.mindstorms.com/faq.

View File

@@ -1,47 +0,0 @@
# battery Property
Return the information about the battery
```sig
brick.batteryInfo(BatteryProperty.Level)
```
## Parameters
* property: the kind of information
## Returns
* a [number](/types/number) which represents the value of the property requested.
## Example
Show the battery level percentage on the screen. Also, show a green light if the battery level is above 15%. If the battery level is below 15% but above 5%, show a orange light. But, if the battery level is below 5%, show a pulsing red light.
```blocks
let battery = 0;
forever(function() {
brick.showString("Battery level:", 1)
brick.showNumber(battery, 2)
battery = brick.batteryInfo(BatteryProperty.Level);
if (battery > 15)
{
brick.setStatusLight(StatusLight.Green);
} else if (battery > 5) {
brick.setStatusLight(StatusLight.Orange);
} else {
brick.setStatusLight(StatusLight.RedPulse)
}
pause(30000)
})
```
Or see all the values
```blocks
forever(function () {
brick.showValue("bat V", brick.batteryInfo(BatteryProperty.Voltage), 1)
brick.showValue("bat %", brick.batteryInfo(BatteryProperty.Level), 2)
brick.showValue("bat I", brick.batteryInfo(BatteryProperty.Current), 3)
})
```

View File

@@ -63,7 +63,9 @@ const rbfTemplate = `
export function deployCoreAsync(resp: pxtc.CompileResult) { export function deployCoreAsync(resp: pxtc.CompileResult) {
let w: pxt.editor.Ev3Wrapper let w: pxt.editor.Ev3Wrapper
let filename = resp.downloadFileBaseName || "pxt" const origElfUF2 = UF2.parseFile(pxt.U.stringToUint8Array(ts.pxtc.decodeBase64(resp.outfiles[pxt.outputName()])))
let filename = resp.downloadFileBaseName || (origElfUF2[0].filename || "").replace(/^Projects\//, "").replace(/\.elf$/, "") || "pxt"
filename = filename.replace(/^lego-/, "") filename = filename.replace(/^lego-/, "")
let fspath = "../prjs/BrkProg_SAVE/" let fspath = "../prjs/BrkProg_SAVE/"
@@ -77,8 +79,6 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
let rbfBIN = pxt.U.fromHex(rbfHex) let rbfBIN = pxt.U.fromHex(rbfHex)
pxt.HF2.write16(rbfBIN, 4, rbfBIN.length) pxt.HF2.write16(rbfBIN, 4, rbfBIN.length)
let origElfUF2 = UF2.parseFile(pxt.U.stringToUint8Array(ts.pxtc.decodeBase64(resp.outfiles[pxt.outputName()])))
let mkFile = (ext: string, data: Uint8Array = null) => { let mkFile = (ext: string, data: Uint8Array = null) => {
let f = UF2.newBlockFile() let f = UF2.newBlockFile()
f.filename = "Projects/" + filename + ext f.filename = "Projects/" + filename + ext

View File

@@ -1,40 +1,13 @@
const enum BatteryProperty {
//% level (%)
Level,
//% block="current (I)"
Current,
//% block="voltage (V)"
Voltage
}
namespace brick { namespace brick {
/** /**
* Returns the current battery level * Returns the current battery level
*/ */
//% blockId=brickBatteryLevel block="battery level" //% blockId=brickBatteryLevel block="battery level"
//% group="Battery" //% group="More"
//% help=brick/battery-level //% help=brick/battery-level
//% deprecated blockHidden=1
export function batteryLevel(): number { export function batteryLevel(): number {
const info = sensors.internal.getBatteryInfo(); const info = sensors.internal.getBatteryInfo();
return info.level; return info.current;
}
/**
* Returns information about the battery
*/
//% blockId=brickBatteryProperty block="battery %property"
//% group="Battery"
//% help=brick/battery-property
export function batteryInfo(property: BatteryProperty): number {
const info = sensors.internal.getBatteryInfo();
switch(property) {
case BatteryProperty.Level: return info.level;
case BatteryProperty.Current: return info.Ibatt;
case BatteryProperty.Voltage: return info.Vbatt;
default: return 0;
}
} }
} }

View File

@@ -36,17 +36,8 @@ namespace sensors.internal {
let analogMM: MMap let analogMM: MMap
let uartMM: MMap let uartMM: MMap
let IICMM: MMap let IICMM: MMap
let powerMM: MMap
let devcon: Buffer let devcon: Buffer
let sensorInfos: SensorInfo[]; let sensorInfos: SensorInfo[]
let batteryInfo: {
CinCnt: number;
CoutCnt: number;
VinCnt: number;
};
let batteryVMin: number;
let batteryVMax: number;
class SensorInfo { class SensorInfo {
port: number port: number
@@ -80,13 +71,10 @@ namespace sensors.internal {
IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0) IICMM = control.mmap("/dev/lms_iic", IICOff.Size, 0)
if (!IICMM) control.fail("no iic sensor") if (!IICMM) control.fail("no iic sensor")
powerMM = control.mmap("/dev/lms_power", 2, 0) unsafePollForChanges(500,
() => { return hashDevices(); },
unsafePollForChanges(500, (prev, curr) => { detectDevices();
() => { return hashDevices(); }, });
(prev, curr) => {
detectDevices();
});
sensorInfos.forEach(info => { sensorInfos.forEach(info => {
unsafePollForChanges(50, () => { unsafePollForChanges(50, () => {
if (info.sensor) return info.sensor._query() if (info.sensor) return info.sensor._query()
@@ -94,8 +82,9 @@ namespace sensors.internal {
}, (prev, curr) => { }, (prev, curr) => {
if (info.sensor) info.sensor._update(prev, curr) if (info.sensor) info.sensor._update(prev, curr)
}) })
}) })
}
}
export function getActiveSensors(): Sensor[] { export function getActiveSensors(): Sensor[] {
init(); init();
@@ -121,130 +110,18 @@ namespace sensors.internal {
return manufacturer + sensorType; return manufacturer + sensorType;
} }
const ADC_REF = 5000 //!< [mV] maximal value on ADC export function getBatteryInfo(): { temp: number; current: number } {
const ADC_RES = 4095 //!< [CNT] maximal count on ADC
// see c_ui.c
const SHUNT_IN = 0.11 // [Ohm]
const AMP_CIN = 22.0 // [Times]
const EP2_SHUNT_IN = 0.05 // [Ohm]
const EP2_AMP_CIN = 15.0 // [Times]
const SHUNT_OUT = 0.055 // [Ohm]
const AMP_COUT = 19.0 // [Times]
const VCE = 0.05 // [V]
const AMP_VIN = 0.5 // [Times]
const AVR_CIN = 300
const AVR_COUT = 30
const AVR_VIN = 30
// lms2012
const BATT_INDICATOR_HIGH = 7500 //!< Battery indicator high [mV]
const BATT_INDICATOR_LOW = 6200 //!< Battery indicator low [mV]
const ACCU_INDICATOR_HIGH = 7500 //!< Rechargeable battery indicator high [mV]
const ACCU_INDICATOR_LOW = 7100 //!< Rechargeable battery indicator low [mV]
function CNT_V(C: number) {
return ((C * ADC_REF) / (ADC_RES * 1000.0))
}
function updateBatteryInfo() {
let CinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent);
let CoutCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.MotorCurrent);
let VinCnt = analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.Cell123456);
if (!batteryInfo) {
batteryVMin = BATT_INDICATOR_LOW;
batteryVMax = BATT_INDICATOR_HIGH;
if (powerMM) {
const accu = powerMM.getNumber(NumberFormat.UInt8LE, 0);
if (accu > 0) {
control.dmesg("rechargeable battery")
batteryVMin = ACCU_INDICATOR_LOW;
batteryVMax = ACCU_INDICATOR_HIGH;
}
}
batteryInfo = {
CinCnt: CinCnt,
CoutCnt: CoutCnt,
VinCnt: VinCnt
};
// update in background
control.runInParallel(() => forever(updateBatteryInfo));
} else {
CinCnt = batteryInfo.CinCnt = ((batteryInfo.CinCnt * (AVR_CIN - 1)) + CinCnt) / AVR_CIN;
CoutCnt = batteryInfo.CoutCnt = ((batteryInfo.CoutCnt * (AVR_COUT - 1)) + CoutCnt) / AVR_COUT;
VinCnt = batteryInfo.VinCnt = ((batteryInfo.VinCnt * (AVR_VIN - 1)) + VinCnt) / AVR_VIN;
}
}
export function getBatteryInfo(): {
level: number;
Ibatt: number,
Vbatt: number,
Imotor: number
} {
init(); init();
if (!batteryInfo) updateBatteryInfo();
const CinCnt = batteryInfo.CinCnt;
const CoutCnt = batteryInfo.CoutCnt;
const VinCnt = batteryInfo.VinCnt;
/*
void cUiUpdatePower(void)
{
#ifndef Linux_X86
DATAF CinV;
DATAF CoutV;
if ((UiInstance.Hw == FINAL) || (UiInstance.Hw == FINALB))
{
CinV = CNT_V(UiInstance.CinCnt) / AMP_CIN;
UiInstance.Vbatt = (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
UiInstance.Ibatt = CinV / SHUNT_IN;
CoutV = CNT_V(UiInstance.CoutCnt) / AMP_COUT;
UiInstance.Imotor = CoutV / SHUNT_OUT;
}
else
{
CinV = CNT_V(UiInstance.CinCnt) / EP2_AMP_CIN;
UiInstance.Vbatt = (CNT_V(UiInstance.VinCnt) / AMP_VIN) + CinV + VCE;
UiInstance.Ibatt = CinV / EP2_SHUNT_IN;
UiInstance.Imotor = 0;
}
#endif
#ifdef DEBUG_TEMP_SHUTDOWN
UiInstance.Vbatt = 7.0;
UiInstance.Ibatt = 5.0;
#endif
}
*/
const CinV = CNT_V(CinCnt) / AMP_CIN;
const Vbatt = CNT_V(VinCnt) / AMP_VIN + CinV + VCE;
const Ibatt = CinV / SHUNT_IN;
const CoutV = CNT_V(CoutCnt) / AMP_COUT;
const Imotor = CoutV / SHUNT_OUT;
const level = Math.max(0, Math.min(100, Math.floor((Vbatt * 1000.0 - batteryVMin)
/ (batteryVMax - batteryVMin) * 100)));
return { return {
level: level, temp: analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryTemp),
Vbatt: Vbatt, current: Math.round(analogMM.getNumber(NumberFormat.Int16LE, AnalogOff.BatteryCurrent) / 10)
Ibatt: Ibatt, }
Imotor: Imotor
};
} }
function hashDevices(): number { function hashDevices(): number {
const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS) const conns = analogMM.slice(AnalogOff.InConn, DAL.NUM_INPUTS)
let r = 0; let r = 0;
for (let i = 0; i < conns.length; ++i) { for(let i = 0; i < conns.length; ++i) {
r = (r << 8 | conns[i]); r = (r << 8 | conns[i]);
} }
return r; return r;

View File

@@ -23,6 +23,10 @@
#define MALLOC_LIMIT (8 * 1024 * 1024) #define MALLOC_LIMIT (8 * 1024 * 1024)
#define MALLOC_CHECK_PERIOD (1024 * 1024) #define MALLOC_CHECK_PERIOD (1024 * 1024)
namespace Array_ {
RefCollection *mk(unsigned flags);
}
void *xmalloc(size_t sz) { void *xmalloc(size_t sz) {
static size_t allocBytes = 0; static size_t allocBytes = 0;
allocBytes += sz; allocBytes += sz;
@@ -476,7 +480,7 @@ void stopLMS() {
if (!pid) if (!pid)
continue; continue;
char namebuf[100]; char namebuf[100];
snprintf(namebuf, 1000, "/proc/%d/cmdline", pid); snprintf(namebuf, 100, "/proc/%d/cmdline", pid);
FILE *f = fopen(namebuf, "r"); FILE *f = fopen(namebuf, "r");
if (f) { if (f) {
fread(namebuf, 1, 99, f); fread(namebuf, 1, 99, f);
@@ -590,4 +594,66 @@ void dmesg(const char *format, ...) {
fflush(dmesgFile); fflush(dmesgFile);
fdatasync(fileno(dmesgFile)); fdatasync(fileno(dmesgFile));
} }
const char *progPath = "/mnt/ramdisk/prjs/BrkProg_SAVE";
//%
void deleteAllPrograms() {
char buf[1024];
struct dirent *ent;
DIR *dir;
dir = opendir(progPath);
if (dir == NULL)
return;
while ((ent = readdir(dir)) != NULL) {
if (ent->d_name[0] == '.')
continue;
snprintf(buf, sizeof(buf), "%s/%s", progPath, ent->d_name);
DMESG("FN: %s", ent->d_name);
// unlink(buf);
}
closedir(dir);
}
//%
void deletePrjFile(String filename) {
if (strlen(filename->data) > 500 || strchr(filename->data, '/'))
return;
char buf[1024];
snprintf(buf, sizeof(buf), "%s/%s", progPath, filename->data);
unlink(buf);
}
//%
RefCollection *listPrjFiles() {
auto res = Array_::mk(0);
//registerGCObj(res);
auto dp = opendir(progPath);
for (;;) {
dirent *ep = dp ? readdir(dp) : NULL;
if (!ep)
break;
if (ep->d_name[0] == '.')
continue;
auto str = mkString(ep->d_name, -1);
//registerGCObj(str);
res->push((TValue)str);
//unregisterGCObj(str);
}
if (dp)
closedir(dp);
//unregisterGCObj(res);
return res;
}
} // namespace pxt } // namespace pxt

View File

@@ -1,6 +1,6 @@
//% color="#68C3E2" weight=100 icon="\uf106" //% color="#68C3E2" weight=100 icon="\uf106"
//% groups='["Buttons", "Screen", "Battery"]' //% groups='["Buttons", "Screen"]'
//% labelLineWidth=60 //% labelLineWidth=60
namespace brick { namespace brick {
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "1.1.18", "version": "1.1.17",
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode", "description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
"private": false, "private": false,
"keywords": [ "keywords": [