Skip to content

Commit a8b259d

Browse files
authored
Merge pull request #252 from Open-STEM/JacobNanoXRP
Add NanoXRP robot support with firmware detection and battery threshold
2 parents e00736c + a4a6102 commit a8b259d

6 files changed

Lines changed: 83 additions & 9 deletions

File tree

src/components/blockly/xrp_blocks.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,17 @@ Blockly.Blocks['xrp_r_refl'] = {
308308
}
309309
};
310310

311+
Blockly.Blocks['xrp_m_refl'] = {
312+
init: function () {
313+
this.appendDummyInput()
314+
.appendField("Middle reflectance");
315+
this.setOutput(true, null);
316+
this.setColour(90); // soft green
317+
this.setTooltip("");
318+
this.setHelpUrl("");
319+
}
320+
};
321+
311322
//Sensors - Gyro
312323
Blockly.Blocks['xrp_yaw'] = {
313324
init: function () {

src/components/blockly/xrp_blocks_python.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ pythonGenerator.forBlock['xrp_r_refl'] = function (block) {
174174
return [code, pythonGenerator.ORDER_NONE];
175175
};
176176

177+
// NanoXRP only - middle reflectance sensor
178+
pythonGenerator.forBlock['xrp_m_refl'] = function (block) {
179+
pythonGenerator.definitions_['import_reflectance'] = 'from XRPLib.reflectance import Reflectance';
180+
pythonGenerator.definitions_[`reflectance_setup`] = `reflectance = Reflectance.get_default_reflectance()`;
181+
var code = `reflectance.get_middle()`;
182+
return [code, pythonGenerator.ORDER_NONE];
183+
};
184+
177185
//Gyro
178186
pythonGenerator.forBlock['xrp_yaw'] = function (block) {
179187
pythonGenerator.definitions_['import_imu'] = 'from XRPLib.imu import IMU';

src/components/navbar.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,7 @@ function NavBar({ layoutref }: NavBarProps) {
411411
// await CommandToXRPMgr.getInstance().updateMicroPython(dirHandle);
412412
const fileHandle = await dirHandle?.getFileHandle('firmware.uf2', { create: true });
413413
writable = await fileHandle!.createWritable();
414-
const firmwareFilename =
415-
CommandToXRPMgr.getInstance().getXRPDrive() === Constants.XRP_PROCESSOR_BETA
416-
? 'firmware2040.uf2'
417-
: 'firmware2350.uf2';
414+
const firmwareFilename = CommandToXRPMgr.getInstance().getFirmwareFilename();
418415
AppMgr.getInstance().emit(EventType.EVENT_PROGRESS, '10');
419416
const data = await (await fetch('micropython/' + firmwareFilename)).arrayBuffer();
420417
await writable.write(data);
@@ -1109,7 +1106,7 @@ function NavBar({ layoutref }: NavBarProps) {
11091106
};
11101107

11111108
if (connectionType === ConnectionType.USB) {
1112-
if (voltage < 0.45) {
1109+
if (voltage < 0.45 && !CommandToXRPMgr.getInstance().isNanoXRP()) {
11131110
// display a confirmation message to ask the user to turn on the power switch
11141111
const powerswitchImage =
11151112
CommandToXRPMgr.getInstance().getXRPDrive() ===
@@ -1128,7 +1125,7 @@ function NavBar({ layoutref }: NavBarProps) {
11281125
beginExecution();
11291126
}
11301127
} else if (connectionType === ConnectionType.BLUETOOTH) {
1131-
if (voltage < 0.45) {
1128+
if (voltage < 0.45 && !CommandToXRPMgr.getInstance().isNanoXRP()) {
11321129
// display a confirmation message to ask the user to turn on the power switch
11331130
//this one will only happen if they are using a power device plugged into the USB port and the power switch is off.
11341131
setDialogContent(
@@ -1138,7 +1135,7 @@ function NavBar({ layoutref }: NavBarProps) {
11381135
/>,
11391136
);
11401137
toggleDialog();
1141-
} else if (voltage < 5.0) {
1138+
} else if (voltage < (CommandToXRPMgr.getInstance().isNanoXRP() ? 3.6 : 5.0)) {
11421139
setDialogContent(<BatteryBadDlg cancelCallback={toggleDialog} />);
11431140
toggleDialog();
11441141
} else {

src/connections/connection.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,12 @@ abstract class Connection {
6767
abstract disconnect(): Promise<void>;
6868
abstract isConnected(): boolean;
6969

70+
private _isNanoXRP: boolean = false;
71+
72+
isNanoXRP(): boolean { return this._isNanoXRP; }
73+
74+
setNanoXRP(val: boolean): void { this._isNanoXRP = val; }
75+
7076
/**
7177
* HandleEsc
7278
* @param value

src/managers/commandstoxrpmgr.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class CommandToXRPMgr {
4141
private DEBUG_CONSOLE_ON: boolean = true;
4242
private HAS_MICROPYTHON: boolean = false;
4343
private is_XRP_MP: boolean = false;
44+
private is_NanoXRP: boolean = false;
4445

4546
private latestLibraryVersion: string = "";
4647

@@ -226,6 +227,8 @@ export class CommandToXRPMgr {
226227
this.PROCESSOR = 2350;
227228
} else if (hiddenLines[1].includes('RP2040')) {
228229
this.PROCESSOR = 2040;
230+
this.is_NanoXRP = hiddenLines[1].includes('NanoXRP');
231+
this.connection?.setNanoXRP(this.is_NanoXRP);
229232
}
230233
}
231234
if(hiddenLines[1].includes('XRP')){ //is this an XRP version of microPython?
@@ -250,7 +253,9 @@ export class CommandToXRPMgr {
250253
this.XRPId = undefined;
251254
this.lastRun = undefined;
252255
this.HAS_MICROPYTHON = true; // this is set after connection is successful
253-
256+
this.is_NanoXRP = false;
257+
this.connection?.setNanoXRP(false);
258+
254259
//get version information from the XRP
255260
const info = await this.getVersionInfo();
256261

@@ -1031,6 +1036,20 @@ export class CommandToXRPMgr {
10311036
return (this.PROCESSOR! === 2350) ? "RP2350" : "RPI-RP2";
10321037
}
10331038

1039+
/**
1040+
* getFirmwareFilename
1041+
* @returns the firmware filename for the connected robot
1042+
*/
1043+
getFirmwareFilename(): string {
1044+
if (this.PROCESSOR === 2350) return 'firmware2350.uf2';
1045+
if (this.is_NanoXRP) return 'firnware2040nanoxrp.uf2';
1046+
return 'firmware2040.uf2';
1047+
}
1048+
1049+
isNanoXRP(): boolean {
1050+
return this.is_NanoXRP;
1051+
}
1052+
10341053
/**
10351054
* getMPFilename
10361055
* @returns the MicroPython filename

src/managers/pluginmgr.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,19 @@ export default class PluginMgr {
4747
// --- Public Methods ---
4848
public async pluginCheck(): Promise<void> {
4949
let needsUpdate = false;
50-
50+
5151
// Check for RP2350 board special case
5252
if (this.cmdToXRPMgr.getXRPDrive() === "RP2350") {
5353
await this.configNonBeta();
5454
needsUpdate = true;
5555
}
5656

57+
// Add NanoXRP-specific blocks
58+
if (this.cmdToXRPMgr.isNanoXRP()) {
59+
this.configNanoXRP();
60+
needsUpdate = true;
61+
}
62+
5763
// Load and process plugins from plugin.json
5864
await this.loadPlugins();
5965

@@ -229,6 +235,33 @@ export default class PluginMgr {
229235
}
230236

231237

238+
/**
239+
* Add NanoXRP-specific blocks to the toolbox (middle reflectance sensor)
240+
*/
241+
private configNanoXRP(): void {
242+
const toolbox = BlocklyConfigs.ToolboxJson;
243+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
244+
const contents = toolbox.contents as any[];
245+
246+
const sensorsCategory = contents.find(cat =>
247+
cat.kind === "CATEGORY" && cat.name === "Sensors"
248+
);
249+
250+
if (sensorsCategory) {
251+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
252+
const reflectanceCategory = sensorsCategory.contents.find((cat: any) =>
253+
cat.kind === "CATEGORY" && cat.name === "Reflectance"
254+
);
255+
256+
if (reflectanceCategory) {
257+
reflectanceCategory.contents.push({
258+
"kind": "BLOCK",
259+
"type": "xrp_m_refl"
260+
});
261+
}
262+
}
263+
}
264+
232265
/**
233266
* Configure non-beta blocks for RP2350 board
234267
*/

0 commit comments

Comments
 (0)