Fixed bug changing from esptool to repl
This commit is contained in:
parent
a3ca6b5647
commit
a319eb7d39
3 changed files with 71 additions and 53 deletions
|
|
@ -20,32 +20,32 @@ features:
|
|||
- Breadboard-Friendly
|
||||
---
|
||||
|
||||
- We've got a new machine here at Adafruit, it can uncover your deepest desires. Don't believe me? I'll turn it on right now to prove it to you! What, you want your very own soft serve ice cream machine? OK well, that's not something we can provide. But we can provide your *second*-deepest desire: an **ESP32-S*3* Feather board with a built in IPS TFT color display**. It's got all the delicious creamy goodness features of a Feather main board, the comforting warmth of an ESP32-S3 WiFi+BLE microcontroller, and the crispness of a 240x135 pixel color TFT display. All that and it will even plug in nicely into a breadboard, [terminal block wing](https://www.adafruit.com/product/2926), or [Feather Doubler](https://www.adafruit.com/product/2890) or even just stack on top of another wing.
|
||||
We've got a new machine here at Adafruit, it can uncover your deepest desires. Don't believe me? I'll turn it on right now to prove it to you! What, you want your very own soft serve ice cream machine? OK well, that's not something we can provide. But we can provide your *second*-deepest desire: an **ESP32-S*3* Feather board with a built in IPS TFT color display**. It's got all the delicious creamy goodness features of a Feather main board, the comforting warmth of an ESP32-S3 WiFi+BLE microcontroller, and the crispness of a 240x135 pixel color TFT display. All that and it will even plug in nicely into a breadboard, [terminal block wing](https://www.adafruit.com/product/2926), or [Feather Doubler](https://www.adafruit.com/product/2890) or even just stack on top of another wing.
|
||||
|
||||
This Feather comes with native USB and **4 MB Flash + 2 MB of PSRAM**, so it is perfect for use with CircuitPython or Arduino with low-cost WiFi. Native USB means it can act like a keyboard or a disk drive. WiFi means it's awesome for IoT projects. And Feather means it works with the large community of Feather Wings for expandability.
|
||||
This Feather comes with native USB and **4 MB Flash + 2 MB of PSRAM**, so it is perfect for use with CircuitPython or Arduino with low-cost WiFi. Native USB means it can act like a keyboard or a disk drive. WiFi means it's awesome for IoT projects. And Feather means it works with the large community of Feather Wings for expandability.
|
||||
|
||||
The ESP32-S3 is a highly-integrated, low-power, 2.4 GHz Wi-Fi/BLE System-on-Chip (SoC) solution that has built-in native USB as well as some other interesting new technologies like Time of Flight distance measurements and AI acceleration. With its state-of-the-art power and RF performance, this SoC is an ideal choice for a wide variety of application scenarios relating to the [Internet of Things (IoT)](https://www.adafruit.com/category/342), [wearable electronics](https://www.adafruit.com/category/65), and smart homes.
|
||||
The ESP32-S3 is a highly-integrated, low-power, 2.4 GHz Wi-Fi/BLE System-on-Chip (SoC) solution that has built-in native USB as well as some other interesting new technologies like Time of Flight distance measurements and AI acceleration. With its state-of-the-art power and RF performance, this SoC is an ideal choice for a wide variety of application scenarios relating to the [Internet of Things (IoT)](https://www.adafruit.com/category/342), [wearable electronics](https://www.adafruit.com/category/65), and smart homes.
|
||||
|
||||
The Feather ESP32-S3 has a dual-core 240 MHz chip, so it is comparable to ESP32's dual-core. However, there is no Bluetooth **Classic** support, only Bluetooth LE. This chip is a great step up from the earlier ESP32-S2! This ESP32-S3 mini-module we are using on the Feather comes with 4 MB flash and 2 MB PSRAM, as well as lots of 512KB of SRAM so it's perfect for use with CircuitPython support or any time massive buffers are needed: for fast memory access use SRAM, for slower-but-roomier access use PSRAM. It's also great for use in ESP-IDF or with Arduino support.
|
||||
The Feather ESP32-S3 has a dual-core 240 MHz chip, so it is comparable to ESP32's dual-core. However, there is no Bluetooth **Classic** support, only Bluetooth LE. This chip is a great step up from the earlier ESP32-S2! This ESP32-S3 mini-module we are using on the Feather comes with 4 MB flash and 2 MB PSRAM, as well as lots of 512KB of SRAM so it's perfect for use with CircuitPython support or any time massive buffers are needed: for fast memory access use SRAM, for slower-but-roomier access use PSRAM. It's also great for use in ESP-IDF or with Arduino support.
|
||||
|
||||
The color TFT is connected to the SPI pins and uses additional pins for control that are not exposed to the breakout pads. [It's the same display as you see here, with 240x135 pixels and is IPS](https://www.adafruit.com/product/4383) so you get bright color at any angle. The backlight is also connected to a separate pin so you can PWM the backlight up and down as desired.
|
||||
The color TFT is connected to the SPI pins and uses additional pins for control that are not exposed to the breakout pads. [It's the same display as you see here, with 240x135 pixels and is IPS](https://www.adafruit.com/product/4383) so you get bright color at any angle. The backlight is also connected to a separate pin so you can PWM the backlight up and down as desired.
|
||||
|
||||
For low power usages, the Feather has a *second* low-dropout 3.3V regulator. The regulator is controlled with a GPIO pin on the enable line and can shut off power to the Stemma QT port and TFT. There is also a separate power pin for the NeoPixel that can be used to disable it for even lower quiescent power. With everything off and in deep sleep mode, the TFT feather uses about 100uA of current.
|
||||
For low power usages, the Feather has a *second* low-dropout 3.3V regulator. The regulator is controlled with a GPIO pin on the enable line and can shut off power to the Stemma QT port and TFT. There is also a separate power pin for the NeoPixel that can be used to disable it for even lower quiescent power. With everything off and in deep sleep mode, the TFT feather uses about 100uA of current.
|
||||
|
||||
**Features:**
|
||||
**Features:**
|
||||
|
||||
- **ESP32-S3 Dual Core 240MHz Tensilica processor** - the next generation of ESP32-Sx, with native USB so it can act like a keyboard/mouse, MIDI device, disk drive, etc!
|
||||
- **Mini module** has FCC/CE certification and comes with 4 MByte of Flash and 2 MByte of PSRAM - you can have huge data buffers
|
||||
- **[Color 1.14" IPS TFT with 240x135 pixels](https://www.adafruit.com/product/4383)** - bright and colorful display with ST7789 chipset that can be viewed at any angle angle.
|
||||
- **Power options** - USB type C **or** Lipoly battery
|
||||
- **Built-in battery charging** when powered over USB-C
|
||||
- **LiPoly battery monitor** - LC709203 chip actively monitors your battery for voltage and state of charge / percentage reporting over I2C
|
||||
- **Reset and DFU** (BOOT0) buttons to get into the ROM bootloader (which is a USB serial port so you don't need a separate cable!)
|
||||
- **Serial debug output pin** (optional, for checking the hardware serial debug console)
|
||||
- **STEMMA QT** connector for I2C devices, with switchable power, so you can go into low power mode.
|
||||
- **On/Charge/User** LEDs + status **NeoPixel** with pin-controlled power for low power usage
|
||||
- **Low Power friendly**! In deep sleep mode, we can get down to 80~100uA of current draw from the Lipoly connection. Quiescent current is from the power regulator, ESP32-S2 chip, and Lipoly monitor. Turn off the NeoPixel and external I2C/TFT power for the lowest quiescent current draw.
|
||||
- **Works with Arduino or CircuitPython**
|
||||
- **ESP32-S3 Dual Core 240MHz Tensilica processor** - the next generation of ESP32-Sx, with native USB so it can act like a keyboard/mouse, MIDI device, disk drive, etc!
|
||||
- **Mini module** has FCC/CE certification and comes with 4 MByte of Flash and 2 MByte of PSRAM - you can have huge data buffers
|
||||
- **[Color 1.14" IPS TFT with 240x135 pixels](https://www.adafruit.com/product/4383)** - bright and colorful display with ST7789 chipset that can be viewed at any angle angle.
|
||||
- **Power options** - USB type C **or** Lipoly battery
|
||||
- **Built-in battery charging** when powered over USB-C
|
||||
- **LiPoly battery monitor** - LC709203 chip actively monitors your battery for voltage and state of charge / percentage reporting over I2C
|
||||
- **Reset and DFU** (BOOT0) buttons to get into the ROM bootloader (which is a USB serial port so you don't need a separate cable!)
|
||||
- **Serial debug output pin** (optional, for checking the hardware serial debug console)
|
||||
- **STEMMA QT** connector for I2C devices, with switchable power, so you can go into low power mode.
|
||||
- **On/Charge/User** LEDs + status **NeoPixel** with pin-controlled power for low power usage
|
||||
- **Low Power friendly**! In deep sleep mode, we can get down to 80~100uA of current draw from the Lipoly connection. Quiescent current is from the power regulator, ESP32-S2 chip, and Lipoly monitor. Turn off the NeoPixel and external I2C/TFT power for the lowest quiescent current draw.
|
||||
- **Works with Arduino or CircuitPython**
|
||||
|
||||
## Purchase
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import * as esptoolPackage from "https://unpkg.com/esp-web-flasher@5.1.2/dist/we
|
|||
// because it's very integrated into the serial recieve and send code.
|
||||
//
|
||||
|
||||
export const ESP_ROM_BAUD = 115200;
|
||||
|
||||
export class InstallButton extends HTMLButtonElement {
|
||||
static isSupported = 'serial' in navigator;
|
||||
static isAllowed = window.isSecureContext;
|
||||
|
|
@ -40,7 +42,7 @@ export class InstallButton extends HTMLButtonElement {
|
|||
this.currentFlow = null;
|
||||
this.currentStep = 0;
|
||||
this.currentDialogElement = null;
|
||||
this.serial = null;
|
||||
this.port = null;
|
||||
this.espStub = null;
|
||||
this.dialogCssClass = "install-dialog";
|
||||
this.connected = this.connectionStates.DISCONNECTED;
|
||||
|
|
@ -423,7 +425,7 @@ export class InstallButton extends HTMLButtonElement {
|
|||
}
|
||||
|
||||
async setBaudRateIfChipSupports(chipType, baud) {
|
||||
if (baud == esptoolPackage.ESP_ROM_BAUD) { return } // already the default
|
||||
if (baud == ESP_ROM_BAUD) { return } // already the default
|
||||
|
||||
if (chipType == esptoolPackage.CHIP_FAMILY_ESP32) { // only supports the default
|
||||
this.logMsg(`ESP32 Chip only works at 115200 instead of the preferred ${baud}. Staying at 115200...`);
|
||||
|
|
@ -438,4 +440,16 @@ export class InstallButton extends HTMLButtonElement {
|
|||
await this.espStub.setBaudrate(baud);
|
||||
}
|
||||
}
|
||||
|
||||
async espConnect(logger) {
|
||||
// - Request a port and open a connection.
|
||||
this.port = await navigator.serial.requestPort();
|
||||
|
||||
logger.log("Connecting...");
|
||||
await this.port.open({ baudRate: ESP_ROM_BAUD });
|
||||
|
||||
logger.log("Connected successfully.");
|
||||
|
||||
return new esptoolPackage.ESPLoader(this.port, logger);
|
||||
};
|
||||
}
|
||||
|
|
@ -3,9 +3,10 @@ import { html } from 'https://unpkg.com/lit-html?module';
|
|||
import * as toml from "https://unpkg.com/iarna-toml-esm@3.0.5/toml-esm.mjs"
|
||||
import * as zip from "https://cdn.jsdelivr.net/npm/@zip.js/zip.js@2.6.65/+esm";
|
||||
import * as esptoolPackage from "https://unpkg.com/esp-web-flasher@5.1.2/dist/web/index.js?module"
|
||||
|
||||
//import * as esptoolPackage from "https://adafruit.github.io/Adafruit_WebSerial_ESPTool/js/modules/esptool.js"
|
||||
import { REPL } from 'https://cdn.jsdelivr.net/gh/adafruit/circuitpython-repl-js@1.1.0/repl.js';
|
||||
import { InstallButton } from "./base_installer.js";
|
||||
import { InstallButton, ESP_ROM_BAUD } from "./base_installer.js";
|
||||
|
||||
// TODO: Combine multiple steps together. For now it was easier to make them separate,
|
||||
// but for ease of configuration, it would be work better to combine them together.
|
||||
|
|
@ -13,7 +14,7 @@ import { InstallButton } from "./base_installer.js";
|
|||
// that order, but due to having handlers in the first of those steps, it was easier to
|
||||
// just call nextStep() from the handler.
|
||||
//
|
||||
// TODO: Hide the log and make it accessible via the menu (future feature, console.log for now)
|
||||
// TODO: Hide the log and make it accessible via the menu (future feature, output to console for now)
|
||||
// May need to deal with the fact that the ESPTool uses Web Serial and CircuitPython REPL uses Web Serial
|
||||
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ export class CPInstallButton extends InstallButton {
|
|||
this.circuitpyDriveHandle = null;
|
||||
this._bootDriveName = null;
|
||||
this._serialPortName = null;
|
||||
this.serialDevice = null;
|
||||
this.replSerialDevice = null;
|
||||
this.repl = null;
|
||||
this.fileCache = [];
|
||||
this.reader = null;
|
||||
|
|
@ -238,8 +239,8 @@ export class CPInstallButton extends InstallButton {
|
|||
buttons: [this.previousButton, {
|
||||
label: "Next",
|
||||
onClick: this.nextStep,
|
||||
isEnabled: async () => { return (this.currentStep < this.currentFlow.steps.length - 1) && !!this.serialDevice; },
|
||||
onUpdate: async (e) => { this.currentDialogElement.querySelector("#butConnect").innerText = !!this.serialDevice ? "Connected" : "Connect"; },
|
||||
isEnabled: async () => { return (this.currentStep < this.currentFlow.steps.length - 1) && !!this.replSerialDevice; },
|
||||
onUpdate: async (e) => { this.currentDialogElement.querySelector("#butConnect").innerText = !!this.replSerialDevice ? "Connected" : "Connect"; },
|
||||
}],
|
||||
},
|
||||
|
||||
|
|
@ -253,11 +254,11 @@ export class CPInstallButton extends InstallButton {
|
|||
</div>
|
||||
<div class="field">
|
||||
<label for="circuitpy_wifi_password">WiFi Password:</label>
|
||||
<input id="circuitpy_wifi_password" class="setting-data" type="text" placeholder="WiFi Password" value="${data.wifi_password}" />
|
||||
<input id="circuitpy_wifi_password" class="setting-data" type="password" placeholder="WiFi Password" value="${data.wifi_password}" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="circuitpy_web_api_password">Web Workflow API Password:</label>
|
||||
<input id="circuitpy_web_api_password" class="setting-data" type="text" placeholder="Web Workflow API Password" value="${data.api_password}" />
|
||||
<input id="circuitpy_web_api_password" class="setting-data" type="password" placeholder="Web Workflow API Password" value="${data.api_password}" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="circuitpy_web_api_port">Web Workflow API Port:</label>
|
||||
|
|
@ -479,16 +480,16 @@ export class CPInstallButton extends InstallButton {
|
|||
await this.onReplDisconnected(e);
|
||||
await this.espDisconnect();
|
||||
let esploader;
|
||||
try {
|
||||
esploader = await esptoolPackage.connect({
|
||||
//try {
|
||||
esploader = await this.espConnect({
|
||||
log: (...args) => this.logMsg(...args),
|
||||
debug: (...args) => {},
|
||||
error: (...args) => this.errorMsg(...args),
|
||||
});
|
||||
} catch (err) {
|
||||
/*} catch (err) {
|
||||
this.errorMsg("Unable to open Serial connection to board. Make sure the port is not already in use by another application or in another browser tab.");
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
try {
|
||||
this.updateEspConnected(this.connectionStates.CONNECTING);
|
||||
|
|
@ -543,17 +544,17 @@ export class CPInstallButton extends InstallButton {
|
|||
|
||||
// Connect to the Serial Port and interact with the REPL
|
||||
try {
|
||||
this.serialDevice = await navigator.serial.requestPort();
|
||||
this.replSerialDevice = await navigator.serial.requestPort();
|
||||
} catch (e) {
|
||||
// Likely the user cancelled the dialog
|
||||
return;
|
||||
}
|
||||
await this.serialDevice.open({baudRate: 115200});
|
||||
await this.replSerialDevice.open({baudRate: ESP_ROM_BAUD});
|
||||
|
||||
this.repl = new REPL();
|
||||
this.repl.serialTransmit = this.serialTransmit.bind(this);
|
||||
|
||||
this.serialDevice.addEventListener("message", this.onSerialReceive.bind(this));
|
||||
this.replSerialDevice.addEventListener("message", this.onSerialReceive.bind(this));
|
||||
|
||||
// Start the read loop
|
||||
this._readLoopPromise = this._readSerialLoop().catch(
|
||||
|
|
@ -562,8 +563,8 @@ export class CPInstallButton extends InstallButton {
|
|||
}.bind(this)
|
||||
);
|
||||
|
||||
if (this.serialDevice.writable) {
|
||||
this.writer = this.serialDevice.writable.getWriter();
|
||||
if (this.replSerialDevice.writable) {
|
||||
this.writer = this.replSerialDevice.writable.getWriter();
|
||||
await this.writer.ready;
|
||||
}
|
||||
|
||||
|
|
@ -580,9 +581,9 @@ export class CPInstallButton extends InstallButton {
|
|||
this.writer = null;
|
||||
}
|
||||
|
||||
if (this.serialDevice) {
|
||||
await this.serialDevice.close();
|
||||
this.serialDevice = null;
|
||||
if (this.replSerialDevice) {
|
||||
await this.replSerialDevice.close();
|
||||
this.replSerialDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -816,8 +817,7 @@ export class CPInstallButton extends InstallButton {
|
|||
}
|
||||
}, 0, 0);
|
||||
} catch (err) {
|
||||
this.errorMsg(`Unable to flash file: ${filename}`);
|
||||
console.log(err);
|
||||
this.errorMsg(`Unable to flash file: ${filename}. Error Message: ${err}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -846,15 +846,15 @@ export class CPInstallButton extends InstallButton {
|
|||
|
||||
bytesWritten += chunk.size;
|
||||
progressElement.value = Math.round(bytesWritten / totalSize * 100);
|
||||
console.log(`${Math.round(bytesWritten / totalSize * 100)}% (${bytesWritten} / ${totalSize}) written...`);
|
||||
this.logMsg(`${Math.round(bytesWritten / totalSize * 100)}% (${bytesWritten} / ${totalSize}) written...`);
|
||||
}
|
||||
console.log("File successfully written");
|
||||
this.logMsg("File successfully written");
|
||||
try {
|
||||
// Attempt to close the file, but since the device reboots, it may error
|
||||
await writableStream.close();
|
||||
console.log("File successfully closed");
|
||||
this.logMsg("File successfully closed");
|
||||
} catch (err) {
|
||||
console.log("Error closing file. Continuing...");
|
||||
this.logMsg("Error closing file, probably due to board reset. Continuing...");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -891,7 +891,7 @@ export class CPInstallButton extends InstallButton {
|
|||
}
|
||||
|
||||
getSetting(setting, defaultValue = '') {
|
||||
if (this.tomlSettings.hasOwnProperty(setting)) {
|
||||
if (this.tomlSettings && this.tomlSettings.hasOwnProperty(setting)) {
|
||||
return this.tomlSettings[setting];
|
||||
}
|
||||
|
||||
|
|
@ -903,7 +903,7 @@ export class CPInstallButton extends InstallButton {
|
|||
if (formElement) {
|
||||
if (formElement.type == "number") {
|
||||
this.tomlSettings[settingName] = parseInt(formElement.value);
|
||||
} else if (formElement.type == "text") {
|
||||
} else if (formElement.type == "text" || formElement.type == "password") {
|
||||
this.tomlSettings[settingName] = formElement.value;
|
||||
} else {
|
||||
this.errorMsg(`A setting was found, but a form element of type ${formElement.type} was not expected.`);
|
||||
|
|
@ -965,11 +965,15 @@ export class CPInstallButton extends InstallButton {
|
|||
async espDisconnect() {
|
||||
// Disconnect the ESPTool
|
||||
if (this.espStub) {
|
||||
this.espStub.removeEventListener("disconnect", this.espDisconnect.bind(this));
|
||||
await this.espStub.disconnect();
|
||||
this.espStub.removeEventListener("disconnect", this.espDisconnect.bind(this));
|
||||
this.updateEspConnected(this.connectionStates.DISCONNECTED);
|
||||
this.espStub = null;
|
||||
}
|
||||
if (this.port) {
|
||||
await this.port.close();
|
||||
this.port = null;
|
||||
}
|
||||
}
|
||||
|
||||
async serialTransmit(msg) {
|
||||
|
|
@ -987,20 +991,20 @@ export class CPInstallButton extends InstallButton {
|
|||
}
|
||||
|
||||
async _readSerialLoop() {
|
||||
if (!this.serialDevice) {
|
||||
if (!this.replSerialDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
const messageEvent = new Event("message");
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
if (this.serialDevice.readable) {
|
||||
this.reader = this.serialDevice.readable.getReader();
|
||||
if (this.replSerialDevice.readable) {
|
||||
this.reader = this.replSerialDevice.readable.getReader();
|
||||
while (true) {
|
||||
const {value, done} = await this.reader.read();
|
||||
if (value) {
|
||||
messageEvent.data = decoder.decode(value);
|
||||
this.serialDevice.dispatchEvent(messageEvent);
|
||||
this.replSerialDevice.dispatchEvent(messageEvent);
|
||||
}
|
||||
if (done) {
|
||||
this.reader.releaseLock();
|
||||
|
|
|
|||
Loading…
Reference in a new issue