How to send data via Form using Post method without web page reloading?

Hi, I am a beginner to Arduino of a few months. Apologies this is long, but I want to be specific as searches haven't helped.

Board:
Arduino Mega 2560

Shield:
Ethernet-Shield 2 (with SD Card)

Software:
Visual Studio - PlatformIO

Project:
I have made a circuit that is ten RGB 8x8 LED modules, all controlled via shift registers. And I have them working on a Mega 2560 via buttons (without the Eth-Shield 2 as a proof of concept project).

But now, I wish to control each module's colour and text to be displayed, via my browser. So, I got an Eth-Shield 2 and have been working on examples (WebServer) to get a feel for how the MCU and shield operate. As well as looking through the forum and doing google searches to get a web page (at least) looking and functioning how I like.

I use the SD Card on the Eth-Shield 2 to load the web page.

At this stage, I am not incorporating the RGB 8x8 ten-module circuit. I just want to prove to myself that a web page, hosted by the Mega, can send data to it, without the Mega reloading the entire web page (that is, keeping user entered data on the page intact). Later, when I get that working, I will incorporate the RGB 8x8 ten-module circuit.

Project overview, thus far:
First Part: I am using POST method to send a form with the colour-data to the Arduino Mega, when checkboxes are checked (having ten RGB 8x8 modules, I am sending a lot of data to the Mega, so I chose POST over GET). Each module has a red, green and blue checkbox, so, thirty checkboxes (Three checkboxes in ten forms). On the web page, when any selection of the three checkboxes per module are checked, or unchecked, javascript alters the hex-colour of a representation of the module (see/run the html code below).

Second Part: I have an input field with 'type='text', where the text part to be displayed on the RGB 8x8 ten-modules can be entered. At this stage, I have not tried sending this to the Arduino Mega. I am working upon the colour checkboxes first.

Issue with First Part:
When I check a checkbox, sending the form via POST to the Mega, the code I have reloads the entire page, erasing the check of the most recent checkbox, which I don't want to happen. I would just like to check a checkbox without the page reloading, losing the data entered.

Question:
In my code, how can I differentiate between loading the whole page, and 'pushing' new data selections (clicking a checkbox) to the Arduino Mega without the entire page reloading and loosing all the user data on the page?

Arduino Code:

#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x6E, 0xA2 };

IPAddress ip( 192, 168, 1, 177 );

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// File for loading web page from SD Card
File webFile;

// File to hold data transfered from PC browser (copied from Arduino Forum)
char new_state[1024];

// Configure all the things here
void setup()
{
  // LEDs
  pinMode(40, OUTPUT);  // Blue Indication LED
  pinMode(2, OUTPUT);  // White Clear LED
  pinMode(3, OUTPUT);  // Red LED
  pinMode(4, OUTPUT);  // Yellow LED
  pinMode(5, OUTPUT);  // Orange LED
  pinMode(6, OUTPUT);  // Orange Clear LED
  pinMode(7, OUTPUT);  // Green LED
  pinMode(8, OUTPUT);  // Blue LED
  pinMode(9, OUTPUT);  // Blue Clear LED

  // Test all LEDs
  digitalWrite(40, HIGH);
  delay(1000);
  digitalWrite(40, LOW);
  delay(1000);
  digitalWrite(40, HIGH);
  delay(1000);
  digitalWrite(40, LOW);
  
  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  
  // Get Serial Monitor stuff up and running
  Serial.begin(9600);
  while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Begin: RGB Shift Register Board WebServer POST method");
  
  // (From Webserver example) You can use Ethernet.init(pin) to configure the CS pin 
  // (In some Forum and internet examples this is not here, and everything still works)
  Ethernet.init(10);  // Most Arduino shields

  // Start the Ethernet server:
  Ethernet.begin(mac, ip);

  // Start the server
  server.begin();
  Serial.print("Serving at ");
  Serial.println(Ethernet.localIP());

  // Initialize the SD Card
  Serial.println("Initializing SD card....");
  if (!SD.begin(4)) {
      Serial.println("ERROR!! - SD Card initialization failed!");
      return;
  }
  Serial.println("SUCCESS!! - SD Card has been initialized.");
  //check for index.htm file
  if (!SD.exists("index1.htm")) {
    Serial.println("ERROR!! - SD Card file: Can't find 'index1.htm' file!!");
    return;
  }
  Serial.println("SUCCESS!! - Found 'index1.htm' file.");
}

// Where the web page HTML files are loaded from SD Card (Whole Page to send to browser)
void sendPage(EthernetClient client)
{
  // Send a standard http response header
  client.println("HTTP/1.0 200 OK\Content-Type: text/html\n\n");
  // Send the rest of the page, read from SD Card
  webFile = SD.open("index1.htm");
  if (webFile) {
      while (webFile.available()) {
            client.write(webFile.read());
      }
      webFile.close();
  }
  client.stop();
}

// Main program loop
void loop()
{
  // Listen for incoming clients
  EthernetClient client = server.available();
  
  if (client) {

    while (client.connected()) {

      int i = 0;
      int head = 1;
      int body = 0;

      while(client.available()) {
        char c = client.read();
        
        if (c == '\n') {

          if ( i <= 2 ) {

            // An http request ends with a blank line
            sendPage(client);
            if ( head == 1 ) {
              body = 1;
              head = 0;
            }

          }

          i = -1;
        }

        if ( body == 1 ) {
          new_state[i] = c;
        }
        i++;
        new_state[i] = '\0';
      }
      i = 0;
    }
    
    // While mucking around with code (before final code to use in project), see what comes back on the FORM (via POST method)
    Serial.println(new_state);
    
    // Parse whatever comes back here; Name and Value (looks like this; M10R=on). 
    // 'Name' (M10R) determines which local variable in this code to focus upon. 
    // 'Value' (on) is the value to update the local variable.
    // If I had "var Module_10_Red = 0;", then here, 'M10R=on' would see variable 'Module_10_Red = 0xFF;'
  }

}

HTML code (loaded into SD Card, as 'Index1.htm'):

<HTML>
	<HEAD>
		<LINK rel='icon' href='data:;base64,iVBORw0KGgo='>
		<TITLE>
			-~{Mega & EthShield2}~-
		</TITLE>
		<STYLE type='text/css'>
			BODY {
				background-color:#4F0445;
				color:White;}
		</STYLE>
	</HEAD>
	<BODY>
		<H1 style='text-align:center'>Welcome to my Mega & Ethernet Shield 2 WebServer example muck-around with code! :D</H1>
		<TABLE bgcolor=Black align=center border=1 width='1500' style='font-size:20px; font-familyterminal;'>
			<TR style='height:40px'>
				<TH colspan='10' style='font-size:30px'>RGB 8x8 (Shift Register) Colours</TH>
			</TR>
			<TR>
				<TH id='dM10' style='Color:#808080'>Mod-10</TH>
				<TH id='dM09' style='Color:#808080'>Mod-09</TH>
				<TH id='dM08' style='Color:#808080'>Mod-08</TH>
				<TH id='dM07' style='Color:#808080'>Mod-07</TH>
				<TH id='dM06' style='Color:#808080'>Mod-06</TH>
				<TH id='dM05' style='Color:#808080'>Mod-05</TH>
				<TH id='dM04' style='Color:#808080'>Mod-04</TH>
				<TH id='dM03' style='Color:#808080'>Mod-03</TH>
				<TH id='dM02' style='Color:#808080'>Mod-02</TH>
				<TH id='dM01' style='Color:#808080'>Mod-01</TH>
			</TR>
			<TR align=center style='height:100px'>
				<TD>
					<FORM method='POST' action='/' id='M10'>
					<LABEL for='rM10' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM10' name='M10R' onclick='change("M10")'></INPUT><br>
					<LABEL for='gM10' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM10' name='M10G' onclick='change("M10")'></INPUT><br>
					<LABEL for='bM10' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM10' name='M10B' onclick='change("M10")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M09'>
					<LABEL for='rM09' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM09' name='M09R' onclick='change("M09")'></INPUT><br>
					<LABEL for='gM09' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM09' name='M09G' onclick='change("M09")'></INPUT><br>
					<LABEL for='bM09' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM09' name='M09B' onclick='change("M09")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M08'>
					<LABEL for='rM08' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM08' name='M08R' onclick='change("M08")'></INPUT><br>
					<LABEL for='gM08' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM08' name='M08G' onclick='change("M08")'></INPUT><br>
					<LABEL for='bM08' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM08' name='M08B' onclick='change("M08")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M07'>
					<LABEL for='rM07' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM07' name='M07R' onclick='change("M07")'></INPUT><br>
					<LABEL for='gM07' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM07' name='M07G' onclick='change("M07")'></INPUT><br>
					<LABEL for='bM07' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM07' name='M07B' onclick='change("M07")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M06'>
					<LABEL for='rM06' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM06' name='M06R' onclick='change("M06")'></INPUT><br>
					<LABEL for='gM06' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM06' name='M06G' onclick='change("M06")'></INPUT><br>
					<LABEL for='bM06' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM06' name='M06B' onclick='change("M06")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M05'>
					<LABEL for='rM05' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM05' name='M05R' onclick='change("M05")'></INPUT><br>
					<LABEL for='gM05' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM05' name='M05G' onclick='change("M05")'></INPUT><br>
					<LABEL for='bM05' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM05' name='M05B' onclick='change("M05")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M04'>
					<LABEL for='rM04' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM04' name='M04R' onclick='change("M04")'></INPUT><br>
					<LABEL for='gM04' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM04' name='M04G' onclick='change("M04")'></INPUT><br>
					<LABEL for='bM04' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM04' name='M04B' onclick='change("M04")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M03'>
					<LABEL for='rM03' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM03' name='M03R' onclick='change("M03")'></INPUT><br>
					<LABEL for='gM03' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM03' name='M03G' onclick='change("M03")'></INPUT><br>
					<LABEL for='bM03' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM03' name='M03B' onclick='change("M03")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M02'>
					<LABEL for='rM02' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM02' name='M02R' onclick='change("M02")'></INPUT><br>
					<LABEL for='gM02' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM02' name='M02G' onclick='change("M02")'></INPUT><br>
					<LABEL for='bM02' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM02' name='M02B' onclick='change("M02")'></INPUT><br>
					</FORM>
				</TD>
				<TD>
					<FORM method='POST' action='/' id='M01'>
					<LABEL for='rM01' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='rM01' name='M01R' onclick='change("M01")'></INPUT><br>
					<LABEL for='gM01' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='gM01' name='M01G' onclick='change("M01")'></INPUT><br>
					<LABEL for='bM01' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='bM01' name='M01B' onclick='change("M01")'></INPUT><br>
					</FORM>
				</TD>
			</TR>
			<TR align=center style='height:70px'>
				<TH colspan='10'><br>
					Note: If the above module-display is 'grey' (and the colour checkboxes are all unchecked), and there is a 'space' or no text in the below text-field,<br>
					then the actual RGB 8x8 Matrix associated module will have no LEDs lit.<br><br>
					If text appears in the text-field below, and the associated module-display colour selection above is 'grey' (and the colour checkboxes are all unchecked),<br>
					then the 'old colour value' or 'default colour value' for that character(s) on the RGB 8x8 Matrix will apply.<br><br>
					(Make sure for the colour selection to work, there's text in the text-field below, before sending it.)<br><br>
				</TH>
			</TR>
		</TABLE><BR><BR>
		<TABLE bgcolor=Black align=center border=1 width='1500' style='font-size:20px; font-familyterminal;'>
			<FORM method='POST' action='/' id='TXT'>
			<TR style='height:40px'>
				<TH colspan='4' align=center style='font-size:30px'>RGB 8x8 (Shift Register) Text</TH>
			</TR>
			<TR style='height:60px'>
				<TD colspan='4' align=center>
					<LABEL for='TextInput' style='font-size:25px'>Input Text:</LABEL>
					<INPUT type='text' id='TextInput' name='RGBtxt' maxlength='10' size='10' style='background-color:Black; color:grey; height:30px; font-size:25px; text-align:center'><br>
				</TD>
			</TR>
			</FORM>
		</TABLE><BR><BR>
		</FORM>
	</BODY>
	<SCRIPT>
	    var M10rgb = 0;
		var M09rgb = 0;
		var M08rgb = 0;
		var M07rgb = 0;
		var M06rgb = 0;
		var M05rgb = 0;
		var M04rgb = 0;
		var M03rgb = 0;
		var M02rgb = 0;
		var M01rgb = 0;
		var Mtext = 0;
			
		function change(title) {
			var aa = 0;
			var bb = 0;
			var cc = 0;
			var dd = 0;
			var valR = 0;
			var valG = 0;
			var valB = 0;
			var r_hex = 0;
			var g_hex = 0;
			var b_hex = 0;
			var hex = 0;
			
			switch(title) {
				case 'M10':
					aa = 'rM10';
					bb = 'gM10';
					cc = 'bM10';
					dd = 'dM10';
					break;
				case 'M09':
					aa = 'rM09';
					bb = 'gM09';
					cc = 'bM09';
					dd = 'dM09';
					break;
				case 'M08':
					aa = 'rM08';
					bb = 'gM08';
					cc = 'bM08';
					dd = 'dM08';
					break;
				case 'M07':
					aa = 'rM07';
					bb = 'gM07';
					cc = 'bM07';
					dd = 'dM07';
					break;
				case 'M06':
					aa = 'rM06';
					bb = 'gM06';
					cc = 'bM06';
					dd = 'dM06';
					break;
				case 'M05':
					aa = 'rM05';
					bb = 'gM05';
					cc = 'bM05';
					dd = 'dM05';
					break;
				case 'M04':
					aa = 'rM04';
					bb = 'gM04';
					cc = 'bM04';
					dd = 'dM04';
					break;
				case 'M03':
					aa = 'rM03';
					bb = 'gM03';
					cc = 'bM03';
					dd = 'dM03';
					break;
				case 'M02':
					aa = 'rM02';
					bb = 'gM02';
					cc = 'bM02';
					dd = 'dM02';
					break;
				case 'M01':
					aa = 'rM01';
					bb = 'gM01';
					cc = 'bM01';
					dd = 'dM01';
					break;	
			};
			
			if (document.getElementById(aa).checked) {
				valR = 255;
			} else {
				valR = 0;
			};
			
			if (document.getElementById(bb).checked) {
				valG = 255;
			} else {
				valG = 0;
			};
			
			if (document.getElementById(cc).checked) {
				valB = 255;
			} else {
				valB = 0;
			};
			
			r_hex = parseInt(valR, 10).toString(16);
			g_hex = parseInt(valG, 10).toString(16);
			b_hex = parseInt(valB, 10).toString(16);
			hex = '#' + pad(r_hex) + pad(g_hex) + pad(b_hex);
			
			if (hex == '#000000') {
				document.getElementById(dd).style.color = '#808080'; 
			} else {
				document.getElementById(dd).style.color = hex;
			};
			
			document.getElementById(title).submit();
		};
		
		function pad(n){
			return (n.length<2) ? '0'+n : n;
		};
	</SCRIPT>
</HTML>

Thank you for any help :slightly_smiling_face:

use different action='/' for example action='/action1'

Thanks for replying Juraj.

Followed your suggestion, but the page still reloads.

I have been digging into the forums and online in general, again, and I feel that somewhere after the line of code "while(client.available())", I'd look at the browser's request?

Correct me if I'm wrong....It should, when I first type in the IP address, make a request with 'GET' at the start of the header. Then, after checking any of the checkboxes, the browser will send a request with 'POST' at the start of the header. I think?

So, does that sound like I'm on the right track? And if so, I am wondering how to check that?

I'd then send the full page for the 'GET' request, but for 'POST' I'd just do something with the form data and send nothing back so that the page doesn't reload?

The basic system is that your browser sends a request, and waits for data to display. If you don't send anything, it can not display anything, but your browser will still be waiting for a response though, and when nothing arrives it will consider it 'no response'

Hi Deva_Rishi, thank you for replying.

After some digging, I was thinking that. So, reading your response confirmed my thoughts. Thanks!

I have decided to change up the HTML code for the SD Card. I now have a button that submits a form with hidden inputs that contain all the checkboxes and the text field.

And I am looking into adding Ajax and xml to deal with sending that data to the Arduino, and then, returning the data after updating it in variables held on the Mega.

Not sure if that's the best, but I have found an online tutorial for Ajax and xml using a Mega and am studying that.

Again, thank you for answering my questions to Juraj

That is the approach i take as well. Checkboxes are always tricky to read, because the parameter is only included in the form if the box is 'checked' , which usually means that if you want to update a variable, you have to make sure that the argument is also modified if a checkbox is 'unchecked' , for which you a 'hidden' is the easiest solution.

I use 1 form that includes all checkboxes, and gets send when the form is 'submit'-ted. and not to use 'onclick' because that is the actual part that starts submitting straight away.

If you don’t want a page redraw you need to use JavaScript in the page to update the DOM dynamically. Look for AJAX examples.

Good to know! In the section of my html code on the SD card, I do get the function to look for 'checked' and 'unchecked', to change that into an integer (0 or 255, or, 0x00 or 0xFF), which then gets transformed into a hex colour value (#000000). That hex value then alters the representation of each modules colour.

I was thinking, instead of looking at the three checkboxes (Red, Green and Blue) of a module and transforming them into a hex-colour value, just send the integer value of the single checkbox value or state that's been changed to the Mega. Then update the variable, and via xml, combine the red-green-blue variable for that module into a hex-colour value, and send it back to the browser to update the representation of that module via ajax.

But, sending absolutely everything is still an option. Just depends upon how quickly one avenue or the other is I suppose.

Hey J-M-L, thanks for the advice! I am currently doing so. Have found a tutorial using Arduino, and cross-referencing the w3school's Ajax and XML tutorials.

Have found some things that look promising. So, good to read your idea matches up with that. Thank you!

good - it does work well. I usually use this on ESPs as you have more memory and the asyncWebServer library helps too but nothing preventing you from using a similar approach from a MEGA and Ethernet shield. You do want indeed to store the html either on the SD card or in EEPROM so that you don't impact your SRAM too much

Have a look for the HTML color picker, this is the code i use

    s += "<br><pre><form action='";
    s += webIP;
    s += "' method='post' name='colorpick'>";
    s += "   Pick Color :         <input type='color' id='colorpick' name='colorpick' value='#";
    s += To6Hex(futurecolor);
    s += "'>          <input type='submit' value='   Set   '></form></pre>";

n.b exact copy of my code, does not compile as is.

I'VE CRACKED IT!!!! WOOOOOO-HOOOOOOO!!!

-~(Calming down noises ensue)~-

Okay, so, to @Deva_Rishi and @J-M-L , a big thank you for your replies.

I took a look at AJAX, XML, and poured through these forums, examples on the web, and w3schools. And I got it!

I changed the Arduino code, and the HTML code too. Now, the Arduino looks for a client, waits for it to finish sending their last byte in the response and responds. I have a GET request part for when the IP address is first entered into the browser, which will respond with the web page (via SD Card).

And then, when a checkbox is checked (or unchecked), and the last byte of the POST is finished, the Arduino sorts out what data was sent from the browser, compiles an XML response, then sends that back to the browser. And the page doesn't reload!! But updates.

So, if I check the Module-10 Red checkbox after initially loading the entire page, the Arduino receives that, updates the appropriate part of the RGB array. Then for the XML response, the Arduino will look at the RGB array for Module-10, compile a hex-colour number (#ff0000), and send that back. The browser javascript then updates the appropriate element, changing it's colour accordingly.

Anyway, enough blabbing on... now I got to work something out for the text input, haha!

Here's the code;

Arduino Mega Code:

#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xA8, 0x61, 0x0A, 0xAE, 0x6E, 0xA2 };

IPAddress ip( 192, 168, 1, 177 );

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// File for loading web page from SD Card
File webFile;

// Store the HTTP request
String HTTP_req;

// String finder variables
String CT;
String Module_x;
String Colour_x;
String Val_x;

// String finder locations
int ind1;

// String to integer
int Mod_Num_x;
int RGB_index;
int Col_Num_x;
int Val_Num_x;

// Array for the colour value of each module
byte Web_Array_RGB[10][3] = {
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}, 
  {0x00, 0x00, 0x00}
};   
// 0x00 = 'OFF'; 0xFF = 'ON'
// [0][0], [1][0], [2][0], [3][0], [4][0], [5][0], [6][0], [7][0], [8][0], [9][0] = Blue Value for the 10 Modules
// [0][1], [1][1], [2][1], [3][1], [4][1], [5][1], [6][1], [7][1], [8][1], [9][1] = Green Value for the 10 Modules
// [0][2], [1][2], [2][2], [3][2], [4][2], [5][2], [6][2], [7][2], [8][2], [9][2] = Red Value for the 10 Modules
//  M10      M9      M8      M7      M6      M5      M4      M3      M2      M1   = [M10 = LHS; M1 = RHS]

// Text to display on RGB 8x8 Matrix
byte Web_Array_Message[11] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0 };

// Configure all the things here
void setup()
{
  // LEDs
  pinMode(40, OUTPUT);  // Blue Indication LED
  pinMode(2, OUTPUT);  // White Clear LED
  pinMode(3, OUTPUT);  // Red LED
  pinMode(4, OUTPUT);  // Yellow LED
  pinMode(5, OUTPUT);  // Orange LED
  pinMode(6, OUTPUT);  // Orange Clear LED
  pinMode(7, OUTPUT);  // Green LED
  pinMode(8, OUTPUT);  // Blue LED
  pinMode(9, OUTPUT);  // Blue Clear LED

  // Test all LEDs
  digitalWrite(40, HIGH);
  delay(1000);
  digitalWrite(40, LOW);
  delay(1000);
  digitalWrite(40, HIGH);
  delay(1000);
  digitalWrite(40, LOW);
  
  digitalWrite(2, HIGH);
  digitalWrite(3, HIGH);
  digitalWrite(4, HIGH);
  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
  digitalWrite(6, LOW);
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  
  // Get Serial Monitor stuff up and running
  Serial.begin(9600);
  while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Begin: RGB Shift Register Board WebServer POST method");
  
  // (From Webserver example) You can use Ethernet.init(pin) to configure the CS pin 
  // (In some Forum and internet examples this is not here, and everything still works)
  Ethernet.init(10);  // Most Arduino shields

  // Start the Ethernet server:
  Ethernet.begin(mac, ip);

  // Start the server
  server.begin();
  Serial.print("Serving at ");
  Serial.println(Ethernet.localIP());

  // Initialize the SD Card
  Serial.println("Initializing SD card....");
  if (!SD.begin(4)) {
      Serial.println("ERROR!! - SD Card initialization failed!");
      return;
  }
  Serial.println("SUCCESS!! - SD Card has been initialized.");
  //check for index.htm file
  if (!SD.exists("index1.htm")) {
    Serial.println("ERROR!! - SD Card file: Can't find 'index1.htm' file!!");
    return;
  }
  Serial.println("SUCCESS!! - Found 'index1.htm' file.");
}

// Finds red, green and blue values stored on Mega in array, then combines them into a Hex-Colour string
// Puts the Hex-Colour string, with hash in front, inbetween an element with module number as name
// Sends all as XML back to web page for the module representation to be updated 
void XML_response(EthernetClient cl, int Mod_indx, String Mod_Str) 
{
  String Red_String;
  String Green_String;
  String Blue_String;
  String Hex_Colour;

  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<INPUTS>");
  //----------------------
  //---------------------- 
  // Red value
  if (Web_Array_RGB[Mod_indx][2] == 255) {
    Red_String = "ff";
  } else {
    Red_String = "00";
  }

  // Green value
  if (Web_Array_RGB[Mod_indx][1] == 255) {
    Green_String = "ff";
  } else {
    Green_String = "00";
  }

  // Blue value
  if (Web_Array_RGB[Mod_indx][0] == 255) {
    Blue_String = "ff";
  } else {
    Blue_String = "00";
  }

  // Put all together
  Hex_Colour = "#" + Red_String + Green_String + Blue_String;

  // Create id; 'Mod_Str' should be two characters. Either '0X' (where 'X' is an integer from 1 to 9), or, '10'
  cl.print("<MOD>");
  cl.print("dM" + Mod_Str);
  cl.print("</MOD>");

  // Enter the new hex-value; Format = #ff0000 for red, #00ff00 for green, #0000ff for blue, etc
  cl.print("<COLOUR>");
  cl.print(Hex_Colour);
  cl.print("</COLOUR>");

  //----------------------
  //----------------------
  
  cl.print("</INPUTS>");
}

// Main program loop
void loop()
{
  // Listen for incoming clients
  EthernetClient client = server.available();
  
  // Got a client?
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      
      // Client data available to read 
      if (client.available()) {

        // Read one byte (character) from client
        char c = client.read(); 

        // Save the HTTP request to a string
        HTTP_req += c;
        
        // When this becomes false, the client has sent their last byte
        if (!client.available()) {

          // When first loading the web page, will be a GET request
          if (HTTP_req.indexOf("GET / HTTP/1.1") > -1) {

            // Web Page request
            // Send a standard HTTP response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();

            // Send web page from SD Card
            webFile = SD.open("index1.htm");

            if (webFile) {
              
              while (webFile.available()) {
              
                client.write(webFile.read());
              
              } // End; while (webFile.available())
              
              webFile.close();
            
            } // End; if (webFile)

          } // End; if (HTTP_req.indexOf("GET / HTTP/1.1") > -1)

          // When a checkbox state is changed, or text entered, POST request
          if (HTTP_req.indexOf("POST /Mega HTTP/1.1") > -1) {

            // Data sent by POST in xhttp looks like this: INPUTDATA:M10R=255  
            // Look in the POST body, find out what is being sent, starting at the identifier 'INPUTDATA:'
            ind1 = HTTP_req.lastIndexOf(':');
            
            // Now find if data is from a checkbox (colour update), or text
            // If data sent is; INPUTDATA:M10R=255 
            // Data found should be one character; Either 'M' (Checkbox), or, 'T' (Text)
            CT = HTTP_req.substring(ind1+1, ind1+2);

            // Now find what module number is to be updated
            // If data sent is; INPUTDATA:M10R=255 
            // Data found should be two characters; Either '0X' (where 'X' = an integer from 1 to 9), or, '10'
            Module_x = HTTP_req.substring(ind1+2, ind1+4);

            // Now find what colour is to be updated
            // If data sent is; INPUTDATA:M10R=255 
            // Data found should be one character; Either 'R', or, 'G', or, 'B'
            Colour_x = HTTP_req.substring(ind1+4, ind1+5);

            //Now find the value to be updated
            // If data sent is; INPUTDATA:M10R=255 
            // Data found should be one or three characters; Either '0', or, '255'
            Val_x = HTTP_req.substring(ind1+6);

            // Convert strings to integers
            Mod_Num_x = Module_x.toInt();
            Val_Num_x = Val_x.toInt();
            
            // Convert string colour to number
            if (Colour_x == "R") {
              Col_Num_x = 2;
            } else if (Colour_x == "G") {
                Col_Num_x = 1;
            } else if (Colour_x == "B") {
                Col_Num_x = 0;
            }

            // Find correct index numbers
            switch(Mod_Num_x) {
              case 1:
                    RGB_index = 9;
                    break;
              
              case 2:
                    RGB_index = 8;
                    break;
              
              case 3:
                    RGB_index = 7;
                    break;
              
              case 4:
                    RGB_index = 6;
                    break;
              
              case 5:
                    RGB_index = 5;
                    break;
              
              case 6:
                    RGB_index = 4;
                    break;
              
              case 7:
                    RGB_index = 3;
                    break;
              
              case 8:
                    RGB_index = 2;
                    break;
              
              case 9:
                    RGB_index = 1;
                    break;
              
              case 10:
                    RGB_index = 0;
                    break;
            }

            // Update the array with new value
            Web_Array_RGB[RGB_index][Col_Num_x] = Val_Num_x;

            // POST request of XML data
            // Send a standard HTTP response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: application/xml"); // Anything else will not work browser-side (apparently in Firefox... but, eh, maybe on all browsers too)
            client.println("Connection: close");
            client.println();

            // Send XML file containing input states
            XML_response(client, RGB_index, Module_x);

            // Clear variables
            Mod_Num_x = 0;
            Col_Num_x = 0;
            Val_Num_x = 0;
            RGB_index = 0;

            // Clear strings
            Module_x = "";
            Colour_x = "";
            Val_x = "";

          } // End; if (HTTP_req.indexOf("POST /Mega HTTP/1.1") > -1)
          
          // Display received HTTP request on Serial Monitor
          Serial.print(HTTP_req);

          // Clear saved string
          HTTP_req = "";
          break;
          
        } // End; if (!client.available())
        
      } // End; if (client.available())
    
    } // End; while (client.connected())

    // Give browser time to received data
    delay(1);

    // Close connections
    client.stop();
    
  } // End; if (client)

} // End; Main Programm Loop

HTML Code in the SD Card (entire page):

<!DOCTYPE html>
<HTML>
	<HEAD>
		<LINK rel='icon' href='data:;base64,iVBORw0KGgo='>
		<TITLE>
			-~{Mega & EthShield2}~-
		</TITLE>
		<STYLE type='text/css'>
			BODY {
				background-color:#4F0445;
				color:White;}
		</STYLE>
	</HEAD>
	<BODY>
		<H1 style='text-align:center'>Welcome to my Mega & Ethernet Shield 2 WebServer example muck-around with code! :D</H1>
		<TABLE bgcolor=Black align=center border=1 width='1500' style='font-size:20px; font-familyterminal;'>
			<TR style='height:40px'>
				<TH colspan='10' style='font-size:30px'>RGB 8x8 (Shift Register) Colours</TH> 
			</TR>
			<TR>
				<TH id='dM10' style='Color:#808080'>Mod-10</TH> 
				<TH id='dM09' style='Color:#808080'>Mod-09</TH>
				<TH id='dM08' style='Color:#808080'>Mod-08</TH>
				<TH id='dM07' style='Color:#808080'>Mod-07</TH>
				<TH id='dM06' style='Color:#808080'>Mod-06</TH> 
				<TH id='dM05' style='Color:#808080'>Mod-05</TH> 
				<TH id='dM04' style='Color:#808080'>Mod-04</TH> 
				<TH id='dM03' style='Color:#808080'>Mod-03</TH> 
				<TH id='dM02' style='Color:#808080'>Mod-02</TH> 
				<TH id='dM01' style='Color:#808080'>Mod-01</TH> 
			</TR>
			<TR align=center style='height:100px'>
				<TD>
					<LABEL for='rM10' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M10R' value='' onclick='ArduinoData("M10R")'></INPUT><br> 
					<LABEL for='gM10' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M10G' value='' onclick='ArduinoData("M10G")'></INPUT><br>
					<LABEL for='bM10' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M10B' value='' onclick='ArduinoData("M10B")'></INPUT><br>
				</TD>
				<TD>
					<LABEL for='rM09' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M09R' value='' onclick='ArduinoData("M09R")'></INPUT><br>
					<LABEL for='gM09' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M09G' value='' onclick='ArduinoData("M09G")'></INPUT><br>
					<LABEL for='bM09' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M09B' value='' onclick='ArduinoData("M09B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM08' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M08R' value='' onclick='ArduinoData("M08R")'></INPUT><br> 
					<LABEL for='gM08' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M08G' value='' onclick='ArduinoData("M08G")'></INPUT><br> 
					<LABEL for='bM08' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M08B' value='' onclick='ArduinoData("M08B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM07' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M07R' value='' onclick='ArduinoData("M07R")'></INPUT><br> 
					<LABEL for='gM07' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M07G' value='' onclick='ArduinoData("M07G")'></INPUT><br> 
					<LABEL for='bM07' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M07B' value='' onclick='ArduinoData("M07B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM06' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M06R' value='' onclick='ArduinoData("M06R")'></INPUT><br>
					<LABEL for='gM06' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M06G' value='' onclick='ArduinoData("M06G")'></INPUT><br> 
					<LABEL for='bM06' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M06B' value='' onclick='ArduinoData("M06B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM05' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M05R' value='' onclick='ArduinoData("M05R")'></INPUT><br> 
					<LABEL for='gM05' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M05G' value='' onclick='ArduinoData("M05G")'></INPUT><br> 
					<LABEL for='bM05' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M05B' value='' onclick='ArduinoData("M05B")'></INPUT><br>
				</TD>
				<TD>
					<LABEL for='rM04' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M04R' value='' onclick='ArduinoData("M04R")'></INPUT><br> 
					<LABEL for='gM04' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M04G' value='' onclick='ArduinoData("M04G")'></INPUT><br> 
					<LABEL for='bM04' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M04B' value='' onclick='ArduinoData("M04B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM03' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M03R' value='' onclick='ArduinoData("M03R")'></INPUT><br> 
					<LABEL for='gM03' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M03G' value='' onclick='ArduinoData("M03G")'></INPUT><br>
					<LABEL for='bM03' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M03B' value='' onclick='ArduinoData("M03B")'></INPUT><br> 
				</TD>
				<TD>
					<LABEL for='rM02' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M02R' value='' onclick='ArduinoData("M02R")'></INPUT><br> 
					<LABEL for='gM02' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M02G' value='' onclick='ArduinoData("M02G")'></INPUT><br> 
					<LABEL for='bM02' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M02B' value='' onclick='ArduinoData("M02B")'></INPUT><br>
				</TD>
				<TD>
					<LABEL for='rM01' style='color:RED'>RED</LABEL>
					<INPUT type='checkbox' id='M01R' value='' onclick='ArduinoData("M01R")'></INPUT><br>
					<LABEL for='gM01' style='color:GREEN'>GREEN</LABEL>
					<INPUT type='checkbox' id='M01G' value='' onclick='ArduinoData("M01G")'></INPUT><br> 
					<LABEL for='bM01' style='color:BLUE'>BLUE</LABEL>
					<INPUT type='checkbox' id='M01B' value='' onclick='ArduinoData("M01B")'></INPUT><br> 
				</TD>
			</TR>
			<TR align=center style='height:70px'>
				<TH colspan='10'><br>
					Note: If the above module-display is 'grey' (and the colour checkboxes are all unchecked), and there is a 'space' or no text in the below text-field,<br>
					then the actual RGB 8x8 Matrix associated module will have no LEDs lit.<br><br>
					If text appears in the text-field below, and the associated module-display colour selection above is 'grey' (and the colour checkboxes are all unchecked),<br>
					then the 'old colour value' or 'default colour value' for that character(s) on the RGB 8x8 Matrix will apply.<br><br>
					(Make sure for the colour selection to work, there's text in the text-field below, before sending it.)<br><br>
				</TH>
			</TR>
		</TABLE><BR><BR>
		<TABLE bgcolor=Black align=center border=1 width='1500' style='font-size:20px; font-familyterminal;'>
			<TR style='height:40px'>
				<TH colspan='4' align=center style='font-size:30px'>RGB 8x8 (Shift Register) Text</TH>
			</TR>
			<TR style='height:60px'>
				<TD colspan='4' align=center>
					<LABEL for='TextInput' style='font-size:25px'>Input Text:</LABEL>
					<INPUT type='text' id='TextInput' name='RGBtxt' maxlength='10' size='10' style='background-color:Black; color:grey; height:30px; font-size:25px; text-align:center'><br> <!-- DOM; getElementByTagName('INPUT')[30] -->
				</TD>
			</TR>
		</TABLE><BR><BR>
	</BODY>
	<SCRIPT>
		function ArduinoData(SendData) {
			var CBval = 0;
			if (document.getElementById(SendData).checked) {
				CBval = 255;
			} else {
				CBval = 0;
			};
			var NuData = 'INPUTDATA:' + SendData + '=' + CBval; // String should be at least 10+6=16 characters long for unchecked, and 10+8=18 characters long for checked. 
			                                                    // eg: Unchecked = 'INPUTDATA:M10R=0' (16), Checked = 'INPUTDATA:M10R=255' (18)
			var xhttp = new XMLHttpRequest();
			xhttp.onreadystatechange = function() {
				if (this.readyState == 4 && this.status == 200) { // 4 = request finished and response is ready; 200 = status is "OK"
					if (this.responseXML != null) {
						// Extract XML data from XML file (containing id in element format and hex-colour value)
						// Data comes back as; 	
						//						<?xml version = "1.00" ?>
						//							<INPUTS>
						//								<MOD>dM10</MOD>
						//								<COLOUR>#00ff00</COLOUR>
						//							</INPUTS>
						// This would mean the representation of Module 10's colour should be green
						var ID_VAL = this.responseXML.getElementsByTagName("MOD")[0].childNodes[0].nodeValue;
						var HexColour_Val = this.responseXML.getElementsByTagName("COLOUR")[0].childNodes[0].nodeValue;
						if (HexColour_Val == '#000000') {
							document.getElementById(ID_VAL).style.color = '#808080';
						} else {
							document.getElementById(ID_VAL).style.color = HexColour_Val;
						}
					}
				}
			}
			xhttp.open('POST', 'Mega', true);
			xhttp.setRequestHeader("Content-type", "application/xml");
			xhttp.send(NuData);
		};
	</SCRIPT>
</HTML>

Again, thanks to those who suggested stuff, and took time to respond!! :smiley: :ok_hand: :+1: :fist:

Great news !

Have fun

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.