Difficulty manipulating char/int.

I have a program that lets me telnet into the arduino, and send a angle, with the character “a” afterwards, and the connected servo will go to that position. For instance “140a” will will make the servo go to 140 degrees. The code is at follows

#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>

byte mac[] = { 
  0x90, 0xA2, 0xDA, 0x0D, 0x58, 0x14 };
byte ip[] = { 192, 168, 1, 210 };


//sets up the server (telnet, port 23)
EthernetServer server(23);
EthernetClient client;
boolean connected = false; 
Servo myservo;

const byte BUFFER_LENGTH = 4; // make this long enough to hold your longest command
char buffer[BUFFER_LENGTH+1]; // +1 allows space for the null terminator
byte bufferCount;

                         
void setup() {
   
//starts the server
   Ethernet.begin(mac, ip);
   server.begin();
   myservo.attach(3);
  
}

void loop() {
   // checks if a client connects
   EthernetClient client = server.available();

   if (client) {
       
  
     while (client.connected())
        {
            if (client.available())
            {
                char c = client.read();
                if(c == 'a')
                //is "a" is sent, client is disconnected and the command will be sent to the servo
                {
               
                  handleMessage(buffer);
                    bufferCount = 0; 
                    buffer[bufferCount] = 0;
                    client.stop();
                    //resets all variables and disconnects the client
                }
                else
                {
                    if(bufferCount < BUFFER_LENGTH)
                    {
                        buffer[bufferCount++] = c;
                        buffer[bufferCount] = 0; // append null terminator, I am not quite sure what this does
                      
                    }
                    else
                    {
                        client.stop();
                    }
                }
            }
        }
    }
}

    
void handleMessage(char *msg) //what are theese variables?
{
int pos;
pos = atoi(buffer);
  myservo.write(pos);
}

This code works fine, I don’t know much programming, so I have gotten some help in making the code. So I sorry if my question is very simple

Anyhow, I have tried to modify the code, so i can also input the different servo positions, since the board have several servos connected. I think the easiest input would be something like this:

3140a will move servo 3 to 140 degrees and 4030a would move servo 4 to 30 degrees.

The modified code is like this:

#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>

byte mac[] = { 
  0x90, 0xA2, 0xDA, 0x0D, 0x58, 0x14 };
byte ip[] = { 192, 168, 1, 210 };


//sets up the server (telnet, port 23)
EthernetServer server(23);
EthernetClient client;
boolean connected = false; 
Servo myservo;

const byte BUFFER_LENGTH = 5; // make this long enough to hold your longest command
char buffer[BUFFER_LENGTH+1]; // +1 allows space for the null terminator
byte bufferCount;

                         
void setup() {
   
//starts the server
   Ethernet.begin(mac, ip);
   server.begin();
   
  
}

void loop() {
   // checks if a client connects
   EthernetClient client = server.available();

   if (client) {
       
  
     while (client.connected())
        {
            if (client.available())
            {
                char c = client.read();
                if(c == 'a')
                //is "a" is sent, client is disconnected and the command will be sent to the servo
                {
               
                  handleMessage(buffer);
                    bufferCount = 0; 
                    buffer[bufferCount] = 0;
                    client.stop();
                    //resets all variables and disconnects the client
                }
                else
                {
                    if(bufferCount < BUFFER_LENGTH)
                    {
                        buffer[bufferCount++] = c;
                        buffer[bufferCount] = 0; // append null terminator, I am not quite sure what this does
                      
                    }
                    else
                    {
                        client.stop();
                    }
                }
            }
        }
    }
}

    
void handleMessage(char *msg) //what are theese variables?
{
char servopos;
servopos = buffer[0]; // read out the first digit of the number  
int servposint = servopos; //make the char into an int

myservo.attach(servposint); //attach the servo taht the first number has given us
int pos;
pos = atoi(buffer);
pos=pos-(servopos*1000); // deduct the first part of the number (for instance 3140 will be 140, so the servo will move to 140 degrees)
  myservo.write(pos);
}

The changed part of the code is this part:

void handleMessage(char *msg) //what are theese variables?
{
char servopos;
servopos = buffer[0]; // read out the first digit of the number  
int servposint = servopos; //make the char into an int

myservo.attach(servposint); //attach the servo taht the first number has given us
int pos;
pos = atoi(buffer);
pos=pos-(servopos*1000); // deduct the first part of the number (for instance 3140 will be 140, so the servo will move to 140 degrees)
  myservo.write(pos);
}

But something goes wrong in this part of the code, so it doesn’t work as planned. Any tips?

I'd put in some serial logging, so you can find out what it thinks that key variables are while it's doing that. I'd have it log the data it got down the line, and what it is after you remove the servo number, etc. That way, you can see exactly where it's going wrong.

ATWindsor: But something goes wrong in this part of the code, so it doesn't work as planned. Any tips?

What does it do instead? The nature of the bad behavior can sometimes point the way to a solution.

You would wise to understand the working program before going any further

buffer[bufferCount] = 0; // append null terminator, I am not quite sure what this does

You are creating a zero terminated array of chars and this line puts a zero in the next position in the array ready for the time when all of the characters have been received.

void handleMessage(char *msg) //what are theese variables?

This function takes the data in the buffer array, known as msg within the function, passed as a pointer to the array, hence the asterisk, as a parameter. It uses the first entry in (buffer[0])n the array to determine which servo pin to use, attaches the servo to that pin then determines the servo position to move to by using the atoi() (ASCII to integer, takes a zero terminated array of chars as a parameter) function having caused the first digit of the number in the buffer to be removed by multiplying the number by 1000 and subtracting from the value.

//what are theese variables?

The value passed to the function is not used so the variable is a waste of time declaring the function like this or passing a value to it.

DrAzzy: I'd put in some serial logging, so you can find out what it thinks that key variables are while it's doing that. I'd have it log the data it got down the line, and what it is after you remove the servo number, etc. That way, you can see exactly where it's going wrong.

What does it do instead? The nature of the bad behavior can sometimes point the way to a solution.

Is serial logging supposed to work when you send commands over telnet? I never got anything on the serial monitor when i use Serial.print in this program.

The servo usually does nothing, although it seemed to move when i used a random number once, but that number did not correspond to the right servo number.

UKHeliBob: You would wise to understand the working program before going any further

buffer[bufferCount] = 0; // append null terminator, I am not quite sure what this does

You are creating a zero terminated array of chars and this line puts a zero in the next position in the array ready for the time when all of the characters have been received.

void handleMessage(char *msg) //what are theese variables?

This function takes the data in the buffer array, known as msg within the function, passed as a pointer to the array, hence the asterisk, as a parameter. It uses the first entry in (buffer[0])n the array to determine which servo pin to use, attaches the servo to that pin then determines the servo position to move to by using the atoi() (ASCII to integer, takes a zero terminated array of chars as a parameter) function having caused the first digit of the number in the buffer to be removed by multiplying the number by 1000 and subtracting from the value.

//what are theese variables?

The value passed to the function is not used so the variable is a waste of time declaring the function like this or passing a value to it.

So the sole reason for adding the zero is getting the atoi-function to work? How does the atoi function know the difference between the terminating zero and any random zero i input via telnet to give the right angle?

So the whole "Char *msg" could be removed as it is not used?

I think i understand the rest of that particular function (well, I understand what I am trying to get it to do, but since I have failed, I probably am misunderstanding something) , as i have written that my self. (except the pos = atoi(buffer); line).

So the sole reason for adding the zero is getting the atoi-function to work?

Yes

How does the atoi function know the difference between the terminating zero and any random zero i input via telnet to give the right angle?

The program puts a zero into the array. When you input a zero it is an ASCII character representing a zero which is actually the number 48 (decimal). See ASCII table

o the whole "Char *msg" could be removed as it is not used?

Yes, but remove the parameter from the function call as well.

UKHeliBob: Yes The program puts a zero into the array. When you input a zero it is an ASCII character representing a zero which is actually the number 48 (decimal). See ASCII table Yes, but remove the parameter from the function call as well.

Thanks, I understand the bits I was confused about better now, so I have removed them from the program, however, it doesn't seem to change how the program functions, so this part:

void handleMessage()
{
char servopos;
servopos = buffer[0]; // read out the first digit of the number  
int servposint = servopos; //make the char into an int

myservo.attach(servposint); //attach the servo taht the first number has given us
int pos;
pos = atoi(buffer);
pos=pos-(servopos*1000); // deduct the first part of the number (for instance 3140 will be 140, so the servo will move to 140 degrees)
  myservo.write(pos);
}

Still doesn't do what I am trying to do.

Try adding some Serial.print()s to your code to check whether the values. For instance, what is the value of servopos, servoposint and pos in the function ? Are they what you expect ?

3140a will move servo 3 to 140 degrees and 4030a would move servo 4 to 30 degrees.

Does "atoi" correctly handle octal numbers? If it does, you may find your second example there only going to 24 degrees.

Edit: OK, you're not doing it the way I expected.

UKHeliBob: Try adding some Serial.print()s to your code to check whether the values. For instance, what is the value of servopos, servoposint and pos in the function ? Are they what you expect ?

Is serial print supposed to work when you telnet the commands? I never seem to get anything on the serial monitor when i use the serial print in a prgram like this.

AWOL:
Does “atoi” correctly handle octal numbers?
If it does, you may find your second example there only going to 24 degrees.

Edit: OK, you’re not doing it the way I expected.

I don’t think there is any octal numbers anywhere, I havn’t planned for it anyway.

Is there a smarter way to do it? I am not so skilled at this, so I am sure its not the ideal way.

int servposint = servopos; //make the char into an int

It does not make '5' into 5. It makes '5' into 53. Is that what you want?

myservo.attach(servposint); //attach the servo taht the first number has given us

Well, that looks pretty stupid. I suppose you'll call the next value, that defines where to go servopinint.

PaulS: int servposint = servopos; //make the char into an int

It does not make '5' into 5. It makes '5' into 53. Is that what you want?

myservo.attach(servposint); //attach the servo taht the first number has given us

Well, that looks pretty stupid. I suppose you'll call the next value, that defines where to go servopinint.

No, I want to make the 5 into 5.

I am not sure what you mean with the second system? I am sure its correct it looks stupid, I am not very skilled at programming. Waht I am trying to do is if i wirte 5120a, it will pick out the first digit (5), and attache the servo on port 5.

Can I refer you to my suggestion in reply #7 ? Print the variables and see what is really happening.

UKHeliBob: Can I refer you to my suggestion in reply #7 ? Print the variables and see what is really happening.

Well, as I stated in post #3 and #9, i don't get anything on the serial monitor when i use a telnet to give commands in this way. Is serial.print supposed to work when you are not sending commands over the serial connection?

Is serial.print supposed to work when you are not sending commands over the serial connection?

Yes, as long as you have Serial.begin() in the program and have not used the Tx and Rx pins for something else then Serial.print() does not care where what it is printing came from. If it is in a variable then it will print the value. Can you print text ?

Ok, thanks for the tip, now i got the serial print to work.

If i write 2100a the program is supposed to move servo 2 to 100 degrees, so the variable Serveposint" is supposed to be 2, and the variable "pos" is supposed to be 100.

However serposint is 50 and pos is 17636. So something is wrong with the part that makes them in to numbers, maybe something realated to ASCII and numbers beeing repesented as you and PaulS where talking about?

However serposint is 50 and pos is 17636. So something is wrong with the part that makes them in to numbers, maybe something realated to ASCII and numbers beeing repesented as you and PaulS where talking about?

Go back a step. What do you see when you print servopos ?

With the input 2100a:

If i print "servopos" i see "2", if i print "pos" before the line

pos=pos-(servopos*1000);

I get 2100

So both of those are as expected, so somthing goes wrong in

int servposint = servopos;

and maybe also in:

pos=pos-(servopos*1000);

int servposint = servopos;

What do you expect this line to do ?