0

I'm attempting to send data from a serial connection to a GSM modem, but having problems. The string from rx looks like this:

1.0 2.0 3.0 4.0

Here's my code to replace the spaces and then I just want to pass the whole string on, regardless of what's inside (there could be negative values too).

 data_current[data_index++] = ',';
 char received = bike_port.read(); //bike
 char test[32];
 inData += received; 
 if (received == '\n')
 {
 String nospace = inData;
 nospace.replace("\t",",");
 debug_println("Data: ");
 debug_println(nospace);
 inData = ""; // Clear recieved buffer
 delay(1000);
 } 
 sprintf(test,32,"%d,%d,%d,%d",(String) nospace);
 //strtok(received, tmp);
 for (int i=0; i<strlen(test); i++) {
 data_current[data_index++] = test[i];
 } 

I have also tried

sprintf(test,32,"%ld,(String) nospace);

What I get now is this error

cannot pass objects of non-trivially-copyable type 'class String' through '...'

Without the sprintf line I can successfully echo the string to debug_println (Serial Monitor). What am I doing wrong?

asked Jul 16, 2015 at 12:58
2
  • Your sprintf() line doesn't seem to make sense. What are you trying to get it to do? Commented Jul 16, 2015 at 14:10
  • I basically just need 'nospace' to be added to data_current. Maybe I should try for (int i=0; i<strlen(nospace); i++) { data_current[data_index++] = nospace[i]; Commented Jul 16, 2015 at 14:44

3 Answers 3

1

The basic problem here is that you're trying to pass a String object to sprintf(). That isn't possible because String is a C++ class, and sprintf() is a C variadic function. The only way to pass a string to it is as a char *.

The rest of your call to sprintf() doesn't seem to make sense either, although I suspect it's not what you actually want here. You'd normally use sprintf() if you want to format several values into a string.

As you've suggested in the comments, adding the contents of nospace to data_current character-at-a-time would be the sensible approach. You could do it something like this:

for (int i = 0; i < nospace.length(); ++i) {
 data_current[data_index++] = nospace[i];
}

Note that strlen() won't work on nospace because it's a String object not a char array.

This is all assuming that there's enough space in data_current though. Without seeing the rest of your code, I can't tell you if it will definitely work or not.


Update:
As an alternative, you could use memcpy() to do a block transfer:

memcpy(data_current + data_index, nospace.c_str(), nospace.length());
data_index += nospace.length();

I'm not sure there's much benefit to doing that though. It's hypothetically more efficient, but it probably won't make a noticeable difference unless your string is moderately long and it's being called very frequently. (It's trading-off the loop overhead against a function-call overhead.)

answered Jul 16, 2015 at 14:54
3
  • There should be enough space, if not, I know where to change it. But is there a way to add the whole content of nospace, not a character at a time? Because it then gets sent through GSM. I don't know what the exact character length will be, but I do know the maximum. Commented Jul 16, 2015 at 15:06
  • @Fid You could use memcpy() in theory, although I don't know how much difference it will really make. I've updated my answer with details anyway. Commented Jul 16, 2015 at 15:59
  • "But is there a way to add the whole content of nospace, not a character at a time?" Yes and no: Yes, you can express it that way in C++; adding strings translates into concatenation. No, because for most processors, and for AVR's in particular, it ultimately involves a character by character copy. In other words, write it however it reads best to you. It won't make much difference at run time. Commented Jul 22, 2015 at 14:39
0

As a companion to Nick Gammon's excellent answer, here is a streaming version of that (assuming this is coming in one serial port and out another to the modem).

if (Serial.available()) {
 int inByte = Serial.read();
 if (inByte == ' ')
 Serial1.write(',');
 else
 Serial1.write(inByte); 
}
answered Jul 17, 2015 at 1:35
0

Let me get this straight. You want to change:

1.0 2.0 3.0 4.0

to:

1.0,2.0,3.0,4.0

Right?

How about:

 char indata[32] = "1.0 2.0 3.0 4.0";
 int len = strlen (indata);
 for (int i = 0; i < len; i++)
 if (isspace (indata [i]))
 indata [i] = ',';
 Serial.println (indata); // prints: 1.0,2.0,3.0,4.0

Only problem is that when I change "1.0 2.0 3.0 4.0" to the actual incoming read (bike_port.read()), than I get error ...

In that case, as Jake C said, modify the incoming byte like this:

 char received = bike_port.read(); //bike
 if (isspace (received))
 received = ',';
answered Jul 16, 2015 at 21:16
1
  • This works wonderfully. Only problem is that when I change "1.0 2.0 3.0 4.0" to the actual incoming read (bike_port.read()), than I get error "array must be initialized with a brace-enclosed initializer". Commented Jul 21, 2015 at 16:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.