Adding more analog inputs using a multiplex breakout board


#3

Here is what I beleive the wiring should look like. In this picture I only show 1 Potentiometer attached to the Multiplex board for simplicity sake. I will definitely have 16 Potentiometers attached to each pin in reality.


#4

How many extra controls are you planning on adding? Have you thought of adding them via MIDI? There are plenty of OEM MIDI controller solutions out there that would add tons of controls on top of the analog controls available by direct wiring. Both can work at the same time. Things like the Doepfer Pocket Electronics, Dial Electronics, and other boxes like it can add many custom controllers to the Axo. They may not be as cheap but they are MUCH more flexible than the multiplex approach.


#5

For the sake of this project let's say 16.

Using an additional midi device is not what I aim to do as that requires the user to buy and understand additional (potentially expensive) hardware, software and scripting (which from my experience is a rabbit hole that goes very very deep and consumes a lot of time)

The goal of this is project is to show the cheapest, simplest possible way for others to add additional inputs to their board with the least amount of steps possible so they (and I) don't get overwhemed.


#6

You can get simple small MIDI controllers quite cheaply.

You can also build one using an arduino very easily.

There is little you can't control on Axo with MIDI, I don't see much need for having more than a few rotary encoders and a display on an enclosure.

My 2 cents worth.


#7

Using a third party midi controller confines you to the controllers design and also occupies a port.

As for building a midi controller using Arduino - you need to understand Arduino to do that....just installing Arduino is like 13 additional steps...then theres the additional hardware requiried and even then you don't really get many analog inputs without spending a lot of money....unless you add a multiplexer to a cheaper arduino, which brings us right back here but now with new hardware and software ontop.

I should point out that I've built midi controllers using both teensy and Arduino and its messy/complicated when you throw in multiplexers. If the Axoloti has the capability of having a multiplexer attached to it directly, then that's definitely worth investigating in my opinion.


#8

I've managed to take a look at the contents of Paul's patch from https://sebiik.github.io/community.axoloti.com.backup/t/gpio-i-o-example-4051-de-multiplexer-reads-8-analog-sources/133 using a simple text editor (wordpad for the win!)

My guess is that the file was made for a previous version of Axoloti's patcher software but it's all there and looks like its full of handy info and code that seems like it could be modified to suit a 16 input multiplex.

He also mentioned in his initial post this helpful bit of info:

By editing the number between the brace at line "adcvalues[8]", you can select the adc input pin.
Here is a short overview about the possible adc pins.

PA1 (ADC1_IN1) = 1
PA2 (ADC1_IN2) = 2
PA3 (ADC1_IN3) = 3
PA4 (ADC1_IN4) = 4
PA5 (ADC1_IN5) = 5
PA6 (ADC1_IN6) = 6
PA7 (ADC1_IN7) = 7
PB0 (ADC1_IN8) = 8
PB1 (ADC1_IN9) = 9
PC0 (ADC1_IN10) = 10
PC1 (ADC1_IN11) = 11
PC2 (ADC1_IN12) = 12
PC3 (ADC1_IN13) = 13
PC4 (ADC1_IN14) = 14"

I edited out some things to clean up this post but if you would like to view Paul'd work completely unedited you can just open his file (https://sebiik.github.io/community.axoloti.com.backup/uploads/default/original/1X/46b83d76dc9f2e7ed70a454f90b238b49df6c79a.axp) using wordpad.

this is his work:

<patch-1.0>
4051 De/Multiplexer
Object script reads analog ins from a 4051
z  = PB0
s0 = PA0
s1 = PA1
s2 = P A2

obj type="script/script2" sha="362a4413ceaefbe716480bf8f9c62eb3587fe6c0" name="multiplexer_count" x="42" y="126">
      <params/>
      <attribs>
         <text attributeName="script">
            <sText><![CDATA[

int i;   // select y-input

void setup(void){
	palSetPadMode(GPIOA,0,PAL_MODE_OUTPUT_PUSHPULL);	// s0 Pin of 4051
	palSetPadMode(GPIOA,1,PAL_MODE_OUTPUT_PUSHPULL);	// S1 Pin of 4051
	palSetPadMode(GPIOA,2,PAL_MODE_OUTPUT_PUSHPULL);	// s2 Pin of 4051

	i = 0;
}

void loop(void){

	i++;
	if (i == 8) {
		i = 0;
	}

	palWritePad(GPIOA,0,((i& 0x01) > 0));		// write s0
	palWritePad(GPIOA,1,(((i>>1)& 0x01) > 0));	// write s1
	palWritePad(GPIOA,2,(((i>>2)& 0x01) > 0));	// write s2

	int z = adcvalues[8]<<15;			// ADC z-input

	switch (i){
		case 0: PExParameterChange(&parent->PExch[PARAM_INDEX_y0_value],z,0xFFFD); break;	//connect in1 to dial (named y0)
		case 1: PExParameterChange(&parent->PExch[PARAM_INDEX_y1_value],z,0xFFFD); break;	//connect in2 to dial (named y1)
		case 2: PExParameterChange(&parent->PExch[PARAM_INDEX_y2_value],z,0xFFFD); break;	//connect in3 to dial (named y2)
		case 3: PExParameterChange(&parent->PExch[PARAM_INDEX_y3_value],z,0xFFFD); break;	//connect in4 to dial (named y3)
		case 4: PExParameterChange(&parent->PExch[PARAM_INDEX_y4_value],z,0xFFFD); break;	//connect in5 to dial (named y4)
		case 5: PExParameterChange(&parent->PExch[PARAM_INDEX_y5_value],z,0xFFFD); break;	//connect in6 to dial (named y5)
		case 6: PExParameterChange(&parent->PExch[PARAM_INDEX_y6_value],z,0xFFFD); break;	//connect in7 to dial (named y6)
		case 7: PExParameterChange(&parent->PExch[PARAM_INDEX_y7_value],z,0xFFFD); break;	//connect in8 to dial (named y7)
	}

	
	chThdSleepMilliseconds(5);	// short delay
}]]></sText>
         </text>
      </attribs>
   </obj>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y0" x="42" y="224">
      <params>
         <frac32.u.map name="value" value="0.046875"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="266" text="4051 Input Y0"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y1" x="42" y="308">
      <params>
         <frac32.u.map name="value" value="63.984375"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="350" text="4051 Input Y1"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y2" x="42" y="392">
      <params>
         <frac32.u.map name="value" value="0.03125"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="434" text="4051 Input Y2"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y3" x="42" y="476">
      <params>
         <frac32.u.map name="value" value="0.09375"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="518" text="4051 Input Y3"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y4" x="42" y="560">
      <params>
         <frac32.u.map name="value" value="0.0"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="602" text="4051 Input Y4"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y5" x="42" y="644">
      <params>
         <frac32.u.map name="value" value="0.203125"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="686" text="4051 Input Y5"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y6" x="42" y="728">
      <params>
         <frac32.u.map name="value" value="63.984375"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="770" text="4051 Input Y6"/>
   <obj type="ctrl/dial p" sha="1f21216639bb798a4ea7902940999a5bcfd0de90" name="y7" x="42" y="812">
      <params>
         <frac32.u.map name="value" value="0.0625"/>
      </params>
      <attribs/>
   </obj>
   <comment type="patch/comment" x="126" y="854" text="4051 Input Y7"/>
   <nets/>
   <settings>
      <subpatchmode>no</subpatchmode>
   </settings>
   <notes><![CDATA[]]></notes>
   <windowPos>
      <x>2263</x>
      <y>35</y>
      <width>998</width>
      <height>998</height>
   </windowPos>
</patch-1.0>

Axoloti maybe it just needs to be added to a new object?


#9

If you use a board like the Doepfer Pocket Electronics, you just add 16 switches, pots or whatever just like you do on the Axo. You are not confined to any design any differently than you are with the Axo itself. It has a MIDI in and out so it can be put in series with whatever else you have plugged into the MIDI port and takes nothing away. It can be programmed to use any MIDI channel or multiple channels. The only downside is that it is not super cheap (almost twice as expensive as the Axo) but it is a simple and easy solution. There are many boards out there that are similar in design and vary a lot in cost. Customized MIDI controllers are quite prevalent and there are many makers of these devices to choose from. (google custom MIDI controller)


#10

Is that product even available anymore?
Either way your right, its not cheap. its literally 45 times more expensive than the breakout board on ebay right now and its much larger than the breakout board....

The CD74HC4067 breakout board I'm suggesting be used is 5 dollars and can be used to do all of those things no?

What other midi boards are on the market though? Outside of this project I'm interested!


#11

The PCB version is still available but you are right at $110 (Analogue Haven has them) it is much more expensive than even a Arduino or Raspberry Pi solution. Its main draw is that it is bone simple to use. Just add the controls you want and plug it in. Make as many as you want and put them in series assigned to different channels. Mainly it is the more expensive but easier solution for people like me. No real programming needed etc. Definitely not for everyone and especially not if the budget is a super concern. The advantage is of course the MIDI controller you make with the Pocket Electronics or Livid Brain Jr. ($50 solution), Arduino, or other setup, can be used with any MIDI hardware including probably the DAW or other software you record on.


#12

Niccce.
Those sound pretty sweet. Teensies are similar in their simplicity..Arduino is too but it depends on the board and you can plug them both into just about anything via usb...via midi-5 pin is a bit trickier and multiplexing teensy is a genuine fiasco.

Regardless, lets try to like...stay focused on the goal here.
What I'm suggesting is possible and seems simpler.
I know there's other options out there but for the purpose of this thread lets leave them for another day.


#13

I am new to this and I am getting a little bit confused with so many breakout boards out there. For example what are the differences between the mux board you mention (CD74HC4067) and this one https://www.sparkfun.com/products/13601 ?
Which one's better and why?


#14

That one is better and amazing? lol I've not read up on those yet!
Im defintiely going to have to check em out (less soldering involved, but I'm not sure how to write code for those at all...yet...)


#15

Alllrighty so things are starting to work now! :smiley: I'm modeling this after Paul's patch and its not working %100 but things are responding! :sweat_smile:

I've added a script object into a new patch file and threw a modified version of Paul's code to it that includes an extra "S" pin from the Axoloti to the breakout board and set things up so the code runs through all 16 inputs on the breakout rather than just 8

I then added 16 different dials to the patch, each with different names ranging from y0 to y15 to correspond with the script.

So far all 16 dials seem to be responding to input but they're all taking input from one potentiometer for some odd reason...
Theres also some jitter going on. I have quite a few capacitors laying around but I'm not sure exactly where to put them...i think they may resolve the jitter issue though....I think this issue can be resolved using code as well (I did a similar project using an arduino a while ago that solved this problem quite nicely but I dont know how to implement that code into this project :confused:

heres a picture of what it looks like (I attached an oscilator and output to it in order to hear how bad the jitter was....I chose that dial at random because each dial is outputting almost identical signals....

Here's the patch so far if anyone wants to tinker with it....warning though - i hav't properly commented anything so its probably hella confusing (im not a programmer and have no idea what im doing obviously)
16inputs16respondbut1value.axp (7.3 KB)

and heres the code for those who want to take a look but dont want to download the patch

int i;   // select y-input

void setup(void){
	palSetPadMode(GPIOA,0,PAL_MODE_OUTPUT_PUSHPULL);	// s0 Pin of 4051
	palSetPadMode(GPIOA,1,PAL_MODE_OUTPUT_PUSHPULL);	// S1 Pin of 4051
	palSetPadMode(GPIOA,2,PAL_MODE_OUTPUT_PUSHPULL);	// s2 Pin of 4051
	palSetPadMode(GPIOA,3,PAL_MODE_OUTPUT_PUSHPULL);	// s3 Pin of 4051
	i = 0;
}

void loop(void){

	i++;
	if (i == 16) {
		i = 0;
	}

	palWritePad(GPIOA,0,((i& 0x01) > 0));		// write s0
	palWritePad(GPIOA,1,(((i>>1)& 0x01) > 0));	// write s1
	palWritePad(GPIOA,2,(((i>>2)& 0x01) > 0));	// write s2
	palWritePad(GPIOA,3,(((i>>3)& 0x01) > 0));	// write s2
	int z = adcvalues[14]<<15;			// ADC z-input

	switch (i){
		case 0: PExParameterChange(&parent->PExch[PARAM_INDEX_y0_value],z,0xFFFD); break;	//connect in1 to dial (named y0)
		case 1: PExParameterChange(&parent->PExch[PARAM_INDEX_y1_value],z,0xFFFD); break;	//connect in2 to dial (named y1)
		case 2: PExParameterChange(&parent->PExch[PARAM_INDEX_y2_value],z,0xFFFD); break;	//connect in3 to dial (named y2)
		case 3: PExParameterChange(&parent->PExch[PARAM_INDEX_y3_value],z,0xFFFD); break;	//connect in4 to dial (named y3)
		case 4: PExParameterChange(&parent->PExch[PARAM_INDEX_y4_value],z,0xFFFD); break;	//connect in5 to dial (named y4)
		case 5: PExParameterChange(&parent->PExch[PARAM_INDEX_y5_value],z,0xFFFD); break;	//connect in6 to dial (named y5)
		case 6: PExParameterChange(&parent->PExch[PARAM_INDEX_y6_value],z,0xFFFD); break;	//connect in7 to dial (named y6)
		case 7: PExParameterChange(&parent->PExch[PARAM_INDEX_y7_value],z,0xFFFD); break;	//connect in8 to dial (named y7)
		case 8: PExParameterChange(&parent->PExch[PARAM_INDEX_y8_value],z,0xFFFD); break;	//connect in1 to dial (named y0)
		case 9: PExParameterChange(&parent->PExch[PARAM_INDEX_y9_value],z,0xFFFD); break;	//connect in2 to dial (named y1)
		case 10: PExParameterChange(&parent->PExch[PARAM_INDEX_y10_value],z,0xFFFD); break;	//connect in3 to dial (named y2)
		case 11: PExParameterChange(&parent->PExch[PARAM_INDEX_y11_value],z,0xFFFD); break;	//connect in4 to dial (named y3)
		case 12: PExParameterChange(&parent->PExch[PARAM_INDEX_y12_value],z,0xFFFD); break;	//connect in5 to dial (named y4)
		case 13: PExParameterChange(&parent->PExch[PARAM_INDEX_y13_value],z,0xFFFD); break;	//connect in6 to dial (named y5)
		case 14: PExParameterChange(&parent->PExch[PARAM_INDEX_y14_value],z,0xFFFD); break;	//connect in7 to dial (named y6)
		case 15: PExParameterChange(&parent->PExch[PARAM_INDEX_y15_value],z,0xFFFD); break;	//connect in8 to dial (named y7)
	}


	
}

if anyone out there knows what theyre doing and wants to take a crack at helping, be my guest!


CD74HC4067 mux programming
#16

It would be much easier to add multiplexing to Arduino than to Axo, the added complexity of the software, and hardware, and lack of documentation make it much harder.

Input shift registers are pretty simple, no need for a i/o expander chip and all the software is pretty much freely available already for Arduino.

You coiuld prototype a board with Arduino then plug it into Axo once you knew it was working right.


#17

I actually already have.....Also already did the same thing with a Teensy LC (although for that one I made a USB out version)

There's a really good tutorial on youtube that walks people through how to use an Arduino nano that also has code included which smooths out the of mux signals.....

With that being said, this project is different. It wont require a teensy or arduino. When its done, all you'll need is the breakout board and the object added to your patch for it to work.


#18

Not sure if you are aware or not, but you can chain two mux IC's together, to do so will only take up 1 more Axo GPIO.
Also the general rule of thumb when using Mux's is that you can only change one parameter at a time, so you connot change one pots value with your left hand and another with your right at the same time.
There are some convoluted codes out there that provide alternatives, but they are not true multiple parameter adjustments. The only true way of dealing with this, is an Analogue input for each pot. Some muxes can be controlled via I2C which uses a different communication technique, but I am not familiar with its efficiencies.
:grin:


#19

True! That being said, how will it sound when the Axo flipflops between two params X number of times per second? Im excited to find out....i might be m.i.a. for a while though (lung surgery problems) so I'll check back in when I'm all together again.


#20

Hey! Would you have to manually connect a midi cable from the OEM controller into the axoloti?


#21

Have you made further progress with this?
I just bought a second axoloti and Im preparing to make a drum machine/sequencer/sampler out of it and need tons of switches and LEDs so im debating this as well...


#22

I think my comments above a year ago, is a bit out of date and incorrect, amazing what you can learn in a year.

I am in the process of building a midi controller, 37 pots, 40 mom buttons, led's will be added at a later date.
After all my investigations and tests, I will be using 10 x 4051 analog mux ic's. I will be using an arduino to create the midi, the 10 ic's will take up, 3 x digital outs, 5 digital ins, and 5 analog ins. Same can be done on the axo.
The difference is, I can take code from others to implement, not sure if any Axo members have any code to offer for this. But if required, it should not be too difficult to implement, just need to sequence through 8 inputs on the mux through the digital outs, and read the inputs for each of the inputs 8 times for each sequence.
There are some mux's that will take 16 inputs, but I have chosen the 8. In fact now that I think about it, you may not need to code at all, all should be possible through standard Axo objects.
:grin: