Cd4051 Multiplexer Tutorial Is Here!

For sure, it shouldn’t crash it, I don’t think.
Regardless, give all those a try and keep me posted :slight_smile:

@Takumi_Ogata I tried testing again today, this time without the MUX code and just initialising the ADC. I am still getting a crash at hw.adc.Init(adc_cfg, 1);

This is my code:

/** Example of initializing multiple ADC inputs */
#include "daisy_patch_sm.h"
/** This prevents us from having to type "daisy::" in front of a lot of things. */
using namespace daisy;
using namespace patch_sm;
/** Global Hardware access */
DaisyPatchSM hw;
int main(void)
{
   /** Initialize our hardware */
   hw.Init();
    hw.StartLog(true);
    hw.PrintLine("Log Started");
   /** Configure the ADC
    *
    *  Three CV inputs (-5V to 5V -> 3V3 to 0V)
    *  A0, A6, and A2
    *
    *  This example was made for the Daisy Seed2 DFM, but the pins can be swapped for other hardware.
    */
   AdcChannelConfig adc_cfg[1];
   adc_cfg[0].InitSingle(DaisyPatchSM::A2);
   hw.PrintLine("after init single");

   /** Initialize the ADC with our configuration */
    hw.adc.Init(adc_cfg, 1);
    hw.PrintLine("after adc init");

   /** Start the ADC conversions in the background */
   hw.adc.Start();
   hw.PrintLine("after adc start");

   /** Startup the USB Serial port */
   /** Infinite Loop */
   while(1)
   {
       /** Print the values via Serial every 250ms
        *  Values will be 0 when inputs are 0V
        *  Values will be 65536 when inputs are 3v3
        *
        *  Based on the CV input circuit this means that
        *  Values will be 0 when input is 5V
        *  Values will be ~32768 when input is ~0V
        *  Values will be 65536 when input is -5V
        */
       System::Delay(250);
       int val_0 = hw.adc.Get(0); 
// OR float val_0 = hw.adc.GetFloat(0); to get vals // from 0 to 1
       hw.PrintLine("Input 1: %d", val_0);
   }
}

Hey zyxy398!

Ok, I see why it crashed.
The Init function for the Daisy Patch SM inits and starts the adc. So you could try to stop the adc right after calling hw.Init().
There’s no deinit function unfortunately.

It could be a good idea to for me to make a Patch SM version of the multiplexer example code (especially since we may make a video tutorial in the near future).

Hey, I just tried this and no more crash! Except that all the other adc and cv inputs no longer worked after that. I figured out this was because the new adc_cfg i was initialising the adc with only had a single value, the mux. I’d have to manually configure the 11 other adc pins if I wanted to use them. So in the end I do have it working, but my big question is, Is there a better way to use adc with the patch sm than to manually configure all the adc pins?

Hi Stains!

I’m sorry for the delay in response. I double checked with the team and this code that you posted on Discord seems like the simplest way to handle it actually.

Ah, but that requires a modification to the libDaisy itself, meaning I can’t easily commit this change to my own repo. I can live with it for now! Is there plans for a nicer way to configure MUX with the the patch SM that doesn’t involve modifying libDaisy or reinitialising all ADC pins?

It should be possible to pull that code out of libdaisy for cleanliness.

Either way, thank you for bringing this to our attention. We’ll have more discussion about it especially when we create a more proper tutorial for using mux :slight_smile:

1 Like

Thank you for such a nice tutorial explaining multiplexer!
As I understood for pd2dsy you do all the code in PD and in custom json file you define analog and digital pins?
How do you add digital outs in custom json file for pin 0,1 and 3?
Could you show a simple PD patch for 1 or 2 knobs coming from the multiplexer?
Thank you

1 Like

Sure!

Here’s the json file:

{
  "name": "mux",
  "som": "seed",
  "parents": {
    "pot_mux": {
      "component": "CD4051",
      "mux_count": 8,
      "pin": {
        "adc": 15,
        "sel0": 0,
        "sel1": 1,
        "sel2": 2
      }
    }
  },
  "components": {
    "knob1": {
      "component": "CD4051AnalogControl",
      "index": 0,
      "parent": "pot_mux"
    },
    "knob2": {
      "component": "CD4051AnalogControl",
      "index": 3,
      "parent": "pot_mux"
    },
    "knob3": {
      "component": "CD4051AnalogControl",
      "index": 1,
      "parent": "pot_mux"
    },
    "knob4": {
      "component": "CD4051AnalogControl",
      "index": 4,
      "parent": "pot_mux"
    },
    "knob5": {
      "component": "CD4051AnalogControl",
      "index": 2,
      "parent": "pot_mux"
    },
    "knob6": {
      "component": "CD4051AnalogControl",
      "index": 5,
      "parent": "pot_mux"
    },
    "knob7": {
      "component": "CD4051AnalogControl",
      "index": 6,
      "parent": "pot_mux"
    },
    "knob8": {
      "component": "CD4051AnalogControl",
      "index": 7,
      "parent": "pot_mux"
    }
  },
  "aliases": {
    "knob": "knob1",
    "ctrl": "knob1",
    "ctrl1": "knob1",
    "ctrl2": "knob2",
    "ctrl3": "knob3",
    "ctrl4": "knob4",
    "ctrl5": "knob5",
    "ctrl6": "knob6",
    "ctrl7": "knob7",
    "ctrl8": "knob8"
  }
}

And your patch can be something like this. The [line~] is for smoothing out the sensor data, which is especially crucial for amplitude.

1 Like

This is just great Takumi, thank you very much!

What about using some other multiplexer? Do you just change the name in the json file or this works only with the CD4051?

What are these aliases for in the json file?

As long as it has 3 selector pins like the CD4051, you should be able to keep things the same in the json file.

Hi @Takumi_Ogata , thanks for the great tutorial. I managed to change it to work with the Pod.

One noob question, if you don’t mind:

Both the pots and the multiplexer chip are powered via 3V3 Digital. Aren’t the pots supposed to be powered to 3V3 Analog and the CD4051 via 3V3 Digital?

Thanks

Has anyone got this working with the Patch SM? I see the comments above and tried to follow by editing the daisy_patch_sm.cpp but I’m having no luck at all. Example code for the Patch SM would be greatly appreciated!

Ahhh, good catch! Yes, I think it’ll be good to use the 3V3 Analog for the pots even if the 3V3 Digital was working.
Sorry about that!

1 Like

Hi otem_rellik!
I’m sorry for the delay in my response. We definitely need an example code for using mux with the Patch SM! I would love to do a video version of this tutorial in the near future and I should include how to do it with the SM as well.

In the meantime, please feel free to start a thread and let us know what code you have tried so far and we would be happy to have a closer look. It could be good to include a photo of the circuit too since that could be a factor.

What about multiplexers for switches and leds along with this potentiometer multiplexer and with using pd2dsy?
Thank you

1 Like

For switches, you can still use the "CD4051AnalogControl" like the potentiometer example since you can treat the switch as like an analog sensor that either outputs 0.0 or 1.0 where potentiometer outputs 0.0 to 1.0.

Alright, here comes a short guide on how to use the multiplexer for LEDs (pd2dsy edition)!
I HIGHLY recommend that you read the main Cd4051 multiplexer tutorial on this thread to understand how multiplexer work.

Ok, so what we need to do is send either a 0 (LOW) or 1 (HIGH) to the three selector pins, right? Well, we can use the GateOut in the json file! Now in Pure Data, we can output a digital LOW or HIGH using [send] object like this:

Screenshot 2023-08-31 at 5.37.44 PM

In addition to having three separate GateOuts for each of the three selector pins, we would need one GateOut for the COM OUT/IN pin on the multiplexer. This is the pin that is connected to the Daisy’s pin D15 in the potentiometer example. Unlike that example where we used that pin as ADC0, this pin is now used for sending out digital LOW/HIGH for the LED (similar to how we are sending digital outputs to the selector pins).

With all that in mind, here’s the json file:

{
  "name": "mux",
  "som": "seed",
  "components": {
    "select0": {
      "component": "GateOut",
      "pin": 2
    },
    "select1": {
      "component": "GateOut",
      "pin": 1
    },
    "select2": {
      "component": "GateOut",
      "pin": 0
    },
    "led_out": {
      "component": "GateOut",
      "pin": 15
    }
  }
}

You may have noticed that you can hook up the components like in the potentiometer example, except we now have LEDs instead of the potentiometer! By the way, the digital out (which you can also think of as either 0 volt or 3.3 volt) should be connected to the long leg of the LED, and the short leg to ground.

Now let’s move on to Pure Data!
Here’s a quick patch that I put together:

Every 500 milliseconds, one of the four LEDs is going to be lit up randomly! All from a single digital output pin!! And yes, you could have up to 8 LEDs :slight_smile:

pd2dsy_mux_led_1

Ok, can we light up more than one LED at a time? Yes! Check out this patch:

We are sending out an alternating LOW/HIGH to select pin 1 super fast (5 milliseconds)!!

pd2dsy_mux_led_2

And it actually works! No flickering!

OK, this all should get you started! If you understand how multiplexer work, you’ll be able to put together patches like these from scratch. Good luck, take your time, and have fun!!

3 Likes

Hi @Takumi_Ogata,

I was wondering if it would be possible to use CD4021B for switches. The schematic I found is trivial to implement, but I am not sure how to control CP, PL and DS.

Thanks

For C++ use, there is a reference about 4021 in the libDaisy document: libDaisy: SHIFTREGISTER

Because the Daisy Field uses it, you can reference the json files for pd2dsy and Oopsy usages too.

If you have any specific questions about 4021, I suggest starting a new thread as we want to focus on one component at a time here :slight_smile:

1 Like

I found some CD74HC4067 16-Channel multiplexer modules $1.60 plus tax recently. DAOKI? brand well-fabbed, marked pinouts IIRC yay 24-pin DIP form factor, too, 2.54mm headers included

2 Likes