Teensy 3.6 Problem with Mux (CD74HC4067) and Reading Buttons

Status
Not open for further replies.

ransa

Member
Hi

I have a problem that drives me crazy, same wiring and code working 100% on Arduino Mega but on Teensy 3.6 one button affects the other once.

I used a 10 K resistor between GND and data pins and 3.3v goes to the other leg of the button, please see the diagram below.

Screen Shot 2019-08-15 at 19.26.34.jpg

Even when I try to use Internal PULLUP / PULLDOWN resistors it still shows the wrong values for the button pressed.

For Example Pushing Button #0 Gives me the following result:

Pushing Button Number 0.jpg

Pushing Button #4 Gives me the following result:

Pushing Button Number 4.png

Again, same schematics and code works fine on Arduino Mega 2560 (the only difference I can think of it's 5v if that relevant)

Your help is much appreciated !

Hardware: Teensy 3.6 (3.3volt)
Software: Arduino IDE v1.8.9
Error Messages: See Above Screenshot of Serial Monitor
Wiring: See Above

Code:

/**
* This example demonstrates how to read digital signals
* It assumes there are push buttons with pullup resistors
* connected to the 16 channels of the 74HC4067 mux/demux (in my case 8 buttons)
*
* For more about the interface of the library go to
* https://github.com/pAIgn10/MUX74HC4067
*/

const int ledPin = 13;

#include "MUX74HC4067.h"

// Creates a MUX74HC4067 instance
// 1st argument is the Arduino PIN to which the EN pin connects
// 2nd-5th arguments are the Arduino PINs to which the S0-S3 pins connect
MUX74HC4067 mux(5, 0, 1, 2, 3);

void setup()
{
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH); // set the LED on
Serial.begin(9600); // Initializes serial port

// Configures how the SIG pin will be interfaced
// e.g. The SIG pin connects to PIN 3 on the Arduino,
// and PIN 3 is a digital input
mux.signalPin(4, INPUT_PULLUP, DIGITAL);
}

// Reads the 16 channels and reports on the serial monitor
// if the corresponding push button is pressed
void loop()
{
byte data;

for (byte i = 0; i < 8; ++i)
{
// Reads from channel i and returns HIGH or LOW
data = mux.read(i);

Serial.print("Push button at channel ");
Serial.print(i);
Serial.print(" is ");
if ( data == LOW ) Serial.println("not pressed");
else if ( data == HIGH) Serial.println("pressed");
}
Serial.println();
}
 
Changed the Teensy Frequency to 24Mhz and the reading looks correct now, though further testing is needed.
Can any one confirm this is really the problem ?
 
If the library was specifically made for an Arduino board it likely doesn’t take into account how much faster other boards can be. Being that the Teensy can be so much faster there typically needs to be a delay between switching addresses on the mux and reading the value of the button in your case. In my own experience it’s better to set your address, do something else while the address settles, and then read the value. This ensures that you don’t slow anything else you need to do in your program by inserting delays.
 
Yup, this problem has come up before. You need a delay between driving the mux pins and reading the input. On slow AVR boards where digitalWrite also has a lot of extra overhead in the code, the slow speed is enough. But faster boards like Teensy 3.6 will read too soon.

Look for this function inside that library:

Code:
// Selects the given channel, and enables its connection with the SIG pin by default
// Arguments:
// pin - The channel to select
// set - A flag (DISABLED, ENABLED) to indicate whether to leave the  
//       connection of the channel to the SIG pin disabled or enable it
void MUX74HC4067::setChannel(int8_t pin, uint8_t set)
{
	digitalWrite(enable_pin, HIGH);
	current_channel = pin;
	for (uint8_t i = 0; i < num_of_control_pins; ++i)
	{
		digitalWrite(control_pin[i], pin & 0x01);
		pin >>= 1;
	}
	enable_status = ENABLED;
	if ( set == ENABLED ) digitalWrite(enable_pin, LOW);
}

Add delayMicroseconds(5) at the end of this setChannel() function. Even just a few microseconds is usually plenty of the signals to stabilize.
 
Try splitting your
Code:
mux.read(i);
into
Code:
mux.setChannel(i, ENABLED);
delayMicroseconds(50); //50 microseconds is typically overkill, but a good starting number to test with
mux.read(-1); //Pretty sure you can leave the parenthesis empty, but I haven’t used this library
 
Also, beware the common advice to add a capacitor at the analog input pin. Without a mux chip, that often helps. But with a mux, it causes havoc (unless you add a long delay for the signal to stabilize). Here's a thread where that came up:

https://forum.pjrc.com/threads/3237...cted-to-74HC4051?p=92631&viewfull=1#post92631

But even with no capacitor, the Teensy input pin and your wires have a small capacitance and that mux chip has some resistance (especially if it's the older "CD40" type) which takes a short time to stabilize. Teensy 3.6 is incredibly fast compared to the older AVR boards.
 
Status
Not open for further replies.
Back
Top