forked from JanekOstendorf/THOMAS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathArduinoCom.cpp
More file actions
184 lines (141 loc) · 3.98 KB
/
ArduinoCom.cpp
File metadata and controls
184 lines (141 loc) · 3.98 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
-- ArduinoCom-KLASSE :: IMPLEMENTIERUNG --
*/
/* INCLUDES */
// Klassenheader
#include "ArduinoCom.h"
using namespace THOMAS;
// THOMASException-Klasse
#include "THOMASException.h"
// C++-IO-Stream-Klasse
#include <iostream>
// Terminal-IO-Definitionen [Non-Standard]
// In diesem Header wird u.a. die termios-Struktur definiert.
#include <termios.h>
// POSIX-Definitionen [Non-Standard]
// Dieser Header enthält u.a. Definitionen für viele POSIX-Systemaufrufe.
#include <unistd.h>
// File-Control-Definitionen [Non-Standard]
// Dieser Header erhält u.a. die Definition des open()-Systemaufrufs.
#include <fcntl.h>
/* FUNKTIONEN */
// Konstruktor
ArduinoCom::ArduinoCom()
{
// Anschlusshandle erstellen, USB-Anschluss (ttyACM0) laden
_handle = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
// Fehler abfangen
if(_handle == -1) {
// Fehler
throw THOMASException("Fehler: Es konnte keine Verbindung zum Arduino hergestellt werden!");
}
// Anschluss-Flags leeren
fcntl(_handle, F_SETFL, 0);
// Anschluss-Optionen erstellen
termios fOpt;
// Aktuelle Anschluss-Optionen abrufen
tcgetattr(_handle, &fOpt);
// Baudrate setzen (115200);
cfsetispeed(&fOpt, B115200); // Input
cfsetospeed(&fOpt, B115200); // Output
// Konfigurieren, dass das Programm auf eine Antwort warten soll
fOpt.c_cc[VMIN] = 1;
fOpt.c_cc[VTIME] = 1;
// Flags zum Initialisieren des Arduinos setzen
fOpt.c_cflag |= CS8;
fOpt.c_iflag &= ~(IGNBRK | BRKINT | ICRNL | IXON );
fOpt.c_oflag &= ~(OPOST | ONLCR);
fOpt.c_lflag &= ~ (ECHO | ECHOCTL | ICANON | ISIG | IEXTEN);
// Linux-Befehl zum manuellen Resetten des Arduinos:
//stty -F /dev/ttyACM0 cs8 115200 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts
// Neue Port-Optionen einsetzen
tcsetattr(_handle, TCSAFLUSH, &fOpt);
}
// Destruktor
ArduinoCom::~ArduinoCom()
{
// Verbindung schließen
close(_handle);
}
// Daten an den Arduino senden
void ArduinoCom::Send(UBYTE *package, unsigned char packageLength)
{
// Data Array mit packageLength
UBYTE *data = new UBYTE[packageLength +1];
// Einfügen der gesamten UBYTE-Länge.
data[0] = packageLength;
// Inhalt des Paketes durchlaufen
for(int i = 0; i < packageLength; i++)
{
// Einfügen des package-Arrays in das data-Array
data[i+1] = package[i];
}
// Anzahl der gesendeten Daten merken
int n = write(_handle, data, packageLength + 1);
// Anzahl der gesendeten Daten pruefen
if(n != packageLength +1)
{
// Mist
throw THOMASException("Fehler beim Senden eines Befehls!");
}
// Speicher freigeben
delete[] data;
}
// Auf ein eingehendes Paket warten und dieses zurückgeben
UBYTE* ArduinoCom::Receive()
{
// Erstelle Variable für die UBYTE Länge
ssize_t UBYTEs;
// UBYTE-Array für den Header
UBYTE header[1] = {0};
// Temporärer Puffer
UBYTE tempBuffer[1] = {0};
// Puffer für das Paket
buffer = new UBYTE[header[0]];
// Header empfangen
read (_handle, header, 1);
// Daten empfangen
for(int i = 0; i < header[0]; i++){
// Nächstes UBYTE aus dem Stream lesen
read(_handle, tempBuffer, 1);
// UBYTE in den Puffer schreiben
buffer[i] = tempBuffer[0];
}
// Puffer zurückgeben
return buffer;
}
// Hilfsfunktion zum Ausführen eines Befehles in der Konsole
std::string ArduinoCom::Exec(std::string cmd)
{
// String für die Antwort
std::string data;
// Stream
FILE * stream;
// Größe des Puffers
const int max_buffer = 256;
// Puffer
char buffer[max_buffer];
// String zum Weiterreichen der Ausgabe an den Befehl anhängen
cmd.append(" 2>&1");
// Stram zum Lesen öffnen
stream = popen(cmd.c_str(), "r");
// Öffnen erfolgreich...?
if (stream)
{
// Schleife
while (!feof(stream))
{
// Daten vorhanden?
if (fgets(buffer, max_buffer, stream) != NULL)
{
// An die Antwort anhängen
data.append(buffer);
}
// Stream schlißen
// FIXME: Führt zu Abstürzen, funktioniert aber auch ohne!
//pclose(stream);
}
}
// Antwort zurückgeben
return data;
}