Hi liebes Forum, ich versuche nun schon seit mehreren Tagen ein Programm zu schreiben, das einen Zeichenstring über den UART an einen Microcontroller sendet. Das Programm auf dem Microcontroller funktioniert, wenn ich es mit Minicom vom Computer ansteuere. Nutze ich mein Programm und lasse Minicom im Hintergrund laufen, funktioniert auch das Programm. Ist Minicom aus und ich lasse mein Programm starten, funktioniert die Übertragung nicht. Ich habe den Bus mit dem Salae Logic Analyzer beobachtet, anbei das entsprechende Bild. Ist Minicom nicht an, so entsteht das letzte Bitflag (ganz rechts). Ist Minicom im Hintergrund an, so ist dieses nicht vorhanden. Ich finde inzwischen keine Erklärung mehr, woran das liegt. Wer kann mir weiterhelfen?
Edit: Sorry, erst jetzt deinen Code gesehen. Dumme Frage: Baudrate usw. hast du im Programm eingestellt? Sonst kann man es in der Shell auch mit stty machen.
gibt keine dummen fragen.
ja, baudrate stelle ich mit diesen zeilen ein:
if( cfsetispeed(&port_settings, B38400) != 0) // set baud rates
{ cout << "couldn't set baudrate for input" << endl; }
if( cfsetospeed(&port_settings, B38400) != 0)
{ cout << "couldn't set baudrate for output" << endl; }
int n = read(fd,data,(int) strlen(data)); Sollte es nicht sizeof(data) sein?
Gast
#4379639
Hm. Irgendwie hört sich das nach einem Treiberproblem an. Die These wäre, dass der Treiber korrekt geladen ist, oder auch nur korrekt initialisiert wird, wenn Minicom gestartet ist. Allerdings sollte das theoretisch Konflikte geben, da ja dann zwei Programme auf die selbe Schnittstelle zugreifen. Das mit dem "Bitflag" von Deinem Bild verstehe ich nicht. Scheint mir irrelevant zu sein. Poste doch mal den Code von dem PC-Programmteil.
Gast
#4379640
Oops. Da isser ja, der Code. Sorry.
Hier ist ein alter Code von mir in C, bitte vergleiche es mal, ich bin so müde.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
@fritz: read() wird mit der anzahl an bytes, die gelesen werden können, aufgerufen. Diesen Wert ermittel ich durch strlen() anzahl an chars, die der string (char array) enthalten kann ;). read gibt keinen Fehler zurück, sondern sogar den richtigen String. SOFERN minicom im Hintergrund geöffnet wird. @Klaus: warum denkst du nicht, dass dieser Bitfehler der Ursprung ist? Wenn ich minicom im hintergrund offen habe, ist er weg. Mein Programm vom Controller sollte dieses Bit aufnehmen und abspeichern. Ist dies der Fall, wird der komplette String um 1 Char verschoben, die zugewiesene "Adresse" stimmt nicht mehr überein und der komplette String wird nicht interpretiert...
strlen gibt die Länge des momentanen Inhaltes an. Wenn da "Fritz" drinsteht, dann wirst du nur 5 Bytes lesen können, nicht mehr. Ich bin ziemlich sicher du meinst die Größe des Buffers (sizeof wäre in dem Fall auch falsch).
@Fritz: kontrolliert, alles bei mir entsprechend deinen Bits geändert. Das Ding will nicht so wie ich... oder du
Gast
#4379656
Fabian S. schrieb: > read() wird mit der anzahl an bytes, die gelesen werden können, > aufgerufen. Diesen Wert ermittel ich durch strlen() anzahl an chars, die > der string (char array) enthalten kann ;). und was ist wenn in Daten vorher eine andere länge drin steht? strlen liefert nicht die Anzahl von Array zurück sondern die Anzahl der Zeichen mit zum ersten \0.
Peter II schrieb: > Diesen Wert ermittel ich durch strlen() Wenn der String nicht vorher gefüllt (initialisiert mit erwarteter Länge ) wurde, gibt strlen() evtl. 0 oder, je nach Inhalt von data irgendwas zurück. Lies mal die Beschreibung zu strlen(). Du brauchst statt dessen ..... Was anderes. ;-)
es wird: memset(&data[0],0,16); vor aufruf der read funktion aufgerufen. Es existiert somit kein '\0'. Somit wird die komplette länge des strings genommen. sizeof() gibt bei "1:0,0,0!\n" 8 zurück. strlen() 9. Ich bevorzuge die 9 bytes zu schicken.
selbst wenn ich die read Funktion nicht aufrufe, funktioniert es nicht. Ich möchte lediglich einen String schicken, daraufhin soll der microcontroller die farbe der angeschlossenen rgb-led ändern. schicke ich den string in minicom, so funktionierts. schicke ich ihn mit meinem Programm, funktionierts nicht. schicke ich ihn mit programm und minicom im hintergrund, funktionierts. Alles ohne aufruf von read().
Gast
#4379674
Fabian S. schrieb: > memset(&data[0],0,16); > vor aufruf der read funktion aufgerufen. > Es existiert somit kein '\0'. > Somit wird die komplette länge des strings genommen. es sind nur \0 drin oder was glaubst du was den 0 von memset macht?
ich habe nun den code hierzu abgewandelt:
memset(&data[0],0,16);
data[15] = '\0';
serialport.receive(&data[0]);
somit wird erst alles genullt -> gar kein \0
und danach wird der letzte auf \0 gesetzt....
es hat leider nichts an meiner write-funktion geändert. Der mc reagiert
trotzdem nicht so wie er soll ;-)
Gast
#4379684
Fabian S. schrieb: > somit wird erst alles genullt -> gar kein \0 \0 ist null.
Schicke probeweise ein CR/LF hinten nach. Vielleicht puffert die Schnittstelle zeilenweise. Wenn es dann geht, ist die Schnittstelle nicht im RAW Modus.
Es ist leider keine Änderung zu sehen.
p.s.: ich schicke bereits dauerhaft ein LF mit.
Ich habe alle Varianten durchgeschickt.
Damit ihr nicht mehr raten müsst, wie meine Main aussieht:
int main(int argc, char *argv[])
{
terminal serialport;
char data[16] = "1:0,0,0!\n";
serialport.send(&data[0]);
usleep(10000);
memset(&data[0],0,16);
data[15] = '\0';
serialport.receive(&data[0]);
serialport.~terminal();
return 0;
}
Gast
#4379715
Fabian S. schrieb: > Damit ihr nicht mehr raten müsst, wie meine Main aussieht: irgendwie versucht du alles anders zu machen als üblich. serialport.send(&data[0]); -> serialport.send(data); memset(&data[0],0,16); -> memset(data,0,sizeof(data) ); data[15] = '\0'; -> kompletter Unsinn da stehen schon 0 drin serialport.receive(&data[0]); -> serialport.receive(data); serialport.~terminal(); -> macht man auch nicht. Das macht der Compiler wenn der Gültigkeitsbereich verlassen wird.
@peter. das meiste davon waren Schritte der Verzweiflung und Unwissenheit. Leider ändert das nur nix am Sachverhalt der Funktionalität...
Kurzer einschub für alle: Dieser Thread ist eine weiterführung/neustart von diesem Thread hier: Beitrag "arduino nano seriell (rs232) <-> usb linux (ubuntu14.04) Port Config" So, zurück zum Problem: Es handelt sich um ein Arduino-Board (Das ist wichtig!). Arduino-Boards melden sich unter Linux als Modem (ttyACM! Fabian hat das ganze per udev in ttyPWM umbenannt... warum auch immer), unter BSD 8 ebenfalls Modem (cuaU). Kurzer erkenntnis Gewinn: Es wird der Modemtreiber benutzt (auch diese feststelung ist wichtig zum verstehen!). Unter BSD 8 (ja ja, es geht hier um Umbunut, ich weiß, ich erklär ja nur...) wird der Controller auf dem Arduino-Board resetet (Softreset), sobald der Serielleport geschlossen wird. Sowas muss man abschalten, unter BSD heißt das Flag irgendwas mit "Hang Up...", um die Verbindung zu beenden. Und genau dieses Modem-Hang-Up sorgt unter BSD für einen Reset. Man kann die Arduino-Boards mittels RTS/DTS resetten... ach momentmal, die leitungen gibt es ja gar nicht bei einem USB-Kabel. Das Signal wird also per Software generiert und vom Arduino-USB-Seriellwandler (meistens ein kleiner Atmega) in ein Reset-Signal umgewandelt. Auch unter Linux bin ich da schon in (wenn auch andere) Probleme gelaufen. Ich kann der Stelle nur den Tipp geben: Probier das ganze mal mit einem echten USB-Seriell-Wandler, z.B. diesen hier: http://shop.in-circuit.de/product_info.php?cPath=38&products_id=80 Also: Arduino -> USB-Seriell-Wandler -> PC Was ist jetzt der Unterschied? Ganz einfach, der gepostete Wandler meldet sich als ttyUSB, benutzt also einen anderen Treiber, womit ich bisher keins der Probleme hatte, die ich mit dem ACM-Treiber hatte. Das ist soweit meine Erfahrung mit dem Arduino-Sch*** >:-[ Fabian S. schrieb: > int main(int argc, char *argv[]) > { > terminal serialport; > char data[16] = "1:0,0,0!\n"; > serialport.send(&data[0]); > usleep(10000); > memset(&data[0],0,16); > data[15] = '\0'; > serialport.receive(&data[0]); > serialport.~terminal(); > return 0; > } Über den Destruktor schließt du den Seriellenport... Ich Wette 5 Euro (für die Forums-Kasse!), das der eine Clock genau dieser Modem-Hang-Up mist ist. Der unterschied mit Minicom wird der sein, das Minicom genau das abschalten wird. "Tunnel" das ganze mal über die (oben gepostete) USB-UART-Bridge. Grüße
Gast
#4379727
Fürs Protokoll: 0 ist '\0' 0 (also als zahl) wird im String als die Escape-Sequenz '\0' dargestellt, der Wert ist aber genauso 0. Abweichend davon ist '0' zu sehen, das ist nämlich die ASCII-Repräsentation von der Zahl 0 (also als "Buchstabe") '0' != 0 '0' != '\0' 0 == '\0' Mit diesem Wissen sollte die auffallen, dass strlen etwas anderes zurückgibt, als du dir vorstellst
ja es ist Ubuntu und es ist ein Arduino... mit einem schönen AVR-DRAGON programmiert. Die Hardware mag ein Atmega mit Quarz und und USB <-> RS232 Wandler sein, hat aber nicht mehr viel mit Arduino IDE sein. Wie gesagt mit Eclipse und AVR DRAGON sein. Die 5Euro kannst du einzahlen... ich habe bereits ein sleep(10) vor dem Destruktor eingebaut. D.h. das Board hätte 10 sek. lang die Farbe ändern müssen.... es ist leider nicht geschehen. Womit du recht hast: Minicom unterdrückt/ verhindert dies tatsächlich...
@ N.G.
thanks für den Hinweis. Diesem war ich mir tatsächlich nicht bewusst.
int main(int argc, char *argv[])
{
terminal serialport;
char data[16] = "1:0,0,0!\n";
serialport.send(data);
sleep(10);
return 0;
}
Mit den ganzen Hinweisen mal meine neue main.
Kein receive mehr, um weitere Fehler auszugrenzen -> weniger Code.
sleep(10) um den Destruktor rauszuzögern....
so nach langer weiterer zeit, bin ich auf den Trichter gekommen. Schuld scheint mir tatsächlich dieses 1 Bit zu sein. Getriggert vermute ich jedoch wird es vom microcontroller. Rufe ich die send funktion 2 mal hintereinander auf und schreibe ich die chars einzeln mit 400 us pause dazwischen, stellt der controller um. Somit stellt sich nur noch die Frage. Wo ist der Fehler im mc-programm?
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.
