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?

  • Your sprintf() line doesn't seem to make sense. What are you trying to get it to do? – Peter Bloomfield Jul 16 '15 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]; – Fid Jul 16 '15 at 14:44
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.)

| improve this answer | |
  • 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. – Fid Jul 16 '15 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. – Peter Bloomfield Jul 16 '15 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. – JRobert Jul 22 '15 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); 
}
| improve this answer | |
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 = ',';
| improve this answer | |
  • 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". – Fid Jul 21 '15 at 16:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.