Library for 4051 analog Multiplexer / Demultiplexer

Hi all,

So I've been using these ICs quite a bit recently and whilst they are pretty straight forward to get up and going code wise I found I was copy-pasting a bunch of code into each new project (or iterations of a project) as I've been working on them.

With that in mind and for anyone remotely interested in using it, it's here and available on GitHub.

Obviously any issues or questions please hit me up here, twitter (preference) or log me an issue in GitHub and take a look to fix.

Known incompleteness:

  1. No example for analog multiplexing (reading) at the moment. Will do this tonight as just need to strip back one of my apps back to a reasonable example

  2. Can't currently switch between input and output in code, this has to be done manually. My rationale is it would be pretty rare you were reading and writing off the same IC... (well that's me anyway).

Cheers
ajfisher

Good you are making a library for the 4051.

Some remarks after a quick look at the code,

If I understand it correctly I see an endless recusion between:

int AnalogMux::AnalogRead() {
  // this method reads the currently selected pin and returns the value
  return analogRead(_readpin); <<< THIS LINE CALLS 2nd function
  
}
int AnalogMux::AnalogRead(int pin) {
  // this method calculates which pin to read, switches to it and then returns
  // the currently value
  SelectPin(pin);
  return AnalogMux::AnalogRead();  <<< THIS LINE calls 1st function
}

Can you confirm this?

Furthermore: consider using unsigned integers for parameters as pin number cannot be < 0. using the uint8_t datatype [0..255] is probably sufficient in all places where now an int is used except for the return value of the analogRead(). This reduces the footprint of the library and it RAM usage.

Finally: Arduino libs prefer camelCase => analogRead() iso AnalogRead() - estethic issue, not a bug, just taste.

Q: Errorhandling?

  • is there a way to test if there is a 4051 connected?
  • how do you handle invalid pinNumbers?

Rob

Hi Rob,

Thanks for the feedback.

Okay so I'm going to take the first and last points first. After some mucking around I was getting some namespace issues (more pertinent on the write side) where it was calling the local function even without the namespace defined which was a little weird. As I couldn't find the package which contains the global Arduino analogRead and analogWrite function so I could explicitly refer to them by namespace I decided that I would keep the function names conceptually similar and then change everything in the module to use ProperCasing for the function names.

If anyone knows the package that standard analogRead and analogWrite are in then I'll change this to use the correct namespaces. If not then I may change the functions altogether to something like muxAnalogRead() etc which will keep them a lot more separate....

Great point on using unsigned - will switch that.

Re error handling:

I've been having a think about this - there's no real way (as I see it anyway) to check whether the 4051 is connected - you're essentially manipulating the signal on 3 digital pins and then one Analogue IN or OUT - technically these could all be going elsewhere and you'd end up with some interesting effects...

PinNumbers are coming. Am going to set up some checks and then error handling to deal with it. My plan is to expand this to be able to deal with chained mux/demuxers so you can end up with 16 or 24 etc inputs or outputs - to do this you have to add additional control lines, so I'll need to do some refactoring to deal with this...

Cheers
ajfisher

OK I know it is no recursion but it looked like it ...

analogRead() can be found in - ~\arduino-0021\hardware\arduino\cores\arduino\wiring_analog.c

If not then I may change the functions altogether to something like muxAnalogRead() etc which will keep them a lot more separate....

imho that will be far more clear for the users of the lib to have one clear name. If you want it to look and feel like the standard analogRead(int pin) you should only make the version with the parameter public. Keep the interface of the class as simple as possible, e.g. something like below (mux4051.cpp only)

#include "WProgram.h"
#include "analogmuxdemux.h"

// datasheet - http://pdf1.alldatasheet.com/datasheet-pdf/view/173652/UTC/4051.html
// S0, S1, S2 are the selection pins 
// readPin is the analog pin from the Arduino to be multiplexed. 
mux4051::mux4051(uint8_t S0, uint8_t S1, uint8_t S2, uint8_t readPin)  
{
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  _S0 = S0;
  _S1 = S1;
  _S2 = S2;
  _readPin = readPin;
}

int mux4051::analogRead(uint8_t pin)
{
  // if (pin > 7) pin = 7; 
  digitalWrite(_S0, bitRead(pin, 0));    
  digitalWrite(_S1, bitRead(pin, 1));    
  digitalWrite(_S2, bitRead(pin, 2));   
  return analogRead( _readPin);
}

What do you think of this proposal ?
Rob
ps - demux likewise of course...

Hi Rob,

So in my original code when I was doing this I had something pretty much the same as that however it DIDN'T call the arduino analogWrite at that point, it called the version in my library instead which seemed quite weird as I thought the global function would get called (as I didn't make it explicit by namespace).

I can probably find the code pre-changeset where I had this issue to show you the code (though semantically it's pretty much what you've got) - hence why I was asking about a way to refer to the ardunio analogWrite / Read functions explicitly using a name space because if I do that it would avoid the conflict I'm seeing.

Any thoughts on that? I'm definitely keen to sharpen that side of things up to make it a better interface for users.

Cheers
Andrew