Vraag & Antwoord

Programmeren

c++: class voor seriële communicatie

Anoniem
JaFO
24 antwoorden
  • Mijn probleem is redelijk simpel: ik wil over mijn seriële poort uiterst simpele data verzenden (ANSI tekstregels of iets dergelijks). Dus ik ging zoeken voor een class om data via de seriële poort te verzenden, maar hier liep ik volledig vast: veel classes zijn volledig afhankelijk van Visual C++ (terwijl ik 'gewone' c++ gebruik). Kan iemand me hiermee helpen?
  • *verwijderd: niet het probleem*
  • Ik heb een class gevonden. Communicatie komt bij mij echter nog niet van de grond. Zowel robot als computer ontvangen of zenden niets, wat me met hyperterminal wel lukt. Overigens zit er wel iets van een connectie tussen; bij het resetten van mijn robot wordt automatisch de write (uit unistd.h) afgebroken met error code -1. Wat nu?
  • Ik weet niet wat je zoekt, maar de AT opdracht is voor een modem bedoeld. Welke C compiler gebruik je? Welke Windows versie (of ander OS) gebruik je?
  • Windows 7, met de cygwin gcc compiler (en netbeans ide). Overigens ben ik er achter dat mijn robot alleen bytes kan ontvangen, (8 bits dus), waarmee ik dus precies 1 char kan versturen. Dus ik typ dit:
    [code:1:4b2f08b4d8]fd_set rdfs;
    unsigned char dummy = 10;
    cout << write(fd, dummy, 1) << endl;[/code:1:4b2f08b4d8]
    maar nu krijg ik de compile error:[code:1:4b2f08b4d8]
    main.cpp:51: error: invalid conversion from `unsigned char' to `const void*'
    main.cpp:51: error: initializing argument 2 of `_ssize_t write(int, const void*, size_t)'[/code:1:4b2f08b4d8]
    waarbij write gedefinieerd is in unistd.h als
    [code:1:4b2f08b4d8]_READ_WRITE_RETURN_TYPE _EXFUN(write, (int __fd, const void *__buf, size_t __nbyte ));[/code:1:4b2f08b4d8]
  • Ik werk op de verkeerde computer. Ik vermoede dat je een aantal Windows functies moet gaan aanroepen, het ligt er een beetje aan in hoeverre gcc is aangepast aan Windows.
    Wat is de meer complete code van je programma? Ik neem aan dat je eerst de com poort opent, daarna de poort initialiseert en vervolgens data gaat versturen. Biedt gcc daar ondersteuning voor?
  • [code:1:616e2333d6]
    /////////////////////////////////////////////////
    // Serial port interface program //
    /////////////////////////////////////////////////

    #include <stdio.h> // standard input / output functions
    #include <string.h> // string function definitions
    #include <unistd.h> // UNIX standard function definitions
    #include <fcntl.h> // File control definitions
    #include <errno.h> // Error number definitions
    #include <termios.h> // POSIX terminal control definitionss
    #include <time.h> // time calls
    #include <iostream>
    using namespace std;

    int open_port(void) {
    int fd; // file description for the serial port

    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);

    if (fd == -1) // if open is unsucessful
    {
    perror("open_port: Unable to open /dev/ttyS0 - ");
    } else {
    fcntl(fd, F_SETFL, 0);
    }

    return (fd);
    }

    int configure_port(int fd) // configure the port
    {
    struct termios port_settings; // structure to store the port settings in

    cfsetispeed(&port_settings, B9600); // set baud rates
    cfsetospeed(&port_settings, B9600);

    port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
    port_settings.c_cflag &= ~CSTOPB;
    port_settings.c_cflag &= ~CSIZE;
    port_settings.c_cflag |= CS8;

    tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
    return (fd);

    }

    /*===================================
    * ==Vanaf hier is eigen code: ======
    * ==================================
    */

    int send_message(int fd) {
    write(fd, "Hoi", 3);
    return 0;
    }

    int main(void) {
    int fd = open_port();
    cout << "Port open" << endl;
    configure_port(fd);
    cout << "Port configured" << endl;
    send_message(fd); //Vanaf hier doet het programma niets, totdat robot wordt gereset.
    return (0);
    }[/code:1:616e2333d6]
    waar "Hoi" staat mag ik geen variabele neerzetten, dan krijg ik die conversion error. Ook mag ik niets anders dan een string neerzetten. (alleen write(fd,"xxxxx",n) werkt dus, niet write(fd,'x',n), write(fd,10,n), write(fd,variabele,n).
    Ik zou juist wel graag een char kunnen verzenden, omdat mijn robot nu eenmaal slechts 1 byte per keer kan ontvangen.
  • Op zich zou het niet uit hoeven maken. Wat verstandiger is om ook echt maar 1 byte te versturen en een korte pauze in te lassen. Of heb je dat al geprobeerd? Ik zou een lus maken en dan testen of alle bytes zijn verstuurd, cq een fout is opgetreden. Die test lijkt nu ook nog te ontbreken. Een string mag 1 karakter bevatten … Verder is C/C++ gemaakt om een string efficient te gebruiken. De purist zou zelfs kijken of de nul waarde is gelezen. Mogelijk is dat soort code voor je te riskant, want misschien is de 0 waarde voor de robot zinvolle data. In dat geval werkt de strlen() niet zoals jij zou willen. En heel misschien is het verstandiger om gewoon duidelijk te programmeren … en dus gebruik te maken van 2 strings en de lengte apart bij te houden.
    [code:1:2f6bb720a7]
    char *test = "Hoi";
    for(i = 0; i < strlen(test); i++)
    {
    write(fd, test++, 1);
    }
    [/code:1:2f6bb720a7]
  • Ik ga even weer cygwin op mijn windows xp installeren, zodat ik daar een serial port listener (die niet werkt op windows 7) kan installeren, en kan kijken hoe hyperterminal (die wel werkt) communiceert met mijn robot, zodat ik daar mijn programma op kan aanpassen. Het probleem ligt volgens mij namelijk nu bij de robot, die gewoon niet snapt wat ie naar z'n hoofd gegooid krijgt, en dus niets doet.
  • zelfs in een oneindige lus blijf ik niets ontvangen, bijvoorbeeld als ik typ while(read(..) != 0) { … }, wordt dit een oneindige lus, hoewel mijn robot in een oneindige lus data verzendt. Wat nu?
  • Mogelijk dat de baudrate te hoog is. Oh ja, mijn stringvoorbeeld is geen correct c/c++. In theorie kan je 1 karakter ook versturen door:
    [code:1:a6c83ae17d]
    cout << write(fd, &dummy, 1) << endl; // staat hier echt endl?
    [/code:1:a6c83ae17d]
    Een alternatief is om een character array te maken:
    [code:1:a6c83ae17d]
    char dummy[1];
    char dummyvb[4];
    [/code:1:a6c83ae17d]
  • Let inderdaad heel goed op de instellingen van de com-poort.
    Ik heb weliswaar onder Delphi een dergelijk stuk code gemaakt, maar het belangrijkste probleem blijft hetzelfde.

    De belangrijkste zijn :
    = baudrate (9600 - …)
    = parity (even/oneven)
    = stopbits (0, 1 of anderhalf)
    = databits (6,7 of 8)

    xon/xoff speelt mogelijk ook een rol afhankelijk van de hardware die je aanstuurt, maar aangezien hyperterminal al lukt.

    Waar je ook op moet letten is dat je mogelijk een carriage return of line-feed moet meesturen.

    Wat mij op het eerste gezicht vreemd lijkt is dat je de poort kunt openen zonder de instellingen te moeten instellen.

    Als je de foute instellingen hebt dan kan het een tijdje duren voordat je een time-out krijgt, vooral als ergens intern op een soort van ontvangst-bevestiging wordt gewacht.
    Misschien is dat 'wachten op antwoord' wellicht het probleem waardoor je maar een ding kunt sturen.
    Dus niet alleen een 'commando' sturen, maar ook antwoord ontvangen.

    Ander mogelijk probleem : foute commando.
    Je kunt mogelijk niet elke willekeurige tekst sturen naar je robot.
    Dat zou je eenvoudig moeten kunnen testen door dezelfde tekst via hyperterminal te sturen naar je robot.

    En nog een gemene adder : let er op dat de serieele poort niet in gebruik is !
    Dit is technologie uit de prehistorie en niet alles is berekend op het delen van deze resource (ie : als hyperterminal actief is dan kan niemand anders de poort openen of gebruiken).
  • bedankt voor dit antwoord :D
    inderdaad zie ik nergens instellingen, maar ik heb nu een documentation waar dat allemaal staat, dus dat wordt leuk proberen.
    Hier de werkende instellingen via Hyperterminal:
    BAUD 9600
    8 databits
    parity: none
    stop bits: 1
    flow control: none
    Als ik een ANSI teken verzend via hyperterminal (dus gewoon typ, geen cr of iets), geeft de robot een geluidje.
    Ik ga morgen proberen met deze instellingen hem aan het werk te krijgen.
    De seriele poort is niet in gebruik: dan is de COM-poort niet eens te openen.
  • Schrijven werkt nu als een zonnetje, lezen niet. Niente. Nada. Noppes. (programma hangt op lezen).
  • als je wilt 'lezen' dan moet je op een signaal van de com-poort wachten dat aangeeft dat er uberhaupt iets is. Ik meen dat dat ergens in de windows-api zit.

    Weet je zeker dat er bij de robot zelf geen sdk of iets dergelijks zat om op laag niveau met het ding te praten ?

    Welke robot gebruik je ?
    Is het een soort speelgoed-robot of toch iets serieuzers ?
  • Het is een robot robby rp5. (conrad). Het is iets serieuzer dan een speelgoedrobot; de programmeertaal is niet echt kindvriendelijk, en hij ziet er ook niet leuk kleurrijk uit.
    Ik snap niet helemaal wat je met die sdk-dinges bedoelt, maar het zit err niet bij :wink: Ik gebruik daarvor hyperterminal, die gewoon ansikarakters kan versturen, die de robot ontvangt en opslaat als een 8bit byte. Hij verstuurt op de zelfde manier.
    Ik vraag me af of de pc wacht voor een aankondiging van data, want die is er niet: het is een 3pin aansluiting op de seriele poort, dus geen hardware flow control, en xon/xoff gebruik ik ook niet.
    Saillant detail: als ik O_NONBLOCK instel bij open(), blockt het programma nog steeds.
    edit: om een vage reden had de programmeur fcntl(fd, F_SETFL,0); in het programma gezet, waardoor de O_NONBLOCK gewist werd bij open().
  • De communicatie functies zitten in de Windows API. Heb je ditSerial Communications in Win32 al bekeken? Je compiler zou toch wel het een en ander moeten kunnen ondersteunen anders zou je niet eens Windows toepassingen kunnen schrijven.
  • Bedankt voor de link! Hoe komt het dan dat schrijven op de poort wel kan maar lezen niet met de unistd.h header?
  • sdk : software development kit
    oftewel info over het aansturen van de 'robot'.
    Ik zie op de website van conrad dat er een programma is te downloaden waarmee je de robot kunt programmeren.
    Is die applicatie niet goed genoeg, of wil je het gewoon zelf kunnen doen (want het kan zeker weer beter ;))

    Even googlen levert niet echt veel nuttige info :
    http://home.hccnet.nl/r.akkerman/ROBBY/CCRPer12.txt

    Je zult dus inderdaad even moeten kijken wat & hoe programma's worden overgestuurd vanuit de editor als je zelf zoiets wilt schrijven.
  • je begrijpt me verkeerd hier denk ik! Ik kan gewoon programma's laden naar en van de robot. Dit gaat allemaal via de sdk en de 'kernel' van de robot. Nu heb ik een programma gemaakt en geladen op de robot, die seriele info kan ontvangen en verzenden. Met het programma Hyperterminal gaat dat allemaal goed. Nu wil ik een soort van programmeerbare hyperterminal maken, zodat ik de veel handigere programmeertaal c++ kan gebruiken, in plaats van de nogal klote programmertaal bijgeleverd bij de robot [en ik voel weinig om een complete compiler voor de robot te bouwen]. Hiervoor moet ik dus data kunnen ontvangen in c++, maar om een vage reden lukt dat niet (dat ligt dus niet aan de robot, want hyperterminal ontvangt wel netjes), maar aan de software. Ik ga nog flink wat instellingen proberen, maar misschien zien jullie zo wat ik fout doe. Die win32api werkte trouwens van geen meter.

Beantwoord deze vraag

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.