noopkat / avrgirl-arduino

:girl: :pager: A NodeJS library for flashing compiled sketch files to Arduino microcontroller boards.
MIT License
504 stars 127 forks source link

flashing avr109 in browser #204

Open koriwi opened 3 years ago

koriwi commented 3 years ago

Description

It's currently not possible to flash an avr109 protocol device in the browser

Expected behaviour

it should flash like an stk500v1 based device

Actual behaviour

avrgirl-arduino.js:17815 Uncaught TypeError: Serialport is not a constructor
    at Avr109._reset (avrgirl-arduino.js:17815)
    at Avr109._upload (avrgirl-arduino.js:17744)
    at avrgirl-arduino.js:18606
    at avrgirl-arduino.js:12894
    at Connection._setUpSerial (avrgirl-arduino.js:12910)
    at Connection._init (avrgirl-arduino.js:12893)
    at avrgirl-arduino.js:18602
    at AvrgirlArduino._validateBoard (avrgirl-arduino.js:18584)
    at AvrgirlArduino.flash (avrgirl-arduino.js:18598)

Operating system and version

Linux archlinux 5.8.7-arch1-1 #1 SMP PREEMPT Sat, 05 Sep 2020 12:31:32 +0000 x86_64 GNU/Linux

Avrgirl Arduino version

Please provide version on the Avrgirl Arduino version used

If working in a fork of the GitHub project, obtain this information post installation using:

4.2.3

NodeJS version

v12.18.3

Arduino Board being used

pro micro

Step by step guide to reproducing the issue

just use your react example and add the board string 'micro' or 'sf-pro-micro' or anything similar

noopkat commented 3 years ago

hi @koriwi,

Thanks for reaching out about this issue. It's not mentioned in the docs for the React demo but in the directory above that there's a caveats section that warns we currently still don't have support for avr109 boards.

The reason why this support will be challenging (but not impossible!) is because if an avr109 board changes its reported product id while in bootloader mode (common on Windows particularly), the previous connection permissions that the user granted will no longer be valid for the "new" device, and so another permission dialog and flow will be needed in order to proceed. This flow would need to happen after the board is reset, which is kinda awkward. We could put the user through an "onboarding" process before we try to flash, where they double opt-in to grant permission to both "devices" first, and then all flashing actions after that would be smooth and without interruption.

I don't currently have the capacity to start working on this support just yet (yay covid-19 2020 etc etc) however it is something I want to definitely aim for supporting in the future. If you know enough about avr109 and serialport internals and you're enthusiastic about contributing, I'd love to see a PR but no pressure whatsoever!

koriwi commented 3 years ago

Thanks for explaining it in great detail. I would love to make this happen. Currently I'm also fighting with windows and it's weird serial port behaviour in my own project. But maybe after i solved that i can have a look :)

shikshik commented 3 years ago

Hey, great project you got here! I also hit the rock and would love helping to solve this issue. Can you direct me where to start? I'm more a JS developer, but I'm a fast learner..

Can I override this somehow for mac use at this moment?

koriwi commented 3 years ago

Currently sick (but covid negative :) ) Can't help you right now, but i will come back to this issue

shikshik commented 3 years ago

Currently sick (but covid negative :) ) Can't help you right now, but i will come back to this issue

Be well, drink some tea :)

rubendax commented 3 years ago

My JS skills are somewhat limited but I would be happy to help with this in any way I can, even if just for testing.

benjaminaigner commented 3 years ago

Hi @ all,

I've experimented with WebSerial and the AVR109 bootloader protocol for the Arduino Micro (ProMicro) updater. With my limited JS skills, I've implemented a proof-of-concept: https://github.com/benjaminaigner/avr109-webserial

@noopkat THX for the inspiration with your avrgirl project! Unfortunately, I've no node.js skills whatsoever, so my implementation is "plain" JS with WebSerial. If anybody wants to use this code to create a PR on avrgirl, I would be really happy.

mrfrase3 commented 3 years ago

Hey, maintainer of duino.app here.

Thanks @benjaminaigner, I had a crack at this a few months ago, due to a few people requesting AVR109 support, to not much success, but I might have another shot now that your example makes it seem possible. Very interesting.

rubendax commented 2 years ago

@benjaminaigner I wanted to report that I tried out your avr109-webserial and it works! Thank you!

I want to try to see if there's any way to make a more desirable user-interaction experience. Even if the double confirmation is necessary, it would be great if there was maybe some way to front-load confirming both ports so that the user is not required to perform any action within a specified time window...

Anyway, thanks so much for your work on this, it's awesome to finally have avr109 flashing in browser.

benjaminaigner commented 2 years ago

@mrfrase3 @rubendax

THX for picking up my example :-). We (AsTeRICS Team needed an update possibility for the WebGUI of our assistive devices (FABI & FLipMouse / FLipPad ), where we want to spare our users from installing Arduino to update their devices.

@rubendax If you find some way to improve the user experience, please inform me, we have this annoying problem too; due to the "problem" with different USB devices when using the bootloader, I didn't find a way.

Greetings

shikshik commented 2 years ago

Hey @benjaminaigner, I didn't try your solution yet, I'm using avrgirl-arduino with a desktop electron + reactjs solution. The issue I'm facing is having the user to click the physical reset button twice to make the device go into upload mode. Have you overcome this issue? I'm about to develop a web browser solution as well, based on my reactjs app, so if your solution fixes the need for clicking a physical button, I might solve your issue as well (+ giving the world an open source reactjs solution).

@rubendax you have my number. Let me know if you want to work this together.

mrfrase3 commented 2 years ago

I never got around to looking into this, but coincidentally I've been looking into refactoring my application, and the first part of that is re-writing avrgirl, the stk500v1, stk500v2, avr109, and esptools into a new independent npm package.

I've gotten stk500v1 done already and am currently decrypting the spaghetti code that is stk500v2, all with typescript, promises, and automated tests (I envision an RPi with a bank of microcontrollers plugged in that runs all the tests, testing uploads to the actual boards)

Can check it out here https://github.com/duinoapp/upload-multitool

benjaminaigner commented 2 years ago

@shikshik You can put the Arduino Sketch into bootloader mode by opening the port with 1200Baud, closing it after 500ms: https://github.com/benjaminaigner/avr109-webserial/blob/0aaf0a524e2b29bb7b606b24d267c38a124e6965/index.html#L221 But as we discussed, afterwards the Arduino enumerates again as a different serial port, so you have to select the serial port in the browser again.

One caveat (heavily depending on your Arduino, especially the bootloader version): if you reset the Arduino via it's own serial interface, the time spent in the bootloader is limited. Pressing the reset button twice extends this time. Reference: https://learn.sparkfun.com/tutorials/pro-micro--fio-v3-hookup-guide/all#ts-reset

Greetings

shikshik commented 2 years ago

Thank you @benjaminaigner ! I will do some tests and try to solve the second interaction issue. I think I did solve it in my electron project. I will update on my results very soon.

rubendax commented 2 years ago

@benjaminaigner So far I've made it so that the upload process is automatically initiated after the device resets, which is one less click, but the user still needs to confirm both ports in separate pop-up windows - and if the user does not confirm the second port within the limited time frame then the flash will fail.

I've tried storing the SerialPort object which is returned from navigator.serial.requestPort() to a variable to be able to be reused later, but I haven't been able to make it work so far. Somehow the SerialPort object seems to be unique every time the device reconnects. That being said, I have never worked with Web Serial before and I could easily just be trying to store the object in the wrong way.

Not relevant to standard Arduino boards, but maybe useful information to share: I've even tried hacking the bootloader so that it reports the same VID and PID in both bootloader mode and regular program mode (unlike most 32u4-based Arduino boards), but this does not seem to have any affect on SerialPort. Even with matching VID and PID, it still appears as a unique serial port every time it connects and therefore requires user interaction.

koriwi commented 2 years ago

I'm back :P

In my app https://github.com/freeyourstream/freedeck-configurator i actually have an auto(re)connect implemented. Not for flashing, but for replugging devices without user interaction. works totally fine. https://github.com/FreeYourStream/freedeck-configurator/blob/6714d6cde6cad09bdc204a0cef2283953aeacafb/src/lib/serial.ts#L33

@mrfrase3 project looks good. i would like to add it to my app when it 109 compatible!