False digital triggers in INPUT_PULLUP

Hello everyone. I have a light switch connected to ground, and to an arduino mega2560 INPUT_PULLUP.

When this switch it on, it activates a relay. This relay is 100% isolated from the arduino (they use different power sources, and they are also separated by an optocoupler)

The problem is: The light switch false triggers at random times in the day. Maybe 3 times in a day. So it’s very hard to debug. I didn’t realize this when I was using TRIACs, but now that I’m using relay, I can hear them turning on.

The light switch cable is around 4 meters long, and it goes right next to the 220 line in my house. The relay also controls a 220v light.

Any ideas on what could be causing the false trigger?

The PSU is 3Amp 12V, it’s NOT a switching psu

Here is the code (I wrote this code as a temporary test while I develop something more complex)

const byte lightPins[] = {32,33,34,35,36,37,38,39}; //8 lights
const byte sensorPins[] = {16,17,18,19,20,21,22,23}; //8 sensors
byte readStatus[8]; //store the last value for each switch


void setup(void) {
	for (int i=0;i<8;i++){
		pinMode(sensorPins[i], INPUT_PULLUP);
		pinMode(lightPins[i], OUTPUT);
		readStatus[i] = digitalRead(sensorPins[i]);
		if (readStatus[i] == HIGH)
			digitalWrite(lightPins[i],LOW);
		else
			digitalWrite(lightPins[i],HIGH);
	}

	return;
}

void loop(void) {
	for (int i=0;i<8;i++){
		// read the state of the switch into a local variable:
		int reading = digitalRead(sensorPins[i]);
		if (reading != readStatus[i]) {
			//we could add debounce logic here. Use millis to calculate a delay
			//but we wont :)
			readStatus[i] = reading;
			if (reading == HIGH)
				digitalWrite(lightPins[i],LOW);
			else
				digitalWrite(lightPins[i],HIGH);
			delay(60); //just prevent a bounce. We don't care about this pause.
		} 
	}
}

How is it wired.

I think you are implying the switch shorts the input to ground.

I think you have probably answered your own question. ie try using a 1k external pullup, or possibly even lower. or else you have supply noise.

The Arduino's pull-up is too weak for this application (cables 4 meters long and near 220V line). Try using external pull-up resistors with any value from 2.2K to 4.7K on each sensor pin. This should give strong input signals with high noise immunity.

dc740:
The light switch cable is around 4 meters long, and it goes right next to the 220 line in my house.

The logical deduction is that induction is the culprit.

Distance. Increase the distance between the low voltage DC wires and the high voltage AC wires. Running them in parallel for four meters was a mistake. #

Pullup. Add a lower resistance pullup. @rogerClark suggested a 1k resistor. Heed his advice.

Filter. Use a low pass filter.

Shielding. Add electrical shielding to the low voltage DC wires.

# In an automotive class, I watched a representative of Champion Spark Plugs demonstrate that a mere 10 centimeters of two cables in parallel is enough to keep an engine running. 30 centimeters has no noticeable adverse affect compared to a solid cable. I will repeat the point: Running low voltage DC wires and high voltage AC wires in parallel is a mistake.

Good suggestions from all. Wow, when posts come in while your creating your own, I'll have to learn how to jump back and read the new posts without loosing the text. Just to clarify - absolutely with rogerClark's suggestion.

lesson learned! Thank you guys. I’ll try your suggestions ASAP. Sadly, I’m going to search for shielding the dc switch line too, because I have no way of separating the 220v line from the switch cables. That would require a “refactor” of a house internal system, which would involve lots of material + work + painting the house again, etc etc etc. Lots of money and time, you get my the point.
I was really afraid this could be one of the problems I would face, but I will try your suggestions. I’m confident they will fix the problem, since it’s so sporadic.

UPDATE: I saw a quick reply that got deleted later (why?). I wanted to detail that this is NOT the only thing the arduino does. This is just a DEMO sketch I wrote in 5 minutes to test the hardware side. The real logic is around two thousand lines of code and is composed of a few sketchs, server side control code, pc interaction, comunication protocols, and several other things. My skills are mostly focused in the software side.

dlloyd: I'll have to learn how to jump back and read the new posts without loosing the text.

Nothing really to learn - when you click "Preview", it will show you the most recent answers and warn you in red text.

You do use "Preview", don't you?

Note that if (no, not "if" but when) you get the oh-so-apt "Broken" message, you click "Reload" on the browser and "Resend" when it prompts you. As many times as necessary.

Another thing you might try is ignoring inputs that last less than, say, a tenth of a second. That way, if it's a false caused by induction, or whatever, it'll likely get filtered out.

That's also a very good workaround. I implemented the pullup with 1k resistors and it seems to be working fine now. Thank you all!