pfalstad / circuitjs1

Electronic Circuit Simulator in the Browser
GNU General Public License v2.0
1.64k stars 279 forks source link

feature: analog multiplexer #76

Open conversy opened 4 months ago

conversy commented 4 months ago

Hello,

the currently available Multiplexer is digital-only: the output is the "High Logic Voltage" if the selected input pin's value is True. It would be nice to have an analog option, that would basically transfer the selected input pin's voltage/current to the output. Maybe something like this in MultiplexerElm.java, though I'm not sure how the internals of CircuitJS work:

class MultiplexerElm extends ChipElm {
    final int FLAG_INVERTED_OUTPUT = 1<<1;
    final int FLAG_STROBE = 1<<2;
    final int FLAG_ANALOG = 1<<3;
...
    int getSelectedValue() {
        int selectedValue=0;
        for (int i = 0; i != selectBitCount; i++)
        if (pins[outputCount+i].value)
            selectedValue |= 1<<i;
        return selectedValue
    }

    void execute() {
        int selectedValue = getSelectedValue();
        if (hasFlag(FLAG_ANALOG)) {
        double current = pins[selectedValue].current;
        if (strobe != -1 && pins[strobe].value)
            current = 0;
        pins[outputPin].current = current;
        } else {
        boolean val = pins[selectedValue].value;
        if (strobe != -1 && pins[strobe].value)
            val = false;
        pins[outputPin].value = val;
        if (hasFlag(FLAG_INVERTED_OUTPUT))
            pins[outputPin+1].value = !val;
       }
    }

I hope this makes sense! (And congrats for this excellent software!)

pfalstad commented 4 months ago

So it would be bidirectional, right?

That wouldn't be hard, although it's not as easy as this. pins[___].current is just for reporting purposes. Modifying it does not change the circuit behavior.

I'd have to get rid of the voltage source for the output (change getVoltageSourceCount()) and instead connect the output directly to the inputs, probably using stampResistor() with a small value for the "on" input and a large value for all the "off" inputs.

conversy commented 4 months ago

Thank you for answering!

Yes, it would be bidirectional, I guess. I read somewhere that such chip has an internal resistance of about 60 ohms, for what it's worth.

[edit] added 'bi' before 'directional'

AgainPsychoX commented 3 months ago

Anyway could it be compatible with something like 74HC4052? Maybe I can use sub-circuit to simulate something like this, using MOSFETS?

AgainPsychoX commented 3 months ago

Indeed I managed to make it with sub-circuits, Or at least I think I do, it seems to working for me, please notify me if something is wrong. 😄 The simulation performance wouldn't be the same as the using pre-programmed approach, but it's neglectable unless you have very large circuits (or slow computer).

Here circuit files (multiple versions due to VCC/logic):

You can File > Open File... and then File > Create Subcircuit... and then move the outputs around and save under some name.

Notes:

Screenshot of the example circuit (using simple version): image

BTW I like CircuitJS so far, there are few annoying things, but it's huge help.

AgainPsychoX commented 3 months ago

Actually there seems to be error in the design, it doesn't work with negative VEE, which is should, and on top of that voltages are weird at best. I will investigate, try to fix it and update the design. I am not really good at electronics :/

It seems the MOSFETs inside are driven not by GND/VCC but VEE/GND logic. And one of MOSFETs seems to be upside down I think.

I will update the comment above (incl. the TXT file links).

Updated the original comment. If anything more is wrong, please let me know.

conversy commented 2 months ago

(sorry for the delay)

@AgainPsychoX thank you so much!

However, I'm not quite sure I understood how to use a subcircuit in circuitjs, even after searching through "directions" on the falstad.com site... How to add one of your circuit into my own and use it?

AgainPsychoX commented 2 months ago

(Sorry for late response, I missed the e-mail).

Here are instructions:

  1. Open the app in new tab https://www.falstad.com/circuit/circuitjs.html
  2. From the menu in right top corner: File > Open File... (or use Ctrl+O keyboard shortcut).
  3. Select the circuit file you downloaded - there are multiple versions, here I will go with 74HC4052_5V_SIMPLE.txt.
  4. The circuit contents should be loaded and displayed. From the menu: File > Create Subcircuit...: image
  5. Now you have to model the reusable element that will be representing the subcircuit.
    • Fill the model name so you can later find it. The name will also be displayed on the element if you select the Show label checkbox. I will go here with 74HC4052_5V_S.
    • You can leave pins as is, or you can move them around by pressing and dragging around. In my case, I rearranged the layout the pins to match DIP16 (flipped X&Y) because it was easiest to drop in to a simulation for a project I was working on.
    • Select the Save Across Sessions checkbox, so the subcircuit is available even in other tabs, after refresh and after browser restarts.
    • After you are finish, press "OK". image
  6. You can close the tab and/or open blank circuit, or any other target circuit where you want to place it.
  7. To place the subcircuit, use from the menu: Draw > Subcircuits > Add <name you choosen>: image
  8. Click anywhere on your circuit (or if doesn't work: press and drag a bit, it's weird sometimes). After placing the instance, you might want to exit from the drawing mode by pressing Esc or Space or using the menu: Draw > Select/Drag Sel.

That's should be it. Extra notes:

Let me know if anything is unclear, I will try to help if I can.

conversy commented 1 month ago

@AgainPsychoX Sorry I saw your answer the other day but could not find the time to implement it... Thank you so much, these are very clear explanations, that might deserve being put somewhere on the circuitjs website, so that others can find them easily...

Thanks to your explanation, I could create the part in a subcircuit and use it in another circuit.

Your design is not exactly what I expected (it seems there are two input, while I only have one in the part I want to simulate), but I can adapt yours easily I think.

Many thanks again!