Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

So simple question about file descriptor


#1

Hi,
I have a simple question about file descriptor.

When I run my program, my file descriptor value is 3.
I thought I have to get either one from 0 to 2.

What does that mean?
Please let me know!
Thank you =]


#2

Your code shouldn’t care about the actual value of file descriptors. You should treat them as arbitrary integers that could be anything. Programs are allowed to open more than 3 files at a time so of course you should expect to get file descriptors that are outside of the 0-2 range. Anyway, the 0-2 range is used for the the standard files (stdin, stdout, and stderr) so if you open another file I would expect the file descriptor to be a different number.

Your question contains very little information. If you want more help, please read this post first:

–David


#3

Thank you for your kind reply David!

Here is more detailed information about current question I’m struggling with

Here is the code I got from one of the posts Paul created:

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>

int main()
{
  int fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY);
  char message[] = {161};
  unsigned char buf[2];
  struct termios options;

  if (fd == -1)
  {
    fprintf(stderr, "error opening");
    exit(1);
  }

  tcgetattr(fd, &options);
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  tcsetattr(fd, TCSANOW, &options);

  if(write(fd,message,4) == EOF)
  {
    fprintf(stderr, "error writing");
    exit(1);
  }

  int bytes_read = read(fd,buf,2);
  if(bytes_read != 2)
  {
    fprintf(stderr, "error reading: %d bytes read", bytes_read);
    exit(1);
  }

  printf("Received: 0x%02x 0x%02x\n",buf[0],buf[1]);

  exit(0);
}

Since the code itself did not work properly, I had to include unistd.h and additionally put " | O_NDELAY " for getting fd value.

However, everytime I run this, I always gets bytes_read to -1.
Paul said it is working but not with me.
Please hep!


#4

What Pololu product are you using? What serial mode is it in (if applicable)? What is the output of ls /dev/ttyACM* ?

–David


#5

I’m using maestro 24


#6

and I’m working on Ubuntu using C and when I make an output I have ttyACM0 and ttyACM1!
Thank you!


#7

This is the testing code I’m working on(for write the code):

 #include <fcntl.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    int main()
    {
      int fd = open("/dev/ttyACM0", O_RDWR | O_NONBLOCK);
      char message[] = {161};
      char buf[2];


   int buffSize = 4;
   unsigned char buff[buffSize]; // The data to be sebt to the servo controller.
   unsigned char test[4];

   int getposition=2;
unsigned char gp[getposition];
gp[0] = 0x90;
gp[1] = 0x01;

int target = 1460;

   buff[0] = 0x84;       // Command byte: Set Target. 
   buff[1] = 0x01;       //channel; // First data byte holds channel number. 
   buff[2] = target & 0x7F;    // Second byte holds the lower 7 bits of target. 
   buff[3] = (target >> 7) & 0x7F;   // Third data byte holds the bits 7-13 of target.

  
    struct termios options;
      if (fd == -1)
      {
        fprintf(stderr, "error opening");
        exit(1);
      }

  printf("printing..fd: %d\n\n", fd);

      tcgetattr(fd, &options);
      options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
      tcsetattr(fd, TCSANOW, &options);

      int bytes_write = write(fd,buff,4);
  printf("printing..br: %d\n", bytes_write); 

      exit(0);
    }

My servo is not moving at all.
I was able to print “4” when I’m printing bytes_write though.

This is another testing code for reading:


 #include <fcntl.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    int main()
    {
      int fd = open("/dev/ttyACM0", O_RDWR | O_NONBLOCK);
      char message[] = {161};
      char buf[2];


   int buffSize = 4;
   unsigned char buff[buffSize]; // The data to be sebt to the servo controller.
   unsigned char test[4];

   int getposition=2;
unsigned char gp[getposition];
gp[0] = 0x90;
gp[1] = 0x01;


  
    struct termios options;
      if (fd == -1)
      {
        fprintf(stderr, "error opening");
        exit(1);
      }

  printf("printing..fd: %d\n\n", fd);

      tcgetattr(fd, &options);
      options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
      tcsetattr(fd, TCSANOW, &options);

     bytes_write = write(fd,message,1);
  printf("printing..br: %d\n", bytes_write);
       
int bytes_read =0;

while(bytes_read!=2){
    usleep(10000);
    bytes_read= read(fd,&buf,2);
      printf("printing..rd: %d\n\n", bytes_read);

      }
 
      
if(bytes_read != 2)
      {
        fprintf(stderr, "error reading: %d bytes read\n", bytes_read);
        exit(1);
      }

      printf("Received: 0x%02x 0x%02x\n",buf[0],buf[1]);

      exit(0);
    }

I was able to get right values for bytes_write.
However, I consistently get “-1” for bytes_read.

Please please help me!!
Thank you!!


#8

Hello.

You still haven’t said what serial mode you are in. It is on the serial settings tab of the control center.

- Ryan


#9

I’m not quite sure I’m serial mode I’m in right now since I haven’t use the control center at all.
I’m working directly onto the board and linux on my Ubuntu.
Is is mandatory to use it and figure out what serial mode i’m in?


#10

The default serial mode is “UART, detect baud rate,” which won’t work with what you are trying to do, I think. You will need to change it. The control center should work on Ubuntu.

- Ryan


#11

Wow!
I was able to install the control center Thanks!!

Yeah, default setting says its serial mode is UART, detect baud rate.
What should I do now?


#12

Hello.

A good first step would be to read the user’s manual to understand what the serial mode options mean:

pololu.com/docs/0J40/5.a

In “detect baud” mode, you must first send the byte 0xAA to the controller so it can learn the baud rate. In fixed baud mode, the controller’s UART runs at the specified baud and the initial 0xAA is not required.

If something is still unclear, please let us know.

- Ben


#13

Hello,

Now, I decided to use USB Chained mode for my serial mode.
It seems “kind of” working since now I can see proper return values of read() and write() functions.

However, even if I set the target of my servo and try to read current position, what I’m getting is that the servo
is not moving at all and 0x00 for both return values for get position command.
Here is my code:

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main()
{
  int fd = open("/dev/ttyACM0", O_RDWR | O_NONBLOCK);
  char message[] = {161};
  char buf[2];
  
  
  int buffSize = 4;
  unsigned char buff[buffSize]; // The data to be sebt to the servo controller.
  unsigned char test[4];
  
  int getposition=2;
  unsigned char gp[getposition];
  gp[0] = 0x90;
  gp[1] = 0x00;
  
  int target = 1460;
  
  buff[0] = 0x84;       // Command byte: Set Target. 
  buff[1] = 0x00;       //channel; // First data byte holds channel number. 
  buff[2] = target & 0x7F;    // Second byte holds the lower 7 bits of target. 
  buff[3] = (target >> 7) & 0x7F;   // Third data byte holds the bits 7-13 of target.
  
  
  struct termios options;
  if (fd == -1)
    {
      fprintf(stderr, "error opening");
      exit(1);
    }
  
  printf("printing..fd: %d\n\n", fd);
  
  tcgetattr(fd, &options);
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  tcsetattr(fd, TCSANOW, &options);

  int bytes_write = write(fd,buff,4);
  printf("printing..br: %d\n", bytes_write); 
  
  bytes_write = write(fd,message,1);
  printf("printing..br: %d\n", bytes_write);
  
  int bytes_read =0;
  
  while(bytes_read!=2){
    usleep(10000);
    bytes_read= read(fd,&buf,2);
    printf("printing..rd: %d\n\n", bytes_read);
    
  }
  
  
  bytes_write = write(fd,gp,2);
  printf("printing..br: %d\n", bytes_write);
  
  while(bytes_read!=2){
    usleep(10000);
    bytes_read= read(fd,&buf,2);
    printf("printing..rd: %d\n\n", bytes_read);
    usleep(10000);
  }
  
  
  
  if(bytes_read != 2)
    {
      fprintf(stderr, "error reading: %d bytes read\n", bytes_read);
      exit(1);
    }
  
  printf("Received: 0x%02x 0x%02x\n",buf[0],buf[1]);
  
  exit(0);
}

Help!!
Thank you!


#14

Hello,

Can you post the complete output from running that program?

-Paul


#15

Here you are Paul!

printing…fd: 3

printing…br: 4
printing…br: 1
printing…rd: 2

printing…br: 2
Received: 0x00 0x00


#16

Oh, you used “&buf” instead of just “buf” as the argument to read. Did you not get a warning when compiling that?

-Paul


#17

when I compile it, I simply used “g++ test4.cc -o test”

and I didn’t get any warning. do I have to get rid of it try again?


#18

even if I get rid of & from “&buf”, I still have the same outcome.


#19

Do you think different setting on control center (like channel setting??) might affect the result differently?


#20

Okay, I guess C does not give a warning in this case. But you still should be using “buf” and not “&buf”, since buf itself is already a pointer.

You are still in USB Chained mode, right? Do you see channel 0 moving at all if you watch it in the control center when running this program?

Can you control channel 0 from the Control Center?

-Paul