wokwi-features icon indicating copy to clipboard operation
wokwi-features copied to clipboard

Multiple MCU Capability

Open rcwilcox opened this issue 3 years ago • 21 comments

Add capability to simulate multiple MCUs in a single simulation diagram.

Possible Use Cases:

  • Prototype multi-processor systems - e.g. Multiple Slave MCUs processing sensor data (DSP algorithms, predictive filters for raw IMU inputs etc.) that would provide preprocessed data back to the Master MCU.
  • Simulate H/W not (yet) available as a Wokwi part. e.g. a MAX7219 could be simulated with a MCU board (or a bare bones MCU chip if that were available) to scan and decode LED outputs.

rcwilcox avatar Sep 21 '21 14:09 rcwilcox

This one seems quite popular already, so I'm sharing some thoughts about the implementation challenges:

  • Performance - right now, we can a single-core 16MHz AVR MCU simulation usually runs at 100% on modern hardware. RP2040 (at 125MHz) runs at about 33% on my hardware here, which is pretty powerful. Running multiple MCUs simultaneously will drop the performance even further. This can be mitigated by carefully writing the user code - putting the MCU to sleep when idle, or by dropping the MCU speed (e.g. using the clock prescaler on AVR).
  • Code - I assume that for most use cases, you want different code to run on each MCU. We need to come up with a way to define several "subprojects" in each project, and associate each to a microcontroller. Any proposals here?

For "Simulate H/W not (yet) available as a Wokwi part" - multiple MCUs is one way to achieve this. Another approach I'm looking at is using Web Assembly (perhaps together with AssemblyScript). It'll be more performant, but comes with its own set of challenges. So perhaps multiple MCUs support can give us a quick win here.

urish avatar Sep 21 '21 18:09 urish

We can create option in diagram.json to configure the MCU speed. I think even 20MHz for RP2040 would be enough for most applications and maybe we can go even slower. For the code problem it can be also set in diagram.json as entry point file. Adding directiories could also help. In single MCU system code would be compiled like it is already. If we add more MCUs the ones with other IDs would have to have code in folder mentioning their id.

diagram.json approach

{
      "type": "wokwi-pi-pico",
      "id": "pico",
      "top": -1.33,
      "left": 6.67,
      "attrs": { "env": "arduino-community" },
      "speed": 10000000 (10MHz)
      "code": "sketch.ino" (optional, without it behaves like it is now)
},
{
      "type": "wokwi-pi-pico",
      "id": "pico2",
      "top": -1.33,
      "left": -100.67,
      "attrs": { "env": "arduino-community" },
      "speed": 10000000 (10MHz)
      "code": "sketch2.ino"
}

directories approach (speed still in diagram.json) 1 MCU:

/sketch.ino
....

N MCU:

/sketch.ino (code of the first MCU with id: pico)
/mcu/pico2/sketch.ino (code of MCU with id:pico2)
....

It would be great to have multi MCU simulation. It would greatly increase speed of prototyping various multiple MCU systems. Like testing I2C between MCUs. Compilation time on wokwi is faster than on my pc for rp2040 and also not including time to restart every one of them to bootloader and compile each separately.

dommilosz avatar Jun 18 '22 20:06 dommilosz

Thanks for the feedback and suggestions!

Directories probably make more sense, as projects often consist of multiple source files (e.g. the libraries.txt / library manager tab). Some of the projects use Python or non-Android SDKs (like the Pi Pico SDK), so they require different kind of treatment.

As far as slowing down the clock - unfortunately, it is not as simple. The code that is running inside the simulation has also to be aware of the slower clock, otherwise things like delay() will take longer than expected.

In the meanwhile, custom chips (#301) should provide a way to create custom I2C devices (also SPI, UART), so they may be useful for certain scenarios. And they have good performance too.

Great to hear you are happy with the developer experience on Wokwi.com :-)

urish avatar Jun 18 '22 20:06 urish

In Arduino IDE there is option to change the clock. Also F_CPU define may help. Other option is to inject code changing cpu speed. In rp2040 you can do it and delays still work fine I think.

dommilosz avatar Jun 18 '22 21:06 dommilosz

Leave the project & window as a single , as it is now. Just add a "connector" item that allows you to connect to another project in another browser tab/window. This would cause that other window to be able to run in the background.

The connector would just connect wires.

leftCoast avatar Jun 20 '22 18:06 leftCoast

The connector would just connect wires.

It's a creative idea, but "just connecting wires" is unfortunately not feasible. To find the voltage on the wire (high/low), the simulator has to look at everything connected to this wire. Different browser tabs communicating by passing messages, which has high latency (we can get around 100 messages per second, often even less). So the simulation will be very very very slow if it'll have to wait for the two tabs to talk every time it has to figure out the state of the wire (imagine driving an Uno down from 16MHz to 100Hz... that kind of slow)

urish avatar Jun 21 '22 17:06 urish

could we just bounce a couple bytes off a server?

leftCoast avatar Jun 22 '22 00:06 leftCoast

could we just bounce a couple bytes off a server?

How exactly?

urish avatar Jun 22 '22 05:06 urish

How? Err..

The "connector" stores a URL, login, password & ID to its mate from another simulation. It uses this to store any changes on its input pins to that file. Then reads the matching file for changes and stores them locally.

It would probably be slow, yes. But, it would be a start. And it's not limited to 2 processors. Heck, it could be any amount if them on any machine. It might be a fun thing to play around with.

-jim

leftCoast avatar Jun 23 '22 07:06 leftCoast

I think using http request would be very very slow like few requests/s. Websockets may be better solution. But still uses tcp which is not great for very quick message system.

dommilosz avatar Jun 23 '22 08:06 dommilosz

Just wanted to pop in here with a few of my own thoughts on this --

  1. Connecting projects together seems to me to be the best way to do this, however it would be meaningful to allow multiple "instances" of a single project to be connected - for instance, if I built some kind of sensor assembly and I wanted to allow multiple instances of that sensor to communicate with the master unit - I wouldn't want to create the same project multiple times. This also comes into play in my suggestion around how to implement the connections
  2. Modeling connections around any type of TCP request (HTTP, WebSockets, etc) will introduce some latency, yes - but let's be honest - for the simulation, what kind of sampling rate are you really trying to get on those MCU to MCU connections?

Now let's talk about the connections themselves, there's several different approaches one could take (and I'll use the ESP32 stuff for this, since I'm right now working in that and looking into this very things from a usability perspective for my project)

  1. Serial I/O -- You can use either a UART port of SoftwareSerial library in your code to connect two MCUs together
  2. BLE -- You can use Bluetooth to communicate between two devices
  3. MQTT / Network / WiFi -- Use a server-side component (MQTT) to facilitate communication between MCUs
  4. ESP-Mesh / ESP-BLE-Mesh -- Use a mesh network
  5. ESP-Now -- Use a direct protocol over wifi

In all of these scenarios, some latency will be added in a real implementation depending on which you choose, so that being said which of these would be the easiest to implement? Well, The MQTT solution can literally do this right now without any changes. Almost every other solution (imo) would be pretty simple to implement using websockets and would provide a balance between being able to simulate how this would work in reality (thus eliminating the amount of code changes between the simulation and the dev board and then the pcb) and an implementation that doesn't "break the bank" and proves to be incredibly unscalable from a simulation perspective (i.e. physically modeling multiple MCUs in the same simulator instance, which is I believe what @urish was getting at above)

TLDR; leave projects alone, allow projects to be linked with multiple instances of a project created on the master or linker side - each instance of a linked project prompts the user to open that instance in a new browser tab; and use websockets for the node to node configuration allowing pretty much any of BLE, Serial, Mesh, ESP-Now as the implementation type - for anything requiring a physical wire (Serial) you would probably want to force the link to reference which pins to connect for TX/RX on both sides and "disable" those pins in the simulator (or maybe not, idk?)

chrisisbeef avatar Sep 28 '22 19:09 chrisisbeef

For an application on which I am volunteering, we would like to have multiple MCU capability. We have an SPI Controller (an UNO) connecting to an SPI Peripheral (a second UNO).

Our application we call the General Purpose Alarm Device. aka GPAD.
https://github.com/PubInv/general-alarm-device The GPAD is an SPI Peripheral and we would benefit if w could simulate two UNOs connected as Controller and Peripheral so we can develop both the controller side and peripheral side firmware.

ForrestErickson avatar Oct 06 '22 17:10 ForrestErickson

This would help us with a current ongoing project quite a lot! :)

EpicLPer avatar Oct 18 '22 08:10 EpicLPer

This would help us with a current ongoing project quite a lot! :)

@EpicLPer can you please explain how it will be helpful for you?

urish avatar Oct 18 '22 08:10 urish

This would help us with a current ongoing project quite a lot! :)

@EpicLPer can you please explain how it will be helpful for you?

We're currently working on a somewhat technical fursuit for a friend, which uses multiple Xiao ESP32C3's from Seeedstudio as "Slaves" and one ESP32 as the main unit.
We want to test SPI/I2C communication amongst all those units to see, check and test various things before implementing them IRL or building them on a breadboard, which includes various temperature readings, monitoring of failing Slaves, error outputs, audio output to a 600 Watt DAC, communication via Bluetooth on a Smartphone and many more small things by the end of our project :)

So quite a project indeed :)

EpicLPer avatar Oct 18 '22 08:10 EpicLPer

Quite a project indeed! How many C3 "slaves" do you need to have in order for the simulation to be useful for you?

urish avatar Oct 18 '22 08:10 urish

Quite a project indeed! How many C3 "slaves" do you need to have in order for the simulation to be useful for you?

So far everything's just a rough sketch, but by the end we'd at minimum need 5 to communicate to each other.
However, less is also okay since we could just split things up, I'm not even a programmer myself (yet), and this would help immensely to get me motivated to look further into things instead of having to flash onto real hardware, deal with god knows how many wires and potential wonky connections, waiting multiple minutes for firmware flashes to update on each Slave and/or the main ESP, etc. etc. etc. :)

EpicLPer avatar Oct 18 '22 08:10 EpicLPer

The recent traffic by "urish" and "EpicLPer" had me thinking I could also be more specific. For our GPAD device we envision only one SPI Controller and one SPI Peripheral for our use case. Each is an UNO (or equivalent). See: https://github.com/PubInv/general-alarm-device

However, in general, SPI systems might have one controller and many peripherals and so for the use case where the peripheral is something like an UNO or an ESP32 an elaborate systems could have as many peripherals attached as the controller can support the nCS (Chip Select low) pins.

For systems with multi master I2C bus it gets even more, interesting.

Simulating both SPI and I2C systems before breadboarding / prototyping or PCB fabrication would be an ideal use case to demonstrate Wokwi utility.

ForrestErickson avatar Oct 18 '22 14:10 ForrestErickson

If anyone needs multiple MCUs now and programming JavaScript/TypeScript is an option, https://github.com/wokwi/rp2040js/pull/117 includes a demo program that wires up two RP2040s and simulates a pullup/open collector bus between them. Probably this can be done in a similar way for ESP32 and Arduino, too.

c1570 avatar Jan 30 '23 20:01 c1570

https://github.com/wokwi/rp2040js/pull/117 includes a demo program that wires up two RP2040s and simulates a pullup/open collector bus between them.

Thanks, very interesting to see this implementation. As far as I can see, the SRAM and peripherals are not shared between the cores? Or did I miss anything?

urish avatar Feb 05 '23 19:02 urish

Oh, my bad - it's simulating two RP2040 MCUs and not both cores. Then obviously you don't need/want to share the peripherals between the cores. Cool demo!

urish avatar Feb 05 '23 19:02 urish