looking around about mutliplexers i found a hc4067-board in my fiddle-box..
in github have the found the Multiplexer4067-lib
but the examples-directory is very poor, only for reading ..
may be i could use that for reading sensors..
but my goal is to drive bistable-relais by it , so there writing is needed
until now i could not find any functions list for the Multiplexer4067-lib
and do example for wirting..
// Blinks an LED attached to a HC4067 pin.
#include <Wire.h>
//- ergaenzt durch LCD-Anzeige zur Adressklaerung
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
#define LED_PIN1 0 // HC4067 pin LED is attached to
#define LED_PIN2 1 // HC4067 pin LED is attached to
// declare the lcd object for auto i2c address location
hd44780_I2Cexp lcd;
// LCD geometry
const uint8_t LCD_COLS = 16;
const uint8_t LCD_ROWS = 2;
uint8_t lcd_status = 0;
String message = "";
// control pins output table in array form
// see truth table on page 2 of TI 74HC4067 data sheet
// connect 74HC4067 S0~S3 to Arduino D7~D4 respectively
// connect 74HC4067 pin 1 to Arduino A0
byte controlPins[] = {B00000000,
B10000000,
B01000000,
B11000000,
B00100000,
B10100000,
B01100000,
B11100000,
B00010000,
B10010000,
B01010000,
B11010000,
B00110000,
B10110000,
B01110000,
B11110000 };
// holds incoming values from 74HC4067
byte muxValues[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,};
void setup()
{
Serial.begin(9600);
//while (!Serial);
Serial.println("HC4067 Blink Test!");
lcd_status = lcd.begin(LCD_COLS, LCD_ROWS);
Serial.print("LCD-Status : " + String(lcd_status));
if (lcd_status) // non zero status means it was unsuccessful
{
// begin() failed so blink error code using the onboard LED if possible
//hd44780::fatalError(status); // does not return
}
delay(1000);
message = "HC4067_wLCD for Nano";
Serial.print(message);
lcd.clear();
lcd.print(message);
delay(1000);
DDRD = B11111111; // set PORTD (digital 7~0) to outputs
Serial.println("Setup ready");
lcd.clear();
lcd.print(message);
delay(1000);
}
void loop()
{
for (int i = 0; i < 16; i++)
{
setPin(i);
delay(250);
}
}
void setPin(int outputPin)
// function to select pin on 74HC4067
{
PORTD = controlPins[outputPin];
}
running this code the sketch seems to stop at
DDRD = B11111111; // set PORTD (digital 7~0) to outputs
setup is not fullfilled !
but why that is compiled without any error-message ?
It has a minimalistic interface that covers its functionality.
HC4067(uint8_t s0, uint8_t s1, uint8_t s2, uint8_t s3, uint8_t enablePin = 255) constructor. Set the 4 select pins and optional the enable pin. If the enablePin == 255 it is considered not used.
void setChannel(uint8_t channel) set the current channel. Valid values 0..15, this value is not checked, only the lower 4 bits will be used.
uint8_t getChannel() get current channel 0..15.
void enable() idem.
void disable() idem.
bool isEnabled() idem. Also returns true if enablePin is not set.
That is about all it can do.
until now i could not find any functions list for the Multiplexer4067-lib
and do example for wirting..
As far as I know the HC4067 has no buffered output. I still need to investigate how multiplexing digitalWrite() behaves in detail.
/**
* This example demonstrates how to write digital signals
* It assumes there are LEDs+resistors with the positive lead of the LEDs
* connected to the 16 channels of the 74HC4067 mux/demux, respectively
*
* For more about the interface of the library go to
* https://github.com/nlamprian/MUX74HC4067
*/
//- writeDigitslSignals1 for A.nano
#include <Wire.h>
#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(7, 8, 9, 10, 11);
MUX74HC4067 mux(4, 8, 9, 10, 11);
void setup()
{
Serial.begin(9600);
Serial.println("MUX74HC4067- instance loaded");
delay(500);
// 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 Output
mux.signalPin(3, OUTPUT, DIGITAL);
Serial.println("MUX74HC4067- S-PIN 3 set");
delay(500);
}
// Writes to the 16 channels a HIGH value, one after the other
void loop()
{
for (byte i = 0; i < 16; ++i)
{
Serial.println("C-PIN "+String(i)+" set TO HIGH");
mux.write(i, HIGH); // Connects to channel i and writes HIGH
//delay(25);
delay(1500);
mux.write(i, LOW); // Connects to channel i and writes HIGH
delay(25);
Serial.println("C-PIN "+String(i)+" set TO LOW");
delay(1000);
}
mux.disable(); // Disconnects the SIG pin from any channel
delay(2000);
}
looking in the cpp-file if possible shows which funtions are public
so i can see whats to do or not..but now i have to to different jobs first..
have a good day all
@alto777
Just finished my investigation. Learned the following from my library and the 4067.
when disabled all lines go LOW
when a channel is not selected it will go LOW
my implementation of setChannel() has a bug when used for write / OUTPUT
The second point indicates there is no buffering of the level.
The latter is only a bug when writing. my setChannel() uses four digitalWrite() calls to set the channel select pins. This may cause "ghost" channels selected for a very short time. Which channels these are depends on the previous and new value of channel.
If the values only differ in 1 bit place there will be no ghost channel. If all 4 bits differ, there will be 3 ghost channels selected. Although only for a brief moment this is definitely unwanted. The effect is only visible when a HIGH is multiplexed by the way.
Note: this effect does not occur when using direct register manipulation as all bits are set at the same time. This is however board specific and therefor not portable.
my bistable relays are managed by a bultin-FlipFlop,
so input to this does not need high currents..in opposite,
its very sensitive i.e. by instability of power !
that i supposed too seeing the light dimmering of the leds..
will measure this next..
OK, now I see what you were investigating, I think.
Since the part is an analog/digital multiplexer, I see the question that comes up.
But how strong is the LOW on inselected (or disabled) channels?
I guess the surprise unpleasant is finding that it is relatively strong enough to need to worry about and account for.
Now you have some good stuff to add to your library… recognize that all address pins come from one port and use direct port manipulation.
Just kidding. To do that across the world of Arduoni I think that would be a nightmare. So maybe another constructor or whatever the instantiating method is, where we could say look these are all on port whatever, so we have an UNO we can hand a port and a mask over, or something like that.
No electric engineer but MOSFETS have very little resistance when conducting (that's why they can handle larger currents) so I think it is almost a direct to GND connection.
In my library I have handled the bug as follows: (pseudo code)
So the old channel goes to LOW due the disable() and the the intermediate ghost channels all stay LOW and only when the new channel is set that line is enabled and can go to HIGH.
So in practice I replaced the ghost channels with a gap of ALL LINES LOW, which is imho an acceptable trade off (to keep code portable). Duration measured 20-36 us and 26 us on average to setChannel() on AVR
An AVR specific setChannel() is a good idea although one needs to hold the register and bitmask.
Food for thoughts...