Thanks to this forum I've been able to transmit and receive data using the RFM69 library. Now that I have characters in a char object I'm wanting to parse out and assign each item to string variables. All the posts I've seen are taking a char of data to compare with the input, typically Serial. In my case, my data is not from Serial. I get that char cannot be compared to (char *)radio.DATA. They're different types. I'm struggling to find a method to cast (char *)radio.DATA as char so that I can compare string objects. The data I'm getting from my transmitter is
#include <RFM69.h> //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
const int numChars = 65;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
int counter = 0;
int lastIndex = 0;
String input;
void setup() {
while (!Serial); // wait until serial console is open, remove if not tethered to computer. Serial.println("Feather RFM69HCW Receiver");
// Initialize radio
radio.initialize(FREQUENCY,NODEID,NETWORKID);
}
void loop() {
//check if something was received (could be an interrupt from the radio)
if (radio.receiveDone())
{
if ((char *)radio.DATA)
{
for(int i=0; i < 61; ++i) {
input[i] = Serial.println((char *)radio.DATA);
}
Serial.print("input= ");
Serial.print(input);
Serial.print("\r");
}
}
}
radio.receiveDone(); //put radio in RX mode
}
As I said, I get that this stunt I tried to pull here to try to iteratively pass each character from the DATA into a string is wrong. As you would know, it's just passing the DATA to Serial 61 times. But
input is not the same type as this DATA. What can I do to cast this into something I can parse? Perhaps there's some methods in this char * that will let me parse. Or just convert it into a string and use those methods? I think that Arduino and C++ share some syntax but not methods so I'm unsure which direction to go. Thanks for pointers
How do you know that you have the data? I don't have the hardware to test this, so is there a buffer in the radio object that is holding the data? It appears that radio.DATA is a property, not a method (or function). What is the method that the radio object makes available to read the data it has?
econjack:
How do you know that you have the data? I don't have the hardware to test this, so is there a buffer in the radio object that is holding the data? It appears that radio.DATA is a property, not a method (or function). What is the method that the radio object makes available to read the data it has?
From RMF69.h it looks like '.DATA' is a public array of uint8_t. The examples cast it as a pointer to the actual type of data being transferred (i.e. struct *, char *, etc).
If all of this:
"wx,1.8,6.4,0.0,33,99.0,188.6,99.1,31.6,61.1,270.0,3.0"
is in a string: an array of char terminated with a trailing '\0', the the strtok function is what you need. This is a standard C/C++ library function in libc, which comes as standard with pretty much all C compilers.
The documentation for #include <string.h> is here.
There is no substitute for simply reading that page and getting a feel for what functions are available in the standard library.
Yes, thank you for the pointer to this library. I was not finding any methods to what can be done with the char * type. Using your suggestion to use char * strtok() I referred back to the Serial Basics use of parsing that Robin2 pointed.
I'm trying to get past the compile errors so using this simplest version. Since this all should be using the char * type I'm still getting compile errors that don't yield results that seem meaningful to me in my Google searches. Mostly because of my ignorance of pointers and what can be done with them.
RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);
const int numChars = 65;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
int counter = 0;
int lastIndex = 0;
char* mytype[2] = {0};
char* winds[10] = {0};
char* windg[10] = {0};
char* rain[10] = {0};
char* btemp[10] = {0};
char* bp[10] = {0};
char* ba[10] = {0};
char* bsea[10] = {0};
char* temp[10] = {0};
char* humid[10] = {0};
char* windd[10] = {0};
char* windv[10] = {0};
char* endMarker = ">";
void parseData() {
// split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok((char *)radio.DATA,","); // get the first part - the string
strcpy(mytype, strtokIndx); // copy it to mytype
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
winds = strcpy(winds, strtokIndx); // convert this part to a text
strtokIndx = strtok(NULL, ",");
windg = strcpy(windg, strtokIndx); // convert this part to a text
}
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly:
}
My errors:
receiver_sam_simpler.ino: In function 'void parseData()':
receiver_sam_simpler:57: error: cannot convert 'char**' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
receiver_sam_simpler:60: error: cannot convert 'char**' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
receiver_sam_simpler:63: error: cannot convert 'char**' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
cannot convert 'char**' to 'char*' for argument '1' to 'char* strcpy(char*, const char*)'
OK, assuming that argument '1' isn't zero based, that suggests that my char * for each variable is being converted into char **? What does that mean? It appears that strcpy is a valid char * method so I should be able to use it. The Serial Basics link is assuming String? Or char? I ask because I've not been able to figure this char * out. Why is this not in a separate post? Because this seems to me to all part of parsing out char * and it might help others in this context.
Ultimately my goal is to take this data and interpolate it into a string that will be sent to std input on the computer.
"curl localhost '-d{"windspeed": " + winds +"}'" etc.
econjack:
Usually strtok() is used in a very precise way, similar to:
That is similar to the parse example in Serial Input Basics except that my version "knows" that there are just 3 pieces of data whereas your's is open-ended.
Yes, it's similar to Serial Basic but I'm unsure how to assign each to a variable OR access them in an array. As it goes around in a loop, it's spitting back out the first ptr variable as the function docs say it would.
An array would be fine but then I'm still dealing with assigning a char * to an incompatible type?
reply #6 implies that data that is (char *) is equivalent to char? In my limited knowledge, I don't find that to be true. Because I'm wrong, I'm posting here, and reading lots of search posts, to make attempts. In econjack's reply I don't see any way to safely assign each iteration of ptr to a variable. So I'm attempting to make an array of char * to catch them and then build my command.
#include <SPIFlash.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_IS31FL3731.h>
#include <RFM69.h> //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>
RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HCW, RFM69_IRQN);
const int numChars = 65;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
char * radio.DATA = "wx,1.8,6.4,0.0,33,99.0,188.6,99.1,31.6,61.1,270.0,3.0";
int counter = 0;
int lastIndex = 0;
char mytype[3] = {0};
char winds[10] = {0};
char windg[10] = {0};
char rain[10] = {0};
char btemp[10] = {0};
char bp[10] = {0};
char ba[10] = {0};
char bsea[10] = {0};
char temp[10] = {0};
char humid[10] = {0};
char windd[10] = {0};
char windv[10] = {0};
char *endMarker = ">";
char *ptr[12]; //incompatible types in assignment of 'char*' to 'char* [12]
void setup() {
// Initialize radio
radio.initialize(FREQUENCY,NODEID,NETWORKID);
}
void loop() {
//check if something was received (could be an interrupt from the radio)
if (radio.receiveDone())
{
//print message received to serial
// Serial.print((char*)radio.DATA);
char * mytokens;
char *p, *i;
char *wx = {};
//check if received message
if ((char *)radio.DATA)
{
//parseData();
//showParsedData();
ptr = strtok((char *)radio.DATA, ",");
// if ptr == "wx" & sizeof(ptr) > 1 { // because I'm in a loop and the strtok() clears out all but the first value in a repeat until new DATA comes in. I need to only do this when I get new DATA in to parse
while (ptr != NULL)
{
Serial.println(ptr);
ptr = strtok(NULL, ",");
wx << ptr //invalid operands of types 'char*' and 'char*' to binary 'operator<<' so another mismatch
}
//char command = 'curl localhost -D {"windspeed": ' + ptr[1] + '"windgust:" ' + ptr[2];
// }
}
}
//delay(100);
}
radio.receiveDone(); //put radio in RX mode
Serial.flush(); //make sure all serial data is clocked out before sleeping the MCU
}
void parseData() {
// split the data into its parts
ptr = strtok((char *)radio.DATA, ",");
while (ptr != NULL)
{
ptr = strtok(NULL, ",");
}
}
void showParsedData() {
// Serial.print("Wind Speed: ");
// Serial.println(winds);
// Serial.print("Wind Gust: ");
// Serial.println(windg);
Serial.println(ptr);
}
So making ptr an array of char * returns
incompatible types in assignment of 'char*' to 'char* [12]
In my reading, it appears I cannot make an empty array. I have to instantiate all its members when I do so and I cannot add to it like I can in dynamic languages. And how to do it in this while loop escapes me. Thanks for your pointers and advice, sam
sam452:
. In econjack's reply I don't see any way to safely assign each iteration of ptr to a variable. So I'm attempting to make an array of char * to catch them and then build my command.
Clearly I'm missing something because saving the results from strtok() is pretty simple:
void setup() {
char testStr[] = "wx,1.8,6.4,0.0,33,99.0,188.6,99.1,31.6,61.1,270.0,3.0";
char *ptr;
char *result[20]; // Large enough to hold each datum
int count;
int i;
Serial.begin(9600);
Serial.print("Test string: ");
Serial.println(testStr);
i = 0;
ptr = strtok (testStr,","); // Look for commas...
while (ptr != NULL)
{
result[i++] = ptr;
ptr = strtok (NULL, ",");
}
count = i;
for (i = 0; i < count; i++) {
Serial.println(result[i]);
}
}
void loop() {
}