I'm trying to modify the UdpServer example from the UIPEthernet library so that I can send my arduino short messages over UDP, like "SR125", then split that message into "SR1" (meaning servo 1) and then the value "25". I get the "SR1" message filtered out just fine, it converts to string, but getting the number part from the char* seems more tricky..
If anyone could give me a push in the right direction I would be very happy!
void loop() {
Â
 // initialization of the variables
 char command[3];   // commandstring
 String value = "";    // string with the value
 unsigned int vnumber; // the value as integer
 boolean flag = true; // a flag to seperate the command from the value
Â
 //check for new udp-packet:
 int size = udp.parsePacket();
 if (size > 0) {
  int i=0;
  do
   {
    char* msg = (char*)malloc(size+1);
    int len = udp.read(msg,size+1);
    msg[len]=0;
    Serial.print("received: '");
    Serial.print(msg);
   Â
     command[0]=msg[0];
     command[1]=msg[1];
     command[2]=msg[2];
     value= String(msg[3])+String(msg[4])+String(msg[5]);
    free(msg);
   }
  while ((size = udp.available())>0);
  //finish reading this packet:
  udp.flush();
  Serial.println("'");
 Â
 Â
  command[3] = '\0';
  value += "\0";   // necessary - the string ends here
  vnumber = value.toInt(); // string to integer, but it doesn't seem to do the trick
 Â
  Serial.println(command);
  Serial.println(value); // this now prints a blank space
  Serial.println(vnumber); // this now prints 0 no matter what number it gets
 Â
  // this part converts the command to hardware
  if (String(command) == "SR1")
  {
   Servo1.write(vnumber);
  }
  if (String(command) == "SR2")
  {
   Servo2.write(vnumber);
  }
 }
}
gorgon:
...like "SR125", then split that message into "SR1" (meaning servo 1) and then the value "25". I get the "SR1" message filtered out just fine, it converts to string, but getting the number part from the char* seems more tricky..
As Paul says, atoi() is your friend.
You might want to think about splitting your message on the 'SR' then convert the '1' into an integer, which you might use as an index into an array of servos.
Also. Read your code again. You enter the IF conditional when size is > 0 but then proceed to always reading a message of more than one byte. Is that what you mean to do?
but getting the number part from the char* seems more tricky..
Using atoi() is tricky?
trickiness is relative i guess, so tricky for me being unexperienced
So, atoi will convert anything to integer, that's great. Then I would need first to convert the char array from say: 2, 5, 6 into 256, and not into 2+5+6 as integers and end up with 13. I guess that's where impulse to convert it to a String came from, I'm coming from Smalltalk (/Supercollider). How would I go about this in arduino?
PaulS:
char* msg = (char*)malloc(size+1);
Not a good idea. You know the maximum (reasonable) size of a packet. Allocate a fixed size array.
MattS-UK:
You might want to think about splitting your message on the 'SR' then convert the '1' into an integer, which you might use as an index into an array of servos.
That's a good idea, thanks!
MattS-UK:
Also. Read your code again. You enter the IF conditional when size is > 0 but then proceed to always reading a message of more than one byte. Is that what you mean to do?
This is in the UdpServer example from the UIPEthernet lib. I thought this meant that it won't perform udp.read unless there's anything to read...
Naw...my comment was meant to be tongue-in-cheek. atoi() expects a null-terminated sequence of characters. So if you want to convert it to a number with an input string of "SR125" and expect to get 25 back, you would need to use:
val = atoi(&msg[3]);
which assumes msg is a null-terminated character array. As to my comment, you could use:
val = ((mess[3] - '0') * 10) + ((mess[4] - '0');
and get the right value, but that seems to be the hard way to do it.
If i send values over 100 it's fine, but it gets problematic with lower values like 25 because then the 2 is multiplied by 100 and the 5 is multiplied by 10, and the last msg[5] gets the value of -48 which I don't know the reason for.
Every time you press a key on your keyboard, a key code gets sent from the keyboard to the computer. These are called ASCII codes. The keycode for a zero is 48, for 1 it's 49, 2 is 50, and so on. So, assuming msg[3] is the character '2', the expression:
msg[2] - '0'
resolves to:
msg[2] - '0'
'2' - '0'
50 - 48
2
Therefore, subtracting the ASCII key code for zero from any numeric digit character gives you that character as a numeric.
Finally, give up on the conversions on msg[]. Instead, if you can't assuming the incoming message is a null-terminated character array, try this:
char msg[7];
int len;
memset(msg, '\0', 7);Â // Set all elements to null
len = udp.read(msg,7);
// msg[len] = '\0';Â Â Â Â Â // You could do away with memset() statement if the
               // read() call does return the message length.
value = atoi(&msg[3]);
You said that the number can never be more than 255, so at most, you need 7 characters: "SR1255", or 6 plus one for the null termination character. The memset() call sets all elements to null, so you know whatever comes in has a null at the end of the array. Get rid of malloc() and free(), they just aren't a real good idea if they can be avoided.
I think it does answer your questions. If you need to know which servo, and it is always the 3rd character, then:
int servoNumber;
int value;
int len;
char msg[7];
servoNumber = msg[2] - '0';Â // Servo number
len = udp.read(msg,7);
msg[6] = '\0';
value = atoi(&msg[3]);Â Â Â Â // Value from the read
gorgon:
This is in the UdpServer example from the UIPEthernet lib. I thought this meant that it won't perform udp.read unless there's anything to read...
What would happen were a properly formed UDP packet containing just 1 byte, arrive at your network interface?
Buffer checking is a hot topic at the moment. A similar bug caused the Heartbleed exploit, which has been all over the news recently.