mermaid-js / mermaid

Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
https://mermaid.js.org
MIT License
70.03k stars 6.21k forks source link

[Feature Request] Electrical circuit diagrams #2112

Open gliu20 opened 3 years ago

gliu20 commented 3 years ago

Is your feature request related to a problem? Please describe. N/A

Describe the solution you'd like It would be nice to be able to specify the connections between each circuit element and have mermaid-js figure out the circuit. I believe this was requested in the past (see issue #811) but the issue was closed due to lack of activity

Describe alternatives you've considered N/A

Additional context N/A

pvgmenegasso commented 1 year ago

Anybody working on this ? Thinking about starting to implement this feature

pvgmenegasso commented 1 year ago

https://github.com/pvgmenegasso/mermaid/tree/feature-2112-electrical-circuits

konsumer commented 1 year ago

I worked on this a bit, a long time ago, but forgot about it. I still think it's a great idea, though. I think we need to figure out the input & output we expect, first.

The example I gave in the other issue was this:

graph TD

R1[1M]
R2[10K]
U1[Arduino Nano]
U2[F0D420]

500V --- R1
R1 --- R2
R1 -- A0 --- U1
R2 --- GND1
500V -- 6 --- U2
U2 -- 4 --- VOUT
U2 -- 1-D2 --- U1
U2 -- 2-GND --- U1
graph TD

R1[1M]
R2[10K]
U1[Arduino Nano]
U2[F0D420]

500V --- R1
R1 --- R2
R1 -- A0 --- U1
R2 --- GND1
500V -- 6 --- U2
U2 -- 4 --- VOUT
U2 -- 1-D2 --- U1
U2 -- 2-GND --- U1

Maybe a first pass is a squared-off layout instead of "bug" and a rudimentary mapping of names?

So to parse this, R means "resistor" and U means "chip" (with pins as the connection-label) and the unknowns are busses (500V and GND)

Maybe a sensible structure to shoot for for input?:

circuit

R1[1M]
R2[10K]
U1[Arduino Nano]
U2[F0D420]

500V --- R1
R1 --- R2
R1 -- A0 --- U1
R2 --- GND1
500V -- 6 --- U2
U2 -- 4 --- VOUT
U2 -- 1-D2 --- U1
U2 -- 2-GND --- U1

But also, netlistsvg can do really fancy stuff with an existing netlist format (yosys JSON.)

AND

It uses elkjs for layout, which might be cool for other mermaid-things:

Screenshot 2023-07-12 at 10 43 16 AM

It seems like the main trick is the skin-lookup, where if you have this cell:

"cells": {
        "<cell name>": {
          "type": "<type name>",
          "parameters": {
            "WIDTH": 3,
            ...
          },
          "port_directions": {
            "<port name>": "<input|output>",
            ...
          },
          "connections": {
            "<port name>": [ 3, "0", ... ],
            ...
          }
      },

It will check the skin (an SVG file with groups, like this) for <cell name> and add it to the layout. It might be possible to do the same thing with mermaid/d3 layout stuff (so we don't need elk, which is a big wasm/js lib.)

I like that this JSON format already exists, but I find the format of my hacked graph TD much easier to read, so I dunno.

I found this which uses the JS layout engine that elk was based on so we might be able to use that for some layout, if the layout stuff already in mermaid can't do it.

konsumer commented 1 year ago

I noticed some of elk here so maybe just inlining that makes sense.

IGitYou commented 1 year ago

I would love this and it would complement my use of mermaid. Subscribed

marmitetype commented 10 months ago

This would be really useful, has anyone found any other resources to do this?

rexolion commented 9 months ago

Will be great to add this type! Subscribed

grahame-student commented 8 months ago

This would be great to include in project documentation!

MrSinho commented 6 months ago

I believe it would be very useful to create electrical circuits with mermaid. Many programmers have some electrical engineering background and I think at least a few of them have felt the need to draw electrical circuits.

RarityBrown commented 4 months ago

Based on the flowchart, it would be easier to first add support for block diagrams. There are mainly four steps required for preliminary support, each step being independent of the others, and the difficulty and specificity increasing sequentially. Below is the first step:

After completing this step, we can approximately depict some simple Block Diagrams as shown below:

Superheterodyne receiver block diagram

flowchart-elk LR
    a["📡"]:::Trans 
    --- LNA{"RF amp"}:::BlackWhite
    -->Mixer1(("`**✕**`")):::BlackWhite
    -->filter["〰\n∿\n〰"]:::BlackWhite_05
    ---A1{"IF amp"}:::BlackWhite
    ---d["-▶|-"]:::BlackWhite
    ---A2{"PA"}:::BlackWhite
    ---speaker["🔊"]:::Trans

    osc["∿"]:::BlackWhite_10-->Mixer1

    classDef Trans fill:#ffffff00,stroke-width:0px,font-size:30pt;
    classDef BlackWhite fill:#ffffff00,stroke:#000,stroke-width:2px;
    classDef BlackWhite_05 fill:#ffffff00,stroke:#000,stroke-width:2px,line-height:0.5;
    classDef BlackWhite_10 fill:#ffffff00,stroke:#000,stroke-width:2px,line-height:1.0;

The source code uses a lot of Unicode and some less common features, and it was not easy to draw:

flowchart-elk LR
    a["📡"]:::Trans 
    --- LNA{"RF amp"}:::BlackWhite
    -->Mixer1(("`**✕**`")):::BlackWhite
    -->filter["〰\n∿\n〰"]:::BlackWhite_05
    ---A1{"IF amp"}:::BlackWhite
    ---d["-▶|-"]:::BlackWhite
    ---A2{"PA"}:::BlackWhite
    ---speaker["🔊"]:::Trans

    osc["∿"]:::BlackWhite_10-->Mixer1

    classDef Trans fill:#ffffff00,stroke-width:0px,font-size:30pt;
    classDef BlackWhite fill:#ffffff00,stroke:#000,stroke-width:2px;
    classDef BlackWhite_05 fill:#ffffff00,stroke:#000,stroke-width:2px,line-height:0.5;
    classDef BlackWhite_10 fill:#ffffff00,stroke:#000,stroke-width:2px,line-height:1.0;
flowchart-elk LR
    An-->S-->L
    M1-->C1-->AD1
    M2-->C2-->AD2
    subgraph A
        Q-->M1
        Q-->M2
        LO-->Q
        L-->M1
        L-->M2
    end
flowchart LR
    An-->S-->L
    M1-->C1-->AD1
    M2-->C2-->AD2
    subgraph A
        Q-->M1
        Q-->M2
        LO-->Q
        L-->M1
        L-->M2
    end

These four steps are just preliminary support for the most basic block diagrams, considering the diversity of circuit levels and the complexity of circuit topologies, to support all circuit diagrams from transistor level to system level is likely to require a huge investment:

Transistor-level circuits Analog and mixed-signal circuits Digital circuits System-level circuits (Block Diagrams) System-level architectures
NE555 Internal Circuit NE555 Block Diagram Digital Logic Circuit Regenerative receiver block diagram IBEX core
image RF Analog and Mixed Signal Integrated Circuits SKY130 OpenFPGA Delta-Sigma Modulation ADC and DAC Microchip Automotive System
RarityBrown commented 4 months ago

Projects worth referencing: Lcapy, Schemdraw, d3-hwschematic, SKiDL, netlistsvg, CircuiTikZ, circuit_macros (link2), PySpice

konsumer commented 4 months ago

I have been working in puredata a lot lately, and this reminds me of that. maybe a similar approach of not really trying to make seperate shapes, and use text to show what things are would help. I think this + squared-routing would get us readable schematics, even if they were not completely traditional.

Here is a simple example of a sinewave (osc~) connected to output (dac~) with an audio-multiple (*~) for "volume".

Screenshot 2024-04-05 at 1 49 06 PM

It has 2 controls for toggling volume & picking a midi note, but those could be signal refs (which, in puredata are done with receive and send.) All could be signals (similar to "bus" in electronics) like this:

Screenshot 2024-04-05 at 1 54 20 PM

It's a bit of a leaky abstraction in puredata, since it's not really made for it, but here is my shot at the RF thing, above:

Screenshot 2024-04-05 at 2 05 12 PM

With more squared routing, I think it would look pretty decent & readable, even though it doesn't really reproduce the same diagram. I made it by making fake puredata sub-patches for all the things, just to show what I mean. In mermaid, it's already easier:

flowchart TD
    Antenna
    Antenna-->SAW
    SAW-->LNA
    LNA-->M1["Mixer"]
    LNA-->M2["Mixer"]
    M1-->Q["Quadradure Generator"]
    M2-->Q
    Q-->C1["Channel Selection Filter"]
    Q-->C2["Channel Selection Filter"]
    C1-->A1["ADC"]
    C2-->A2["ADC"]

It might be a bit tricky, but if there were a new mode (similar to flowchart TD) that did squared-routing, and knew for example names with R prefix are "resistors", I could see something similar to this actually creating a readable electronic schematic:

schematic
   V["5V"]-->R1["100"] -->|+| D1["LED"] -->|-| GND
flowchart TD
    V["⌁ 5V"]-->R1["100  Ω"] -->|+| D1["→| LED"] -->|-| GND