Добрый день! Написал программу, которая запускается автоматически Смысл программы в бесконечном цикле постоянно слушать по usb (serial) приходящие пакеты от подключенной arduino когда приходит правильная команда, запускается определенно видео проблема в следующем, если отключить малину от питания, то слетает графический режим, и не возможно запустить в дальнейшем startx, т.е. приходится заново переустанавливать систему на малине подозреваю, что работа в linux с com портами происходит как и с файлами, вот код программы: Код (C++): #include <stdlib.h> #include <pty.h> #include <unistd.h> #include <stdio.h> #include <errno.h> #include <termios.h> #include <string.h> #define STATIONS_MAX_NUM 5 // Количество станций в нашем плейлисте // Это наш маленький типа плэйлист // Между кавычек вставляем URL потока вещания станци char *station1[]={"./Videos/Movie_01.mov", NULL}; char *station2[]={"./Videos/Movie_02.mov", NULL}; char *station3[]={"./Videos/Movie_03.mov", NULL}; char *station4[]={"./Videos/Movie_04.mov", NULL}; char *station5[]={"./Videos/Movie_05.mov", NULL}; char* getDeviceFileName(int argc, char **argv) { if (argc < 2) { fprintf(stderr, "Argument missing: Arduino device file.\n"); exit(EXIT_FAILURE); } return argv[1]; } int openDeviceFile(const char* fileName, const char* mode) { FILE* file; file = fopen(fileName, mode); if (file == NULL) { perror(fileName); exit(EXIT_FAILURE); } return fileno(file); } unsigned int getBaudRate(int argc, char **argv) { return (argc > 2) ? atoi(argv[2]) : 57600; } void setAttr(int fd, unsigned int baud) { struct termios toptions; speed_t brate; if (tcgetattr(fd, &toptions) < 0) { perror("Can't get term attributes"); exit(EXIT_FAILURE); } switch(baud) { case 4800: brate=B4800; break; case 9600: brate=B9600; break; #ifdef B14400 case 14400: brate=B14400; break; #endif case 19200: brate=B19200; break; #ifdef B28800 case 28800: brate=B28800; break; #endif case 38400: brate=B38400; break; case 57600: brate=B57600; break; case 115200: brate=B115200; break; case 230400: brate=B230400; break; default: fprintf(stderr, "Invalid baud rate value: %d\n", baud); exit(EXIT_FAILURE); } cfsetispeed(&toptions, brate); cfsetospeed(&toptions, brate); // 8N1 toptions.c_cflag &= ~PARENB; toptions.c_cflag &= ~CSTOPB; toptions.c_cflag &= ~CSIZE; toptions.c_cflag |= CS8; // no flow control toptions.c_cflag &= ~CRTSCTS; toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw toptions.c_oflag &= ~OPOST; // make raw // see: http://unixwiz.net/techtips/termios-vmin-vtime.html toptions.c_cc[VMIN] = 0; toptions.c_cc[VTIME] = 20; if (tcsetattr(fd, TCSANOW, &toptions) < 0) { perror("Can't set term attributes"); exit(EXIT_FAILURE); } } void sendCommand(int fd, const char *cmd) { write(fd, cmd, strlen(cmd)); } void displayResult(int fd) { char buf[256]; ssize_t sz; do { sz = read(fd, buf, 255); buf[sz] = 0; printf("%s", buf); } while (sz); } void do_child (char **omx_arg) { if (execlp("omxplayer", "omxplayer", *omx_arg) < 0) { perror("exec omxplayer"); exit(1); } } int do_parent (int fd, pid_t p, int n, int fdserial) { char buf[256]; ssize_t sz; int num; do { sz = read(fdserial, buf, 255); //buf[sz] = 0; //printf("%s", buf); if (strncmp("play_movie_0", buf, 12) == 0){if(n!=1){n=1;break;}} if (strncmp("play_movie_1", buf, 12) == 0){if(n!=2){n=2;break;}} if (strncmp("play_movie_2", buf, 12) == 0){if(n!=3){n=3;break;}} if (strncmp("play_movie_3", buf, 12) == 0){if(n!=4){n=4;break;}} if (strncmp("play_movie_4", buf, 12) == 0){if(n!=5){n=5;break;}} printf("%s - %d", buf, strlen(buf)); } while (1); bcm2835_delay(500); // Эта задержка в 500мс нужна для фиксации нажатия кнопки char r; write(fd, "q", 1); // Здесь мы посылаем omxplayer-у эквивалент нажатия на клавишу "q" клавиатуры // что заставляет плеер завершить работу while (read(fd, &r, 1) > 0) { write(1, &r, 1); } // Всё, что ниже, нужно для корректного завершения процесса waitpid(p, 0, 0); close(fd); // Всё, плеер выключен, процесс завершён. Можно начинать всё заново с новой станцией //++n; // Увеличиваем порядковый номер проигрываемой станции на 1 if (n>STATIONS_MAX_NUM) n=1; // Проверяем, если мы проиграли все станции в плей-листе, то устанавливаем номер снова на 1 return(n); // Выходим из функции и возвращаем номер очередной станции } // Функция проигрывания очередной станции // Входной параметр n- порядковый номер проигрываемой станции. // Если добавили в плей-лист ещё станций, то и здесь нужно увеличить // количество строк case void play_station(int n) { switch (n) { case 1: do_child(station1); case 2: do_child(station2); case 3: do_child(station3); case 4: do_child(station4); case 5: do_child(station5); default: ; } } // Основная программа int main() { int fd; // файловый дескриптор int n=4; // порядковый номер станции const char fileName[] = "/dev/serial/by-id/usb-Arduino_Srl_Arduino_Uno_75435353038351217041-if00"; const char fileMode[] = "r+"; unsigned int baud = 115200; int fdserial; //fileName = getDeviceFileName(argc, argv); fdserial = openDeviceFile(fileName, fileMode); //baud = getBaudRate(argc, argv); setAttr(fdserial, baud); //displayResult(fdserial); while(n) // Бесконечный цикл. Выход не предусмотрен. { pid_t p = forkpty(&fd, 0, 0, 0); // Запускаем параллельный процесс в псевдотерминале switch (p) { case 0: play_station(n); // Если всё получилось, запускаем плеер в созданном процессе case -1: perror("forkpty"); // Иначе аварийное завершение. exit(EXIT_FAILURE); default: break; } n=do_parent(fd, p, n, fdserial); // А в основном процессе начинаем следить за кнопкой. } close(fdserial); }
А какая разница, как работает с сериалом linux? Вообще-то там других сущностей для работы, кроме файлов, и нету. Сделайте автозапуск графической оболочки при помощи raspi-config, а программку вашу запустите в теринале уже внутри оболочки. Ну или извне, но тогда плееру придется указывать дисплей на котором надо запустится. Да и вообще это все проще написать на питоне, получится десяток строк вместо огромной портянки, и компилировать не надо...
нет, система ложилась наглухо, никаких вариантов ее поднять не было, причем и половина файлов даже пользовательских пропадало или переименовывалось, вообще файловая система была в шоке но проблема не в выключении питания оказывается, а в том, что при обращении к usb (serial), если вдруг отсоединить этот usb чтобы переписать скетч в arduino, то такого linux не любит, в отличии от windows, так что проблема решилась тем, что usb не отсоединяем пока не вырубим малину, уже две недели полет нормальный
Наверное все-таки ошибки в вашей программе. У меня сейчас в работе проект, который использует одновременно 4 usb-serial. При отвале любого ни разу не было ни зависания малинки ни тем более краша файловой системы. Правда весь софт - на питоне, только пара мелких кусочков на C, но они не имеют отношения к usb-serial.
может и в программе проблема, собственно для этого и выложен ее код чуть Выше. питон не знаю, а вот С++ с университета использую, мне он и легче и удобнее, если можете показать как то же самое сделать на питоне, буду рад
Код (Python): #!/usr/bin/python ############################################################################### import sys import serial import os link = serial.Serial(port="/dev/ttyUSB0", baudrate=9600) while True: s = link.readline() s1 = s.strip() if s1=="play_movie1": os.system(u"echo %s >> out.txt" % (s1)) link.write(u"command %s accomplished\n" % (s1)) elif s1=="play_movie2": os.system(u"echo %s >> out.txt" % (s1)) link.write(u"command %s accomplished\n" % (s1)) elif s1=="quit": break else: link.write(u"error command %s \n" % (s1)) link.write(u"use commands: play_movie1|play_movie2|quit \n") link.close() Вместо строчек "echo %s >> out.txt" вставляете свои команды запуска плеера. по пустой команде выдает подсказку, по quit выходит. Код гарантировано рабочий, проверил.
спасибо, а программа будет работать в режиме консоли? мне так не подходит. нужно чтобы запускался отдельный процесс. данной решение используется в квест-руме, через 15 минут после запуска малины она уходит в спящий режим и экран черный, а запуск моей программы не выводит из спящего режима, таким образом не портит задачу, когда видео не воспроизводится - экран темный
Спящий режим надо отключить конечно. Смотрите настройки Xserver. Моя программа будет работать как угодно, если ее правильно запустить. Чтобы работало в фоне надо чтобы программа ничего не выводила в консоль и запускалась в фоне. Это можно сделать строкой запуска типа python программа.py > /dev/null 2>&1 & > /dev/null - переназначение вывода в нулевое устройство 2>&1 - переназначение ошибок туда же & - запуск в фоне