I am not sure which of the components is actually causing the problem but is seems to be SIPO related. I am already using a very similar design (that works flawlessly) in an earlier version of my device so the problem must be due to something that I changed in the new version.
The devices use 2 of those 5V 4-Relay modules (with built-in opto-couplers, etc) and I am using a SIPO (74HC595) to feed the 8 inputs that control the relays (0V activates the relay, 5V deactivates it).
My original device used a 5V ATMega128 or ATMega328P, i.e. everything was using the same 5V and it worked without a glitch (based on the experience with this device I'd guess that the 74HC595 outputs are strong enough to control the relay modules and I therefore guess that this should not be the problem here).
My current device is based on an ESP8266EX (3v3), i.e. I am using an additional level-shifter (one of those 12 pin PCBs that allow to bi-directionally shift 4 lines) for the CLK/LATCH/DATA lines to the SIPO. I already replaced the level-shifter and the SIPO and that did not resolve the problem. The pins I am using
are GPIO12-GPIO14 so I think that there should not be any limitations attached to them.
The device is powered via a 2A buck-converter that creates the 5V used in the device (starting from a 3A 12V DC power supply). I'd guess that should be enough to power everything (and it worked fine in the old device).
As a test I am using a simple sketch that activates one relay at a time and round-robin cycles through the 8 relais using 500ms pauses (see code below) ... I'd say half of the time this works as expected but some of the time instead of activating one particular relais, ALL 8 are simultaneously activated. This erroneous state may then be repeated for 1 or several steps before the relays are suddenly correctly activated again..
The time between correct/wrong activations seems to be totally random (i.e. there can be a streak on 80 correct activations and then it fails 20 times before it again works correctly - for a while).
I am currently not using any capacitors on either of the lines and I don't know if the ESP8266 pins (the ones that I am using) react differently to what I was used to from the ATMega* stuff..
Any ideas?
const int ValveDriver::sLatchPin = D7; // blue
const int ValveDriver::sClockPin = D6; // brown
const int ValveDriver::sDataPin = D5; // yellow
const int ValveDriver::sSelectVoltagePin = D0;
const int ValveDriver::sBurnOutDetectionPin = A0;
void ValveDriver::setupValveCtrlPins(void) {
//set 74HC595 shift register pins to output because they are addressed in the main loop
pinMode(ValveDriver::sLatchPin, OUTPUT);
pinMode(ValveDriver::sDataPin, OUTPUT);
pinMode(ValveDriver::sClockPin, OUTPUT);
pinMode(ValveDriver::sSelectVoltagePin, OUTPUT);
}
ValveDriver::ValveDriver(void) {
fNumValves = 8;
setupValveCtrlPins();
closeAllValves();
}
int ValveDriver::getNumberOfValves() {
return fNumValves;
}
void ValveDriver::closeAllValves(void) {
digitalWrite(ValveDriver::sLatchPin, LOW);
shiftOut(ValveDriver::sDataPin, ValveDriver::sClockPin, MSBFIRST, 0xff);
digitalWrite(ValveDriver::sLatchPin, HIGH);
}
void ValveDriver::powerUpValve(int whichPin) {
digitalWrite(ValveDriver::sSelectVoltagePin, LOW); // initially use 12V
// This method sends bits to the shift register 74HC595
byte bitsToSend = ~(1 << whichPin); // invert bits because LOW actually switches relay ON
digitalWrite(ValveDriver::sLatchPin, LOW); // turn off the output while you're shifting bits
shiftOut(sDataPin, ValveDriver::sClockPin, MSBFIRST, bitsToSend); // shift the bits out
digitalWrite(ValveDriver::sLatchPin, HIGH);
}
void ValveDriver::sustainVoltage() {
digitalWrite(ValveDriver::sSelectVoltagePin, HIGH); // fall back to 9V once the valve is active
}
void ValveDriver::resetVoltage() {
digitalWrite(ValveDriver::sSelectVoltagePin, LOW); // 12V default.. so that additional converter can be switched off
}
ValveDriver *driver;
int i= 0;
void setup()
{
Serial.begin(9600); // Debugging only
driver= new ValveDriver();
}
// The loop function is called in an endless loop
void ICACHE_FLASH_ATTR loop()
{
delay(500);
driver->powerUpValve(i);
i= (i+1);
if (i == driver->getNumberOfValves()) i= 0;
}