I'm using a MCP23016 with ESP8266 to multiplex a display. This combination works fine (albeit only if I drop the recommended 33pf timing capacitor on the MCPx).
The problem comes if I reset the processor. The pins on the MCP23016 latch and if the processor is reset, say during uploading a sketch, the display element which is currently active at that time is overdriven because the multiplexing is temporarily frozen.
There is no output enable pin so I have considered switching Vdd on the MCP23016 via a processor pin (directly or with a transistor/transistor pair) so that during a processor reset, when all pins are high impedence, the MCPx is not powered.
Any comment / suggestions ?
6v6gt:
This combination works fine (albeit only if I drop the recommended 33pf timing capacitor on the MCPx).The problem comes if I reset the processor. The pins on the MCP23016 latch and if the processor is reset, say during uploading a sketch, the display element which is currently active at that time is overdriven because the multiplexing is temporarily frozen.
Maybe the MCP23016 clock gets influenced by spikes on the power rail. Do you have enough decoupling there.
The ESP draws peak currents spikes that a regulator is too slow to react to.
I have seen cap values of >= 470uF. I use two 220uF/6.3vol tantalums on my ESP designs.
Can't suggest a fix for the other problem until a diagram is posted.
Maybe switch power to the display instead of the expander.
Leo..
Are these multiplexors powered by the same line than arduino?
Perhaps you could shut the power for those multiplexors when the arduino is reset. You could, for instance, power these multiplexors with an arduino PIN, if they don't require too much current, and so you would be able to just switch them off at startup.
Does it sound like a good idea?
OK. Thanks for the contributions.
I'll solve the problem by putting an MCP23017 on my shopping list.
It has a /reset pin which looks from the data sheet that I could tie low and have held high by an ESP8266 pin. It also does not require the external timing components that its predecessor needs.
It has a /reset pin which looks from the data sheet that I could tie low and have held high by an ESP8266 pin
If you tie it low, the mcp and the esp will both be held permanently in reset state. Just tie it to the esp reset. I don't know what esp board/module you are using, but on the Wemos I use, there is a pull up resistor on the reset pin, either on the Wemos board or the esp module, so you can tie that to any other reset pins in your circuit (e.g. LCD/oled displays, attinys etc.)
What display are you multiplexing, by the way? I2c chips are not a common choice for that task.
Ah yes, I meant to write pull low(10K) rather than tie low and hold it high with an ESP8266 pin. Since I drive the MCPx at 5 volt I guess I'll need to level change it as I do with the I2C connections. But I'll consider what you said about using the ESP8266 reset pin.
The displays are, incidentally, 4 IN12 nixies (multiplexed) and 2 INS-1 neons. The MCPx handles the anodes (via transistor drivers), the cathodes (via a single K155id1 driver) and 2 neons (via transistor drivers). I'm using an Adafruit Huzzah ESP8266 module.
I2C is (or should be) simple and uses only 2 processor pins which are already level changed in my application and I already had the MCP23016 in my toy box. Speed is not a big issue because the multiplexing is in units of 1ms. Of course, there are other ways of doing it using shift registers etc. and these may be better, but apart from the freezing during system reset which is not nice but has solutions already mentioned in this thread, it works.
I don't see why you want to pull it low with 10K either. Just connect it to the RST pin on the Huzzah, then it gets reset when the Huzzah gets reset.
Can't you run the mcp at 3.3V? If it's driving everything through transistors, you might have to lower the base resistors slightly, maybe not. Looks like the K155id1 would be ok with that too.
I would really love to understand what's up with the mcp23016, have been trying to make it work for days now. I have the 33pf to GND and the resistor to VDD, on the CLK line - but my data is so inconsistent.
Leaving out the cap also gives me more stable (though still not good enough) data, like other users have suggested.
How is one supposed to get this chip to work properly?
I have everything hooked up correctly, with the address pins to GND etc.
I have one button connected to one of the pins on the MCP, with a pullup resistor implementation.
Here is my code:
#include<Wire.h>
byte input1 = 0;
byte input2 = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(B01000000); // address, RW bit 0
delayMicroseconds(12);
Wire.write(0x06); // IO direction
delayMicroseconds(12);
Wire.write(0xFF);
delayMicroseconds(12);
Wire.write(0xFF);
delayMicroseconds(12);
Wire.endTransmission();
delayMicroseconds(12);
}
void loop() {
Wire.beginTransmission(0x20);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x20, 2); // request bytes from slave device
int data = 0;
if(!Wire.available()){}
data = Wire.read();
if(!Wire.available()){}
data |= Wire.read() << 8;
Wire.endTransmission();
Serial.println(data, BIN);
delay(400);
}
And here is a snippet of the arduino serial log (i'm not pushing the button or anything):
11111101
111111111111
111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
111111111111111
1111111111111
111101111111
1
1
1
1
1
1
11011111111
1111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
111111111111111
111101111111
11000001111
1
1
1
1
1
1
10000001
111111111111
1111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
111111111111111
111111111111111
111101111111
11000111111
1
1
1
1
1
1
10000001
111111111111
1111111111111
111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
11111111111111111111111111111111
111011101111111
101111111111111
NOTE:
I just tried measuring the cap (which is supposed to be a 33pf cap) on my cheap-ass multimeter, and it says 28 pf... I bought these caps in 2011, and now I'm wondering if this is just my cheap multimeter not being correct or if they could've dropped in capacitance and potentially leading to my problems I have now?
Please read the forum guidelines in the sticky post. Your question does not truly relate to the thread subject and you have not used code tags.
if(!Wire.available()){}
data |= Wire.read() << 8;
It is not clear if this construct is doing what you intend.
Do you want to perform a Wire.read() operation only if Wire.available() is true ?
6v6gt:
if(!Wire.available()){}
data |= Wire.read() << 8;
It is not clear if this construct is doing what you intend. Do you want to perform a Wire.read() operation only if Wire.available() is true ?
that there was just one of many ways I tried reading from the mcp23016.
one of the other ways I tried reading from it was like this:
if(Wire.available()) }
data = Wire.Read();
}
this did not make any difference - I have the same strange output inconsistency.
I have a gut feeling it has to do with the RC part. right now I tucked out my grand old analog oscilloscope and tried to see if the clock is actually at 1 mhz as the datasheet recommends (requires actually).. haven't been able to get a decent signal yet.. also I just ordered some mcp23017's, just because the hazzle with the mcp23016 just seems ridiculous
EDIT: after having hooked up my oscilloscope I can see that the clock period is indeed 1 microsecond long (= 1mhz freq), and its voltage range is a little bit above 4v. So I would assume RC is not the problem anyway...
Wire.beginTransmission(B01000000); // address, RW bit 0
...
Wire.beginTransmission(0x20);
Mismatch.
I have everything hooked up correctly, with the address pins to GND etc.
I have one button connected to one of the pins on the MCP, with a pullup resistor implementation.
Serial.println(data, BIN);
If you only have one IO pin connected, then there is little point in printing out the state of the other (floating?) pins. Just print out the value of the one bit you are interested in and see if it changes when the button is pressed.
Is the switch connected to GP0.0 ?
I just tried measuring the cap (which is supposed to be a 33pf cap) on my cheap-ass multimeter, and it says 28 pf... I bought these caps in 2011, and now I'm wondering if this is just my cheap multimeter not being correct or if they could've dropped in capacitance and potentially leading to my problems I have now?
Capacitors can have a wide tolerance, like 20%.
Update: it appeared to flicker simply because I was looking at the unused (floating) pins also.. in case anyone else stumbles upon this thread with the sample issue.