UKHeliBob:
What is the maximum length of the expected user input ?
Robin2:
In the small memory of the Arduino it is better to allocate space for the largest message and use strings (small s)
The maximum number of characters I will receive is 339
The maximum number of LEDs will be 112
I have reworked my sketch from the ground up to use strings, and to delimit the individual LEDs with colons so that I can read the entire string and then toggle the LEDs.
My sketch is now as follows (I have used snippets of code from Nathan, Nick, and Robin)
#include <SPI.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
/** === Starting Ethernet and parsing declarations === **/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char server[] = "my.server.com";
String dataLocation = "/my/file/location/arduino.txt HTTP/1.1"; //test location
EthernetClient client;
//const int requestInterval = 900000; // ms delay between requests (15 min) live time
const int requestInterval = 60000; // ms delay between requests (15 min) test time
boolean requested; // whether you've made a request since connecting
long lastAttemptTime = 0; // last time you connected to the server, in ms
const byte numChars = 339;
char receivedChars[numChars];
char *parsed[112];
int ledCount = 0;
boolean newData = false;
/** === Starting LED declarations === **/
const byte LATCH = 10;
const byte numberOfChips = 2;
const byte maxLEDs = numberOfChips * 8;
byte LEDdata [numberOfChips] = { 0 }; // initial pattern
unsigned long delayAmount = 100;
void setup()
{
SPI.begin ();
Serial.begin (9600);
Serial.println ("Starting ...");
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0)
{
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore
}
Serial.println(Ethernet.localIP());
// Connect to server
connectToServer();
}
void refreshLEDs ()
{
digitalWrite (LATCH, LOW);
for (int i = numberOfChips - 1; i >= 0; i--)
{
SPI.transfer (LEDdata [i]);
digitalWrite (LATCH, HIGH);
}
} // end of refreshLEDs
void connectToServer()
{
// attempt to connect, and wait a millisecond:
Serial.println("connecting to server...");
if (client.connect(server, 80))
{
Serial.println("making HTTP request...");
// make HTTP GET request to dataLocation:
client.println("GET " + dataLocation);
// client.println("Host: bmi-ctn.no-ip.biz");
client.println("Host: 192.168.165.173");
client.println();
}
// note the time of this connect attempt:
lastAttemptTime = millis();
}
// turn an LED number into the position in the array, and a bit mask
boolean getChipAndBit (unsigned int led, int & chip, byte & mask)
{
if (led > maxLEDs)
{
Serial.print ("LED ");
Serial.print (led);
Serial.println (" too high.");
return true; // error
} // end of too high
led--; // make zero relative
// divide by 8 to work out which chip
chip = led / 8; // which chip
// remainder is bit number
mask = 1 << (led % 8);
return false; // no error
} // end of getChipAndBit
// clear LED n (or all if zero)
void clearLED (const long n)
{
// zero means all
if (n == 0)
{
for (int i = 0; i < numberOfChips; i++)
{
LEDdata [i] = 0;
}
return;
} // end of if zero
int chip;
byte mask;
if (getChipAndBit (n, chip, mask))
{
return; // bad number
}
LEDdata [chip] &= ~ mask;
} // end of clearLED
// set LED n (or all if zero)
void setLED (const long n)
{
// zero means all
if (n == 0)
{
for (int i = 0; i < numberOfChips; i++)
{
LEDdata [i] = 0xFF;
}
return;
} // end of if zero
int chip;
byte mask;
if (getChipAndBit (n, chip, mask))
{
return; // bad number
}
LEDdata [chip] |= mask;
} // end of setLED
void loop()
{
recvWithStartEndMarkers();
parseData();
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
if (client.connected())
{
while (client.available() > 0 && newData == false)
{
rc = client.read();
if (recvInProgress == true)
{
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker)
{
recvInProgress = true;
}
}
}
else if (millis() - lastAttemptTime > requestInterval)
{
// if you're not connected, and two minutes have passed since
// your last connection, then attempt to connect again:
connectToServer();
}
}
void parseData()
{
if (newData == true)
{
Serial.println("This just in ... ");
char *str;
char *p = receivedChars;
while ((str = strtok_r(p, ":", &p)) != NULL)
{
parsed[ledCount] = str;
Serial.println(parsed[ledCount]);
ledCount++;
}
ledCount = ledCount - 1;
newData = false;
lightLEDs();
}
}
void lightLEDs()
{
Serial.println("About to light them up ... ");
Serial.println("Refreshing LEDs ... ");
refreshLEDs();
Serial.println("Clearing ALL LEDs ... ");
clearLED(0);
for (int i = 0; i <= ledCount; i++)
{
long LED = atol(parsed[i]);
Serial.print("Setting LED: ");
Serial.println(LED);
setLED(LED);
}
}
Points to note:
On my test board I only have 2 shift registers and the code reflects this
My input sequence (from PHP) has now changed from "" to "<5:9:15>"
The output displayed on the serial monitor is what I expect
Starting ...
127.0.0.1
connecting to server...
making HTTP request...
This just in ...
5
9
15
About to light them up ...
Refreshing LEDs ...
Clearing ALL LEDs ...
Setting LED: 5
Setting LED: 9
Setting LED: 15
BUT instead of LED 5, 9 and 15 lighting up LED 9, 10, 11 and 14 are lit up