Arduino Mega, Ethernet shield and 48 relays

Hello everyone,

Ive been banging my head against the wall trying to write a program (im a very amateur coder ( ) for an arduino controlled 48-relay board consisting of 3 16-relay modules, an Arduino mega 2560 and a W5100 ethernet shield.

I was successful mimicking a few instructables such as this one which is sadly for a maximum of 10 relays, but Im having trouble adapting this code for 48 outputs, so my questions are:

1- Are there enough pins to control all 48 relays? My pin array is { 2, 3, 5, 6, 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, A0, A1, A2, A3, A4, A5, A7, A8, A9, A12, A13, A14, A15 }
Or am I wrong in using the analog pins as output? Ive googled plenty and finally decided to opt out on using pins 4, 10, 11, 12 ,13, 50, 51, 52, and 53 because im not sure if they are usable in my case or not. Can you shed some light on what pins I must steer clear of and what pins are good?

2- Since my pins are not a normal sequence, I cant use a regular “for loop” (this is the major coding problem for me) and I don’t quite understand how the buttons are being printed and the output status is being checked. The best I could come up with is the following:

char relayPins[] = { 2, 3, 5, 6, 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, A0, A1, A2, A3, A4, A5, A7, A8, A9, A12, A13, A14, A15};
int relayCount = 48;
for (int thisPin =0; thisPin < pinCount; thisPin++) {
  pinMode(relayPins[thisPin], OUTPUT);
}

Perhaps if I omit the analog pins, I can declare this array as int. this probably would work for setting the pinMode, but is trickier for printing the buttons. any ideas?

3- Im using a 12V-1A external power adapter to power both the relays and the Arduino+shield, do I need more juice?
I don’t need the code to be fancy, I just need it to work, even If I have to manually repeat some lines 48 times.

I realize it’s a lot to ask, but im desperate. Help!

Declare the array of relay pins as const byte and the contents just as you have in your code. The A* pin names are not characters but are defined as numbers behind the scenes to match the actual pin numbers of the board. Try printing A0, A1 etc to see what I mean.

Your code has an error in it in that you declare relayCount but use pinCount as the upper limit in the for loop but I suspect that is a simple typo.

You could improve the code and make it safer by using sizeof(relayPins); to determine the number of entries in the byte array rather than code it explicitly. This would allow the number of entries to be changed more easily.

And sizeof(relayPins)/sizeof(relayPins[0]) would even take into account any change in the size of the array elements.

vaj4088:
And sizeof(relayPins)/sizeof(relayPins[0]) would even take into account any change in the size of the array elements.

I deliberately chose not mention that so as not to complicate things. Should the OP need to use an Arduino that has more than 255 pins some time in the future then it would, of course, be relevant.

I knew that UKHeliBob already knew about this. I can understand about not wanting to complicate things.

Thank you both for the help!
It does make things easier knowing the A* pins are also numbers, and yes i appreciate not complicating things too much for me since i certainly dont need more than 48 pins.
The typo was fixed in my original code prior to asking this question, that was just a stupid mistake on my behalf.
Concerning the power supply, any suggestions or ideas?

Hey :slight_smile:
I managed to adapt Claudio Vella's code to work with 48 relays. The page prints 48 buttons that work as expected but only if i comment out the lines related to the allOn and allOff commands. Otherwise it breaks and no buttons are printed. This is on lines 622 to 625.
In the original code, pressing the allOn button returns "?H2H3H4H5H6H7H8H9" and the allOff returns the same with L. My problem is in the double digit pins I suspect. What am I missing?

_48relays_working1-1.ino (23 KB)

My problem is in the double digit pins I suspect. What am I missing?

You are reading one letter at a time, and assuming that a numeric value ('2', for example) corresponds to a pin number. Once you get beyond '9', you have a problem.

The solution is to properly parse the data. When you find an H (or L), you need to read all the characters until there are no more, or until you encounter another H (or L), storing the data in an array. When you encounter the end of data, or the next H (or L), append a NULL terminator, and use atoi() to convert the string to an int.

  const byte relayPins[] = { 2,3,5,6,7,8,9,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,54,55,56,57,58,59,61,62,63,66,67,68,69 };


  for (int thisPin=0; thisPin < relayCount; thisPin++) 
  {
    readInput[(relayPins[thisPin])] = digitalRead(relayPins[thisPin]);
  }

When thisPin is 47 relayPins[thisPin]) will equal 69

How many entries can the readInput array hold ?
Why have you declared relayPins for the second time ?

Thanks Paul but I feel like your solution implies that no button is working. I dont have a problem with any pin/button and they're working fine, except the two buttons that turn on and off ALL of the pins.
Or is it that you DO understand my problem and I DONT understand your solution? Sorry for the noobness but again i say im an amateur coder. Can i get a code snippet?

UKHeliBob, the readinput holds 48, and i declared it a total of 3 times in this code because for some reason, it wouldnt load with a global declare :confused:

readinput holds 48

Correct. So where will readInput[69] be stored ?

i declared it a total of 3 times in this code because for some reason, it wouldnt load with a global declare

That problem needs to be understood and fixed because what you have done is merely a sticking plaster and not a cure. Take the declaration of relayPins out of setup() and make it global. Comment out or delete the other declarations of relayPins. Is there a problem when you compile the code ? If so, post the error message and modified code here.

UKHeliBob:
Correct. So where will readInput[69] be stored ?

I just got what you meant, a light bulb turned on in my head!
Thing is with the global declaration it compiles fine without errors or warnings, but the html finishes loading without printing any buttons and it jumps right to printing the footer. This one i dont get..

Or is it that you DO understand my problem and I DONT understand your solution?

I think that is the case. You talk about "In the original code, pressing the allOn button returns "?H2H3H4H5H6H7H8H9"", but the only proof of that is that the server data is printed one letter at a time. I presume, then, that in the modified code, pressing the allOn button returns a much longer string, with "H10H11H12", etc. in it.

There is no code to deal with the '1's, and the '2's are dealt with, but, obviously not in the way that you want.

Is my presumption correct? Is my conclusion correct?

PaulS:
Is my presumption correct? Is my conclusion correct?

At first, I could not get to the part where i test the client output from the buttons allOn and allOff probably due to some programming logic error. After fiddling with the global declares and the readInput array (what @UKHeliBob suggested), the buttons are printed, and yes indeed the buttons return a long string of H or L with all the right pin numbers, which in theory should turn them on or off. However, it does not:(

In this scenario, the code for all the other buttons is also pooped. What's interesting is that for instance, pressing "Turn on Pin 44" does not turn on 44, but instead turns on pin 30, because in my array,the pin number "44" is in the 30th position.
Also, when the webserver loads, not all buttons are turned off. The problematic pins are the ones with the number greater than 48 which is the number of elements in my array. Somewhere in this sketch is a wrong assignment of pin numbers to corresponding array element.

Conclusion: Something's off in the output statuses function to say the least, and/or the triggerPin function, and/or the readInput array.

Can anyone suggest a cleaner leaner code instead of trying to fix my mess? Im going to give another sketch a shot, something i found here dealing with 40 pins and a similar approach to mine. Stay tuned boys and girls.

The problematic pins are the ones with the number greater than 48 which is the number of elements in my array. Somewhere in this sketch is a wrong assignment of pin numbers to corresponding array element.

Has the light bulb in your head gone off again ? I assume that you did fix the problem, or did you ?

Why does the user of your web page need to know anything about pin numbers? "Turn on 1" to make the 1st device come on makes more sense to me than knowing that the device I want to turn on is connected to pin 47. Or 23. Or 14.

If the numbers the user have to choose from correspond to array indices, rather than pin numbers, life will be easier.

UKHeliBob:
Has the light bulb in your head gone off again ? I assume that you did fix the problem, or did you ?

do you mean changing

readInput[relayPins[thisPin] = digitalRead(relayPins[thisPin]);

to

readInput[thisPin] = digitalRead(relayPins[thisPin]);

cause i did that already

Paul you're right it would make more sense, but it isnt my main concern just yet. I figured once they are all working properly i can think about a more user friendly label.

Paul you're right it would make more sense, but it isnt my main concern just yet. I figured once they are all working properly i can think about a more user friendly label.

But, it isn't working, and will be very difficult to get working. And, you already have a more user-friendly label - the array index, not the array value.

When the NAMES of the widgets on the web page correspond to the array index value, then handling the incoming data, and determining which pin to diddle with, will be trivial.

cause i did that already

Have I missed seeing your revised code ?

In any case, you would be better taking Paul's advice to allow the user to enter a number from 1 to 48 and allowing the program to work out the corresponding pin number.

Don't wait. Do it now.

UKHeliBob:
Have I missed seeing your revised code ?

In any case, you would be better taking Paul's advice to allow the user to enter a number from 1 to 48 and allowing the program to work out the corresponding pin number.

Don't wait. Do it now.

I apologize for taking long to reply. I feel like im close to get it all to work.
The buttons are now labeled relay 1 to 48 and the program is "trying" to figure out the right pin. Most one digit pins work, but double digits behave wrong; relay 42 turns on relays 44 and 22 if im not mistaken.
Another thing, does the code "char c = client.read()" tell the program to move on to the next character when reading the user input? or does finishing the loop do that on its own?
Please check my revised code and tell me what i did wrong.

_48relays_working1-2.ino (22.4 KB)