groundFungus:
I suggest that you look at the serial input basics tutorial. It will show how to do serial reception into a null terminated character array (c_string). That avoids the use of the potentially troublesome String class and the examples are non-blocking.
Example #5 shows how to parse data using a delimiter (:).
Thank you for the hint. I had a look at the code in Example #5 and it was very enlightening. I previously didn't know how to approach this problem. During my research, i read that there is an issue of String being a memory hog considering the limited resources of the UNO.
steve20016:
Which RTC are you using? One thing to consider: the DS3231, for example, has built-in alarms that can be configured in a number of ways.
I am using the DS1302. It's the only RTC that i have ever worked with, but i will have a look at the one that you suggested.
Here is my sketch:
// Receive integers with start- and end-markers combined with parsing
// non-destructive
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// integer variables to hold the parsed data
int integer1FromPC = 0;
int integer2FromPC = 0;
boolean newData = false;
//============
void setup() {
Serial.begin(9600);
Serial.println("Enter data in this style: <12, 24>");
Serial.println();
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0; // variable that defines where to store the next character in the array (an index, in other words).
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.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; // reset the ndx counter
newData = true; // set new data status to available
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars, ","); // get the first part - the string
//strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
integer1FromPC = atoi(strtokIndx); // convert this part to an integer (ASCII to int)
//strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
//integer1FromPC = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
integer2FromPC = atoi(strtokIndx); // convert this part to an integer (ASCII to int)
}
//============
void showParsedData() {
Serial.print("First Integer: ");
Serial.println(integer1FromPC);
Serial.print("Second Integer: ");
Serial.println(integer2FromPC);
}
The code above compiles without errors and i did some basic testing and it seems to work. But i'm wondering if i missed anything that could cause the program to crash or maybe memory overflow??
And here is a different (and maybe improved?) version of this sketch whereby there is no copy of the original string since it is not needed in this project. I found the relevant code snippet for parseData() by sterretje from reply #7 in interpreting a string - Programming Questions - Arduino Forum
// Receive integers with start- and end-markers combined with parsing
// destructive
const byte numChars = 32;
char receivedChars[numChars];
//char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
int integer1FromPC = 0;
int integer2FromPC = 0;
boolean newData = false;
//============
void setup() {
Serial.begin(9600);
Serial.println("Enter data in this style: <12, 24>");
Serial.println();
}
//============
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
//strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
showParsedData();
newData = false;
}
}
//============
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0; // variable that defines where to store the next character in the array (an index, in other words).
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.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; // reset the ndx counter
newData = true; // set new data status to available
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData()
{
// find comma
char *ptr = strchr(receivedChars, ',');
// if no comma found
if (ptr == NULL)
{
return;
}
// replace comma by null chracter
*ptr = '\0';
// convert
integer1FromPC = atoi(receivedChars);
// restore comma
*ptr = ',';
// point to position after comma
ptr++;
// convert
integer2FromPC = atoi(ptr);
}
//============
void showParsedData() {
Serial.print("First Integer: ");
Serial.println(integer1FromPC);
Serial.print("Second Integer: ");
Serial.println(integer2FromPC);
}
Could i have used this method instead: string.toInt(); to convert string to int? Is it better?
Any recommendations on how/if i can make this code better (as in, more reliable and efficient)?