Kommunikation über die serielle Schnittstelle mit Arduino und C++
Ich habe ein problem mit Kommunikation über Serielle Schnittstelle zwischen Arduino Nano und C++, obwohl das problem in C++ - Seite. Grundsätzlich will ich senden Integer (oder long,...) aus dem Arduino an einem C++ - Programm verarbeitet werden.
Zuerst habe ich einen test senden von Informationen vom Arduino an den computer mit Hilfe von Matlab. Der Arduino-code ist ziemlich einfach:
int i = 0;
void setup() {
//start serial port at 9600 bps:
Serial.begin(9600);
establishContact();
}
void loop() {
Serial.println(i);
i=i+1;
delay(10);
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.println('A', BYTE);
delay(10);
}
}
Der Matlab-Seite ist auch einfach:
clc;
clear all;
numSec=2;
t=[];
v=[];
s1 = serial('COM3'); % define serial port
s1.BaudRate=9600; % define baud rate
set(s1, 'terminator', 'LF'); % define the terminator for println
fopen(s1);
try % use try catch to ensure fclose
% signal the arduino to start collection
w=fscanf(s1,'%s'); % must define the input % d or %s, etc.
if (w=='A')
display(['Collecting data']);
fprintf(s1,'%s\n','A'); % establishContact just wants
% something in the buffer
end
i=0;
t0=tic;
while (toc(t0)<=numSec)
i=i+1;
t(i)=toc(t0);
t(i)=t(i)-t(1);
v(i)=fscanf(s1,'%d');
end
fclose(s1);
plot(t,v,'*r')
catch me
fclose(s1);
end
Mein Ziel ist, mit C++, das gleiche zu tun, geschieht in Matlab mittels fscanf(s1, '%d').
Hier ist der aktuelle code, den ich verwende (C++ code):
void main()
{
HANDLE hSerial;
hSerial = CreateFile(TEXT("COM3"),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,//FILE_FLAG_OVERLAPPED,
NULL);
if ( hSerial == INVALID_HANDLE_VALUE)
{
printf("Error initializing handler");
}
else
{
//Set the parameters of the handler to the serial port.
DCB dcb = {0};
dcb.DCBlength = sizeof(dcb);
if ( !GetCommState(hSerial, &dcb) )
{
printf("Error setting parameters");
}
FillMemory(&dcb, sizeof(dcb), 0);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
if ( !SetCommState(hSerial, &dcb) )
{
//error setting serial port state.
}
//Tell the program not to wait for data to show up
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 0;//20;
timeouts.ReadTotalTimeoutConstant = 0;//20;
timeouts.ReadTotalTimeoutMultiplier = 0;//50;
timeouts.WriteTotalTimeoutConstant = 0;//100;
timeouts.WriteTotalTimeoutMultiplier = 0;//100;
if ( !SetCommTimeouts(hSerial, &timeouts) )
{
printf("Error setting the timeouts");
}
char szBuff[5] = "";
DWORD dwBytesRead = 0;
int i = 0;
char test[] = "B\n";
int maxSamples = 10;
DWORD dwCommStatus;
WriteFile(hSerial, test, 2, &dwBytesRead, NULL);
SetCommMask(hSerial,EV_RXCHAR);
while (i < maxSamples)
{
WaitCommEvent (hSerial, &dwCommStatus, 0);
if (dwCommStatus & EV_RXCHAR)
{
memset(szBuff,0,sizeof(szBuff));
ReadFile(hSerial, LPVOID(szBuff), 4, &dwBytesRead, NULL);
cout<<szBuff;
printf(" - %d - \n", atoi(szBuff));
}
i++;
}
scanf("%d", &i);
CloseHandle(hSerial);
}
}
Dem Ziel, mein code wäre so etwas wie num = ReadSerialCOM(hSerial, "%d");
Meiner aktuellen C++ - code liest die Daten aus dem Puffer, aber es ist nicht eine akzeptierte das Ende der Zeile, was bedeutet, dass meine zahlen (Integer) empfangen werden geschnitten.
ZB:
Sende ich 8889 vom Arduino, an welchen Orten es in den COM-port. Und der Befehl ReadFile
spart '88' in szBuff
. Bei der nächsten iteration '89\n' werden in sZBuff
. Grundsätzlich möchte ich vermeiden, um post-Prozess sZBuff
zu concat '88' und '89\n'.
Jemand?
Danke!
Ich habe kein problem, über die Formatierung von mehr text, aber ich bin nicht sicher, was Sie meinen. Code, "Erklärung" oder beides? PS: beachten Sie die Anführungszeichen in der Erklärung. Ich bin nicht sicher, dass ich einen guten job gemacht, die das problem erläutert.
Sie können nicht verhindern, dass es so lange verwenden Sie das raw-API. Class-Bibliotheken für die serielle Schnittstelle wrapper implementiert, dass ReadLine() sind sicherlich vorhanden.
InformationsquelleAutor sergi | 2010-08-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn ich verstehe deine Frage richtig, ein Weg, um zu vermeiden, dass 'post-Prozess' ist, bewegen Sie den Mauszeiger übergeben
ReadFile
dem Ende der verfügbaren Daten, so dass derReadFile
Aufruf Anhängen an den Puffer überschrieben.Im wesentlichen, Sie würden zwei Zeiger. Einer der Puffer, die andere an das Ende der Daten im Puffer. Also, wenn Ihr das Programm startet, werden beide Zeiger werden die gleichen sein. Nun, Sie Lesen die ersten 2 bytes. Erhöhen Sie die Ende-der-Daten-Zeiger um 2. Sie wollen andere Lesen, aber statt
szBuff
, übergeben Sie einen Zeiger an das Ende des zuvor gelesenen Daten. Lesen Sie die nächsten drei bytes und Sie haben den kompletten Eintrag inszBuff
.Wenn Sie müssen warten, bis einige Trennzeichen zu markieren das Ende der einen Eintrag erhalten, Sie konnte, suchen Sie einfach die empfangenen Daten für Sie. Wenn er nicht da ist, Sie halten Sie zu Lesen, bis du es findest. Wenn es da ist, können Sie einfach zurück.
Ob diese Vorgehensweise akzeptabel ist, es erfordern ein wenig mehr Arbeit. Zum Beispiel, würden Sie haben, um sicherzustellen, dass Sie nicht überlauf-Puffer. Wenn Sie entfernen die Daten aus dem buffer, müssen Sie verschieben Sie alle Daten, die nach dem entfernten segment zu Beginn, und befestigen Sie das Ende des Daten-Zeiger. Alternativ können Sie einen Ringspeicher.
char
's, bis ich Lesen Ende der Zeile. Legen Sie dann alle char ' s zusammen wieder den erstenint
. Ich war mir sicher, wenn es sieht, dass ich mich Irre, dass es eine Lösung ähnlich der Matlab -fscanf(h, '%d")
bereits getan für dieses problem, obwohl ich nicht gefunden haben, etwas ähnliches. In der Matlab-code geschieht dies über eine terminator-Charakter und ich war im Grunde Fragen, ob ich etwas verpasst Eigenschaft der Funktionen verwendet.Oh, wie ich sehe. Dies ist im Grunde die Art und Weise so etwas wie fscanf umgesetzt würde, aber Windows bietet keine Funktion, die das tun kann, soweit ich weiß.
InformationsquelleAutor Collin Dauphinee
Als Hans Passant und dauphic zeigte, scheint es nicht zu sein, eine Allgemeine Lösung für meine Frage. Ich Schreibe, wenn, der code, den ich versuchte, zu vermeiden, nur für den Fall, jemand findet es nützlich oder Gesicht das gleiche problem, dass ich hatte:
InformationsquelleAutor sergi