Demultiplexing Hall Effect Sensors

Hello!
I am currently trying to multiplex 16x UGN3144 Hall Effect sensors using a CD74HC4067, my final goal being to create a 8x8 array of them (chess board). I already know that the UGN3144 gives a digital output and that the CD74HC4067 expects analog input, but I thought that wouldn't be much of an issue.
Please do excuse the horrendous wiring and overall low quality of the schematic as well as the fact that there is only one hall sensor in the image.
Try to imagine 15 more sensors wired up in the exact same manner, but for different channels.


GND, EN -> GND
S0 -> D2
S1 -> D3
S2 -> D4
S3 -> D5
C0,1,2... -> output of the UGN3144 -> 10k Ohm pull down resistor
SIG -> A0
The VCC is provided by Arduino's VBUS pin -> 5V

Using this code:

//Mux control pins
int s0 = D2;
int s1 = D3;
int s2 = D4;
int s3 = D5;

//Mux in "SIG" pin
int SIG_pin = A0;


void setup(){
  pinMode(s0, OUTPUT); 
  pinMode(s1, OUTPUT); 
  pinMode(s2, OUTPUT); 
  pinMode(s3, OUTPUT); 

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);

  Serial.begin(9600);
}


void loop(){

  //Loop through and read all 16 values
  //Reports back Value at channel 6 is: 346
  for(int i = 0; i < 16; i ++){
    Serial.print("Value at channel ");
    Serial.print(i);
    Serial.print("is : ");
    Serial.println(readMux(i));
    delay(100);
  }

}


int readMux(int channel){
  int controlPin[] = {s0, s1, s2, s3};

  int muxChannel[16][4]={
    {0,0,0,0}, //channel 0
    {1,0,0,0}, //channel 1
    {0,1,0,0}, //channel 2
    {1,1,0,0}, //channel 3
    {0,0,1,0}, //channel 4
    {1,0,1,0}, //channel 5
    {0,1,1,0}, //channel 6
    {1,1,1,0}, //channel 7
    {0,0,0,1}, //channel 8
    {1,0,0,1}, //channel 9
    {0,1,0,1}, //channel 10
    {1,1,0,1}, //channel 11
    {0,0,1,1}, //channel 12
    {1,0,1,1}, //channel 13
    {0,1,1,1}, //channel 14
    {1,1,1,1}  //channel 15
  };

  //loop through the 4 sig
  for(int i = 0; i < 4; i ++){
    digitalWrite(controlPin[i], muxChannel[channel][i]);
  }

  //read the value at the SIG pin
  int val = analogRead(SIG_pin);

  //return the value
  return val;
}

I get 0 from all channels even though I should technically get 4096 when triggering any of the sensors with a magnet.
What am I doing wrong? Any suggestion is appreciated. Thank you!

Why are you using analogue read when you know the output of the Hall effect sensors is digital?

You loop through all the multiplexer select pins, then, when that's done you read the last one and return it's value.

2 Likes

Are you suggesting that I change the pin to a digital one as well as reading the output using

int val = digitalRead(SIG_pin);

?

I have tried this, but it doesn't change anything.

Yes, you are reading a digital output so use digital read.

You need to attend to the last part of my comment. I've not given you the answer in order to give you chance to think about it.

1 Like
  • A0 is also a digital pin, use digitalRead(A0)

  • Always study the data sheet.

  • Do you have a pull-up resistor on the sensor ?

2 Likes
  • We don’t see a connection for S1 in the layout.

  • Suggest you use a counter to control the mux rather than the array.

Asking more than one question, or suggesting more than one change very often gives this kind of responce, responding to only one sentence. Why?
Is there a game to maximize the number of posts?

1 Like

Not shown is any connection between the two buses on the right side breadboard.

1 Like

You have an open collector device. Therefore it's output is either ground, or floating.

You have a resistor on its output that goes to the right most ground rail - which isn't connected to anything.

1 Like

I am especially sorry for the diagram I have attached, it is my fault for not having access to better software at the moment. The S1 is actually connected, as mentioned in my original post (S1 -> D3) and I can assure you that the breadboards are also connected between each other.

I have changed the pin to D9 while also using digitalRead().
I have tried using both pull up and pull down resistors, but all that changes is the output from 0 to 1, depending on the option.
Once again, this doesn't solve the issue - the outputs are not being influenced by triggering the sensors with magnets.

Also, Mr. @PerryBebbington, I don't fully understand what is wrong with the code provided.

Pen. Paper. Photograph. Post.

You are not reading all 16 inputs, you are reading one, or possibly none, I'm not sure.

Edit:
I'm not so sure now, can someone else take a look at the code and comment please?

Take a step back and write simple code that reads one input, when it works then modify it so it still reads one input but you can specify which one easily. When that works add code to cycle through the inputs.

1 Like
  • Try this version of your sketch.

  • See if you can follow what is being done, ask questions.

  • Add a LED with a series 220R resistor on pin 13,

//
//================================================^================================================
//

//use the GPIOs you want
byte s0                        = 2;
byte s1                        = 3;
byte s2                        = 4;
byte s3                        = 5;

int SIG_pin                    = 9;   //Mux in "SIG" pin

byte heartbeatLED              = 13;

//timing stuff
unsigned long muxTime;
unsigned long heartbeatTime;

//                                           s e t u p ( )
//================================================^================================================
//
void setup()
{
  Serial.begin(9600);

  digitalWrite(s0, LOW);
  digitalWrite(s1, LOW);
  digitalWrite(s2, LOW);
  digitalWrite(s3, LOW);

  pinMode(s0, OUTPUT);
  pinMode(s1, OUTPUT);
  pinMode(s2, OUTPUT);
  pinMode(s3, OUTPUT);

  pinMode(heartbeatLED, OUTPUT);

  pinMode(SIG_pin, INPUT_PULLUP);

} //END of   setup()


//                                            l o o p ( )
//================================================^================================================
//
void loop()
{
  //========================================================================  T I M E R  heartbeatLED
  //gives us a visual indication the sketch is running
  //is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= 500ul)
  {
    //restart this TIMER
    heartbeatTime = millis();

    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, digitalRead(heartbeatLED) == HIGH ? LOW : HIGH);
  }

  //========================================================================  T I M E R  mux
  //is it time to check the mux ?
  if (millis() - muxTime >= 1000ul)
  {
    //restart this TIMER
    muxTime = millis();

    //================================================
    //get all 16 mux inputs
    for (byte counter = 0; counter < 16; counter++)
    {
      Serial.print("Value at channel ");
      Serial.print(counter);
      Serial.print(" is : ");

      Serial.println(readMux(counter));
    }

    Serial.println("");
  }


  //================================================
  //       Other non blocking code goes here
  //================================================


} //END of   loop()


//                                         r e a d M u x ( )
//================================================^================================================
//
byte readMux(int _channel)
{
  digitalWrite(s0, bitRead(_channel, 0));
  digitalWrite(s1, bitRead(_channel, 1));
  digitalWrite(s2, bitRead(_channel, 2));
  digitalWrite(s3, bitRead(_channel, 3));

  //read this mux input.
  byte val = digitalRead(SIG_pin);

  return val;

} //END of   readMux()

//
//================================================^================================================
//

  1. That PNP is just a replacement for the UGN3144, as I couldn't find this specific sensor, and yes the wiring is done correctly.
  2. I am using the Arduino Nano ESP-32, but yet again, I couldn't find the specific model.
  3. Once again I have 15 more sensors wired up in the same manner.
    Hopefully this clears up any misunderstandings regarding the circuitry.

Here is an actual photograph of my implementation of your circuit. And it works.

I used a 74HC4051 (8 channel analog mux) because that's what I had. I used 10K pullups on all of the mux's inputs. I altered your code to loop through the first 8 addresses, and changed D2..D5 to 2..5 for the Uno. And I did a digitalRead on A0 rather than an analogRead. Those are the only changes I made.

With no magnet near any of the 3 A3144s, all inputs read as 1. When I bring a magnet close to one of them, its output flips to 0.

Conclusion: when your circuit is wired properly, your code will work.

1 Like

I think your design is too complex and has too many components.

Instead of hall-effect sensors, use reed switches. Put a small signal diode in series with each switch. Use 16 Arduino pins to read the matrix. No need for multiplexers.

@PaulRB but his goal is 64...

Yes, of course, there are 64 squares on a chessboard. Why did you say "but" ?

Although my lighting conditions are poor, hopefully you can understand the circuitry.


Neither mine, nor @LarryD's code work.
His code simply reports 1 for all, while mine... well mine is a bit more interesting since it seems to alternate between 0 and 1 for all pins (but this effect triggers when approaching the magnet to the hall sensor).
Also, I am using pin D9 for SIG.
It might be that the multiplexer has issues (?)