2013-07-16 3 views
2

Я работаю над проектом, в котором мой компьютер взаимодействует с платой arduino, которая считывает вывод датчика и помещает его в последовательный порт только в том случае, если получено «t». Arduino код, как показано ниже, работает.Чтение из последовательного порта после его записи

const int inputPin = 0; 
void setup(){ 
    Serial.begin(9600); 
    pinMode(13, OUTPUT);} 

void loop(){ 
if (Serial.available() > 0){ 
    char c=Serial.read(); 
    if(c=='t'){ 
     int value = analogRead(inputPin); 
     float celsius = (5.0 * value * 100.0)/1024.0; 
     Serial.println(celsius); 
    } 
    } 
} 

Моя проблема в коде C, когда я пытаюсь прочитать, что Arduino ставит на последовательный порт. Мой код C:

#include<string.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<errno.h> 
#include<unistd.h> 
#include<fcntl.h> 

int main(){  
    int STATE_OK=0; 
    int STATE_WARNING=1; 
    int STATE_CRITICAL=2; 
    char tempbuf[10]; 
    int fd=open("/dev/ttyACM0",O_RDWR | O_NOCTTY | O_NONBLOCK); 
    if(fd == -1){ 
      printf("Unable to open /dev/ttyACM0\n"); 
      return STATE_WARNING; 
    } else { 
     fcntl(fd, F_SETFL, FNDELAY); 
     int w=write(fd, "t", 1); 
     printf("The number of bytes written to the serial port is %d \n",w); 
     fprintf(stderr, "fd = %d.\n", fd); 
     sleep(10); 
     int n=read(fd,tempbuf,5); 
     printf("%d,%s \n",n,strerror(errno)); 
     if(n>0){ 
      float temp=atof(tempbuf); 
      printf("Temperature is: %f Celsius\n", temp); 
      if (temp>27){ 
       return STATE_CRITICAL; 
      }else{ 
       printf("The temperature is %f Celsius and checked 10 seconds ago\n",temp); 
       return STATE_OK; 
      } 
     } 
    } 
    close(fd); 
    return 0; 
} 

n всегда = 0, и я не могу понять, в чем проблема. Спасибо заранее.

+0

Является ли сон достаточным для ответа? – suspectus

+0

Я уже пытался сменить его (1000), но n still = 0, и я думаю, этого достаточно, потому что у arduino есть быстрый ответ. –

+0

По крайней мере, используйте программу типа Putty для проверки того, что ваш ПК может получать данные из последовательного порта. Ошибки проводки, конечно, являются объяснением, а не заботой об установлении связи - это другое. Используя O_NONBLOCK, число 5 и не настраивая параметры порта, такие как скорость передачи данных, также являются хорошими способами, чтобы попасть в проблему. –

ответ

3

я не могу понять, что это проблема

Одна большая проблема заключается в том, что программа C работает на «компьютер» является неполным.

Программа Arduino выполняет настройку последовательного порта, по меньшей мере, скорости передачи (и все, что может быть выполнено по умолчанию).
Но программа «компьютер» C никогда не настраивает последовательный порт. Последовательный порт будет использовать ранее настроенные атрибуты (скорость передачи, длину данных, настройку четности, канонический или сырой режим), что приведет к непредсказуемым чтениям и записи. (Тест на петлевую проверку, вероятно, приведет к ложноположительному результату.)

Используйте код POSIX Serial Port guide или this answer для примера кода.

Для каноническом режиме, вероятно, нужно добавить код, как (при условии, 8N1):

rc = tcgetattr(fd, &tty); 
    if (rc < 0) { 
     /* handle error */ 
    } 
    savetty = tty; /* preserve original settings for restoration */ 

    spd = B9600; 
    cfsetospeed(&tty, (speed_t)spd); 
    cfsetispeed(&tty, (speed_t)spd); 

    tty.c_cflag &= ~PARENB 
    tty.c_cflag &= ~CSTOPB 
    tty.c_cflag &= ~CSIZE; 
    tty.c_cflag |= CS8; 

    tty.c_cflag &= ~CRTSCTS; /* no HW flow control? */ 
    tty.c_cflag |= CLOCAL | CREAD; 

    tty.c_iflag |= IGNPAR | IGNCR; 
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
    tty.c_lflag |= ICANON; 
    tty.c_oflag &= ~OPOST; 

    rc = tcsetattr(fd, TCSANOW, &tty); 
    if (rc < 0) { 
     /* handle error */ 
    } 

Вы, вероятно, следует удалить строку

fcntl(fd, F_SETFL, FNDELAY); 

, а также O_NONBLOCK опцию в open() вызова.

+0

Спасибо за ваш ответ, но, честно говоря, я не понял код, нет другого способа решить проблему без последовательного программирования? Спасибо заранее. –

+0

Есть команда 'stty', но это не на 100% надежнее, как кодирование c onfiguration в программе. Вам необходимо прочитать [Руководство по последовательному порту POSIX] (http://www.cmrr.umn.edu/~strupp/serial.html) и/или [этот ответ] (http://stackoverflow.com/questions/12437593/how-to-read-a-binary-data-over-serial-terminal-in-c-program/12457195 # 12457195) для примера кода. – sawdust

+0

После прочтения руководства по последовательному порту POSIX я редактирую свой код (как вы сказали), и у меня все еще есть n = 0 и c = , я отправлю свой новый код в ответ. –

0

попробовать это вместо

int n=read(fd,&tempbuf,sizeof(tempbuf)); 

из

int n=read(fd,tempbuf,5); 
+0

Спасибо за ваш ответ, но это не сработало :( –

+0

удалить O_NONBLOCK и посмотреть, что произойдет. –

+0

У меня все тот же результат. –

0

Вы не должны прекращать данные, отправленные с '\ 0'? Serge

+0

Спасибо, но это не сработало. –

0

Чтение описания read() (показано ниже) говорит нам, что n = 0, когда вы достигаете конца файла. Поскольку серийный номер не отправляет \ 0, чтение будет продолжаться до тех пор, пока не будет достигнут конец файла. Поэтому я думаю, что n == 0 - результат, который вы хотите.

Так, может быть, ваш если (п> 0)

тест должен быть , если (п == 0)

Вы можете увидеть символы, которые вы ожидаете в буфере с помощью отладчика?

read() #include int read (int handle, void * buffer, int nbyte);

Функция read() пытается считывать nbytes из файла, связанного с дескриптором, и помещает символы в буфер. Если файл открывается с помощью O_TEXT, он удаляет возврат каретки и обнаруживает конец файла.

Функция возвращает количество прочитанных байтов. В конце файла возвращается 0, по ошибке он возвращает -1, устанавливая errno для указания типа произошедшей ошибки.

+0

Спасибо, но у меня всегда есть тот же результат. –

0

Благодарим за ответы. Это мой окончательный код:

#include<string.h> 
#include<stdlib.h> 
#include<stdio.h> 
#include<errno.h> 
#include<unistd.h> 
#include<fcntl.h> 
#include<termios.h> 

int main() {  

    int STATE_OK=0; 
    int STATE_WARNING=1; 
    int STATE_CRITICAL=2; 
    char tempbuf[10]; 
    struct termios tty; 

    int fd=open("/dev/ttyACM1",O_RDWR | O_NOCTTY); 
    if(fd == -1){ 
      printf("Unable to open /dev/ttyACM1\n"); 
      return STATE_WARNING; 
    }else { 
     if(tcgetattr(fd, &tty)!=0){ 
      perror("tcgetatt() error"); 
     }else{ 
       cfsetospeed(&tty, B9600); 
       cfsetispeed(&tty, B9600); 

       tty.c_cflag &= ~PARENB; 
       tty.c_cflag &= ~CSTOPB; 
       tty.c_cflag &= ~CSIZE; 
       tty.c_cflag |= CS8; 
       tty.c_cflag &= ~CRTSCTS; 
       tty.c_cflag |= CLOCAL | CREAD; 

       tty.c_iflag |= IGNPAR | IGNCR; 
       tty.c_iflag &= ~(IXON | IXOFF | IXANY); 
       tty.c_lflag |= ICANON; 
       tty.c_oflag &= ~OPOST; 
       tcsetattr(fd, TCSANOW, &tty); 

       int w=write(fd, "t", 1);/*printf("%d\n",w); 
       fprintf(stderr, "fd = %d.\n", fd);*/ 
       usleep(1000); 
       int n=read(fd,tempbuf,8);/*printf("%d \n",n);*/ 
       tempbuf[9]=0; 
       float temp=atof(tempbuf); 

       if (temp>27){ 
        printf("CRITICAL: %f celsius\n",temp); 
        return STATE_CRITICAL; 
       }else{ 
        printf("Everything is OK and the temperature is %f Celsius\n",temp); 
        return STATE_OK; 
       } 
     } 
    } 
    close(fd); 
    return 0; 
} 
+0

Правильная благодарность была бы «принять» ответ, объясняющий, как вы попали в этот окончательный код. – sawdust

Смежные вопросы