• The longer-worded version of my question is...

    Can I configure an Espruino Wifi module as a USB Master, and connect multiple Picos as USB slaves, so that the Wifi can bidirectionally communicate with each Slave? I would be wiring these together using USB pins, not using USB connectors/cables (if that matters).

  • No, there's no USB Master stack available on Espruino.

  • Thanks @maze1980, so I'm gonna have to resort to using I2C. I know I2C can do 1-Master-Many-Slave, but is this supported by the Pico/Wifi boards?

  • Wed 2019.07.24


    Many examples that follow the last function there


  • @Robin the reference manual for I2C Class says:

    This class allows use of the built-in I2C ports. Currently it allows I2C Master mode only.

    That sounds like I can't connect one Pico to a second (or third/fourth/etc) Pico and have them communicate via I2C, because I can't put any device into Slave mode. Am I misinterpreting the docs?

    Edit: and the doc says the same thing about SPI.

  • 'Am I misinterpreting the docs?'

    Probably not.

    I mentioned my attempts with SPI,


    and @allObjects pointed out there, some issues/solutions in #6 and @Gordon points out only master in #2. I have been successful at connecting two uP masters and a slave sensor, then ping pong between the two as the supreme master, but got side tracked on a more perplexing issue. Just haven't gotten back at this, and I2C was in the plan to attempt the same.

    I placed a logic analyzer on the bus to see what is going on. Added a protocol decoder for byte verification. Eventually will get back to writing more code. I don't see why it wouldn't be possible to use digitalRead() on a pin, after detecting a CS, but not using the SPI js module. The master would send the SPI request, the slave will just use plain reads not using SPI.

    Note that Chip Select is on D1 and this is a snap shot of a read request. Binary is amazing. Seeing a visual representation of what was typed in code is just plain cool. As Spock said in a 70's episode to an inbound distress call, 'Captain, a simple binary code.'

    Several images of USART bus in action, just as cool:

    at #3 http://forum.espruino.com/conversations/­332295/

  • @Robin, really interesting information, and again I greatly appreciate the time everyone has been taking to help me. I saw a demo of two Arduinos chatting on I2C, and it looks similar to what you described. But even better, I found this chip, a Cypress I2C Dual Slave Bridge: https://www.cypress.com/documentation/da­tasheets/cy7c65221-dual-i2c-slave-bridge­

    "...is an I2C bus bridge. It functions as an I2C slave for two masters, allowing them exchange data."

    This chip appears to solve the exact problem I have, and even more, appears to allow me to chain as many as I want, which is really important to my project. I now have a lot of work to do before I move forward with this dual-slave chip, but hey, I have a solution!

  • A I2C slave isn't that hard to implement, see e.g.

    I'd say it can be converted to Javascript.

  • Fri 2019.07.26

    Nice find @maze1980!!

    Maybe SPI could be implemented in the same manner perhaps?

    It will be several weeks out before I am able to take a stab at this @indianajones

  • @Robin, no problem, I also have several other tasks to complete before I get to multi-microcontroller communication.

  • For the I2C slave, you could take a look at setWatch's data pin option (so you setWatch SCL and use SDA for data) - although things may still be a bit tricky to get it working nicely.

    What I always suggest for things like this is just to use Serial communications with the UART. This generally works really nicely:

    • Connect all the TX pins of slaves together, and all the RX pins
    • Add a 10k pullup resistor to the Slave TX line
    • Slave TX -> master RX, Slave RX -> master TX
    • Ensure that after you set up all the Serial ports on the slaves, you set the pin mode of the TX pins to opendrain
    • Create some kind of software system to ensure that the slaves only write data when they're asked to by the master. The simplest is just to use the built-in JS REPL to execute code that does some kind of if (id=myId) doSomething() type thing:

      // Slave
      var ID = 1; // change this for each slave
      // Master
      function sendCmd(id, cmd) {
      function gotResponse(d) {
      print("Got data ",JSON.stringify(d));
      var lineData = "";
      Serial1.on('data',function(l) {
      var d = lineData.split("\n");
      lineData = d.pop();
  • Wow, that's awesome, @Gordon, thanks for the help. I actually outlined an ID-based comm idea, but talked myself out of it over the fear that I couldn't control crosstalk between the slave devices. I hadn't considered also using that to control when they communicate. Looks like it's time to get past the theories and start trying something.

  • Mon 2019.07.29

    RATS!! You would have to spoil our spacey dreams with an actual reliable way that would work, @Gordon !    wink, wink  ;-)

    All kidding aside, thank you for detailing how we ought to be doing this task. For my project, running short of pins and didn't want to add a MUX chip as well. But it is nice to have confirmation on how it should be done. Thank you for detailing that snippet.   

    rethink and redesign underway. . . .

  • @Gordon what is the recommended maximum baud rate for USART communication between a Pico and a Wifi?

  • I'd definitely keep it at or below 921600 - I don't think you'll get anything extra out of it above that and for anything over 100 byte packets (IIRC) you may hit FIFO_FULL errors.

    Also I'd start at 9600, get it working, and then raise the speed later - it's entirely possible that at higher baud rates you'll need a lower resistor value, and if you have more than 10cm of wire between devices you may start to hit electrical noise issues as well.

  • My message payload should be a max of 56 bytes, and often much less. I'll start slow and go from there. Thanks.

  • @Gordon I plan to write binary data using the Uint16Array object. The master will send this to one slave, and the slave will respond back with a Uint16Array object. Total bytes in each direction will be < 100 bytes.

    Since I want to control the send and receive, I'm thinking of using Serial.write(data), then Serial.read() to receive the response from the slave. But Serial.read() appears to be a blocking call (no callback). So I'm not sure if my idea is the right approach. Thoughts?

  • But Serial.read() appears to be a blocking call

    It's not blocking, but it'll only return what data is available.

    It's much easier to use Serial1.on('data', callback) to get called back when the data arrives. You'll also need to convert it to a Uint16Array (use new Uint16Array(E.toArrayBuffer(data))) - and also be aware that you need to make sure you've received all the relevant data - since Serial1.on may be called before the full 'frame' is received. Most protocols use a number that isn't normally sent to denote an 'end of frame'.

    You should also use Serial.write(myUint16Array.buffer) to write the underlying buffer since trying to write a normal Uint16Array directly will result in each element being truncated to just 8 bits.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Espruino Wifi as USB Master, Pico as USB slave - is that possible?

Posted by Avatar for indianajones @indianajones