webusb / arduino

WebUSB demos running on Arduino (and compatible) hardware.
566 stars 152 forks source link

Feature Request: Arduino PortentaH7 #96

Closed hpssjellis closed 2 years ago

hpssjellis commented 2 years ago

Feature Request: Arduino PortentaH7

@reillyeon any chance of the PortentaH7 being added to this library. When I plug it into my desktop chrome://device-log/ says (among other things)

vid=2341 pid=025B vendor=9025 "Arduino", product=603 "Envie M7",

If it can't be supported any other options for using webUSB?

reillyeon commented 2 years ago

If this library doesn't support the PortentaH7 then it either means that this board doesn't support the pluggable USB API (which allows a sketch to add custom USB behavior) or the board-specific API is incompatible.

Now that the Web Serial API is available in Chromium-based browsers this library is not required for sites to access Arduinos. You can use the Web Serial API to access the normal virtual serial port provided by most Arduinos over their USB connection.

hpssjellis commented 2 years ago

Thanks @reillyeon, great work on this library. Your response is what I thought but finding it harder than it should be. I have a Seeeduino XIAO which has the new USB support. I would expect the Portenta to also have it. Any suggestions would be appreciated. I am just using normal serial read and write on the arduino but never seem to get connected and Chrome has nothing useful. This seems to be my issue point

    await usbDevice.controlTransferOut({
    requestType: 'class',
    recipient: 'interface',
    request: 0x22,  // vendor-specific request: enable channels
    value: 0x01,  // 0b00010011 (channels 1, 2 and 5)
    index: 2   // Interface 1 is the recipient
  });
  let result = await usbDevice.transferIn(1, 6);   // 1 2 or 5

On the Arduino I just have

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    int serialMessage = Serial.parseInt();
    if(serialMessage == 1) {
      Serial.println("LED On");
      digitalWrite(LED_BUILTIN, LOW);
    } else if(serialMessage == 0) {
      Serial.println("LED Off");
      digitalWrite(LED_BUILTIN, HIGH);
    }
  }
}

Which does kind of work with webSerial but slow and only on a few platforms, but no connection with webUSB.

My repo is here

reillyeon commented 2 years ago
await usbDevice.controlTransferOut({
  requestType: 'class',
  recipient: 'interface',
  request: 0x22,  // vendor-specific request: enable channels
  value: 0x01,  // 0b00010011 (channels 1, 2 and 5)
  index: 2   // Interface 1 is the recipient
});

let result = await usbDevice.transferIn(1, 6);   // 1 2 or 5

I'm confused by the comments in this code. It looks like you are issuing a SET_LINE_CODING control request to enable the virtual serial port implemented by the 2nd USB interface, but the comments are talking about "channels 1, 2 and 5".

You should also make sure to pass a length to transferIn() that is a multiple of the maximum packet size on the endpoint so that you don't get babble errors and can recover more easily if the device sends more data than you expect.

Which does kind of work with webSerial but slow and only on a few platforms, but no connection with webUSB.

The Web Serial API isn't implemented on Android. Is that what you mean by "only on a few platforms"? I don't understand what you mean by "no connection with webUSB".

hpssjellis commented 2 years ago

@reillyeon Yes, I have know idea what I am doing! I am just trying a ton of things to see if I get anything working. So far I can pair a device but never get any full connection. Everywhere I look you seem to be the only expert.

My github is here my active demo site is here. Yes it is a mess!

Until someone can easily connect an Arduino to a webpage webUSB seems kind of useless. Today I am going to see what I can do with the Arduino Create Agent for javascript

reillyeon commented 2 years ago

Unfortunately using these hardware APIs requires knowing a little bit about what you're doing because if you don't send a request to the device that makes sense it isn't likely to give you a useful response.

Looking at your code from the previous comment (I'm ignoring your repo because there are too many different code snippets to comment on) the JavaScript is trying to read 6 bytes from the device using transferIn() while the Arduino sketch is waiting for the host to send either "1" or "0". That's not going to do anything useful. You want to be calling transferOut() and you need to figure out which USB endpoint address to use since you are sending data rather than receiving it, check chrome://usb-internals to list your device's endpoints. Similar to the Web Serial samples you need to use a TextEncoder to turn a string into a Uint8Array you can pass as an argument.

This is probably easier to do with the Web Serial API (and you can use google/web-serial-polyfill to support Android devices) because you don't need to figure out control transfer parameters and endpoint numbers. I'd like to understand your comment previously about it being "slow".

hpssjellis commented 2 years ago

@reillyeon

I updated my arduino code to send and receive over serial


byte incomingByte[1];
int myDelay = 3000;   // non-block delay in milliseconds
unsigned long myStart; 
int serialMessage = 1;

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  myStart = millis();   // set delay
  randomSeed(analogRead(A0));  // AO pin on XIAO does not have to be connected to anything

}

void loop() {

    if ( (millis() - myStart ) >= myDelay) {       
       myStart = millis();      //  reset the delay time
       byte myRandByte = (byte)random(0, 8);
       Serial.write(myRandByte); 
     }

  if (Serial.available() > 0) {
   // incomingByte[1] = Serial.read();
    serialMessage = Serial.parseInt();
    if(serialMessage == 1) {
      Serial.println("LED On");
      digitalWrite(LED_BUILTIN, LOW);
    } else if(serialMessage == 0) {
      Serial.println("LED Off");
      digitalWrite(LED_BUILTIN, HIGH);
    }
  }
}

I am interested in the webSerial and polyfill for android. The slow comment is just that my webBLE and WebSerial seem very slow to get information back and forth to the device. With WebBLE if I send 10 LED on/off commands I can actually see the LED flash, it is that slow. With WebSerial I havn't got a good enough connection but using webSerial googletesting it also seems fairly slow. If you think it can be fast and on Android/IOS then that would be great.

Background: I teach High School Robotics/Machine learning. Everything I do has to be super easy (For me and the students!). I typically bug experts like you until I can simplify their code.

I used to teach TensorflowJS and link to Arduinos using websockets. (10 ms delay, very fast, but a pain needing wifi), but have since switched to the expensive Arduino PortentaH7 with edgeImpulse.com machine learning models. These work fine to drive a toy car but I kind of crave the power of browser Javascript ML with a direct fast connection to a microcontroller , preferably a cheap one like the Seeeduino XIAO .

hpssjellis commented 2 years ago

@reillyeon

Loving your polyfill I can really work with that. I will be testing the npm here

The basic demo.html runs great on Android, slightly different between my XIAO and PortentaH7. Surprised it does not run on my desktop, do you have a link to an equivalent demo that runs on the desktop?

Great to view the id's after connecting, that is so much easier than having to enter them. Weird how the vendor and product ID are different than the assigned value.

hpssjellis commented 2 years ago

@reillyeon I am going to close this issue as the most sensible place to continue this is at the polyfill github.

Looks to me like webSerial works fine for desktop computers and webpolyfill for Android. I am getting better speeds now, just need to find a simple webSerial interface.

The new issue on Polyfill is https://github.com/google/web-serial-polyfill/issues/40

hpssjellis commented 2 years ago

All done using WebSerial and Web-serial-polyfill

https://hpssjellis.github.io/web-serial-polyfill/desktop-serial05.html