Erst einmal danke für die Antworten. Das mit den Timeouts + Protokoll werde ich mal versuchen.
Mittlerweile hab ich es geschafft, eine Steuerung für den RP6 über den PC zu bauen. Ein Protokoll ist hier denke ich nicht unbedingt notwendig, da nur hier und da ein paar Parameter versendet werden. Im Grunde sendet der PC die Parameter (Bewegungsart, Richtung, Distanz, Speed) an den Pi, der leitet die Parameter dann weiter zum RP6, der den Befehl dann verarbeitet. Hier der Quellcode, falls es jemanden interessiert:
Auf dem PC wird eine normale HTML-Seite verwendet, über Ajax werden dann einfach die gewählten Parameter per HTTP GET Request an den Webserver auf dem Pi geschickt. Der Pi und der PC müssen sich nur im gleichen Netzwerk befinden, dann muss man noch die richtige IP-Adresse eintragen. Die Jsonp-Sache dient nur zu Debug-Zwecken, braucht man, um Daten auch wieder vom Pi an den PC zurückzuschicken.
HTML-Code:
<html>
<head>
<script src="jquery-1.10.2.min.js"></script>
<title>RP6 Steuerung </title>
</head>
<body>
<h1> RP6 Steuerung </h1>
<script>
function sendCommand()
{
var move = document.Formular.movement[document.Formular.movement.selectedIndex].value;
var dir = document.Formular.direction[document.Formular.direction.selectedIndex].value;
var dist = document.Formular.distance.value;
var speed_ = document.Formular.speed.value
$.ajax({
type: 'GET',
url: 'http://10.0.0.4',
dataType: 'jsonp',
jsonp: 'jsonp',
jsonpCallback : 'parseResponse',
crossDomain: true,
data: {movement: move, direction: dir, distance: dist, speed: speed_},
error: function (data){
$('#antwort').html("Befehl konnte nicht gesendet werden: " + data);
},
success: function (data){
$('#antwort').html("Folgender Befehl wurde erfolgreich gesendet:<br>" + "Bewegung: " + data.movement + "<br>Richtung: " + data.direction + "<br>Distanz/Grad: " + data.distance + "<br>Geschwindigkeit: " + data.speed);
}
});
}
</script>
<form name="Formular">
Bewegung:<select name="movement">
<option>Fahren</option>
<option>Rotieren</option>
</select><br>
Richtung:<select name="direction">
<option>Vor</option>
<option>Zurueck</option>
<option>Links</option>
<option>Rechts</option>
</select><br>
Distanz/Grad:<input name="distance"><br>
Geschwindigkeit:<input name="speed" value="100"><br>
<a href="javascript:sendCommand()">Senden!</a>
</form>
<div id="antwort">
</div>
</body>
</html>
Auf dem Pi verwende ich das Framework Flask für den Webserver und die pylibftdi für die Kommunikation zum USB-Interface. Das Script verarbeitet HTTP-Anfragen und sendet die Parameter durch einen Strichpunkt getrennt an den RP6 weiter.
Code:
from flask import Flask
from flask import request
from pylibftdi import Device
import time
app = Flask(__name__)
@app.route('/')
def send_command():
if 'direction' in request.args and 'movement' in request.args and 'distance' in request.args and 'speed' in request.args:
with Device(mode='b') as dev:
dev.baudrate = 38400
dev.write(request.args.get('movement') + ';' + request.args.get('direction') + ';' + request.args.get('distance') + ';' + request.args.get('speed') + '\n')
time.sleep(1)
answer = dev.readline()
print repr(answer)
return request.args.get('jsonp') + '({"text": "Kommando wurde erfolgreich gesendet",' + '"direction":"' + request.args.get('direction') + '","movement":"' + request.args.get('movement') + '","distance":"' + request.args.get('distance') + '","speed":"' + request.args.get('speed') + '"})';
else:
return 'Willkommen zur RP6-Steuerung!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=True)
Auf dem RP6 habe ich zum Einlesen im Grunde das Beispielprogramm genommen. Die Parameter werden in ein Struct geschrieben, welches dann einer Funktion übergeben wird, die den Befehl ausführt.
Code:
#include "RP6RobotBaseLib.h"
#include <stdint.h>
#define MAX_SIZE 70 // maximum UART buffer size
typedef struct command
{
char movement_ [20];
char direction_ [20];
char distance_string_ [20];
char speed_string_ [20];
int16_t distance_; // also degrees for rotation
int16_t speed_;
} Command;
void executeCommand (Command* command)
{
uint8_t direction = 0;
if (strcmp(command->direction_,"Vor") == 0)
{
direction = FWD;
}
else if (strcmp(command->direction_,"Zurueck") == 0)
{
direction = BWD;
}
else if (strcmp(command->direction_,"Links") == 0)
{
direction = LEFT;
}
else if (strcmp(command->direction_,"Rechts") == 0)
{
direction = RIGHT;
}
//fortunately the functions move and rotate have the same signature
void (*movement_function) (uint8_t, uint8_t, uint16_t, uint8_t) = 0;
if (strcmp(command->movement_,"Fahren") == 0 && (direction == FWD || direction == BWD) && command->speed_ <= 200)
{
command->distance_ = DIST_CM(command->distance_);
movement_function = move;
setLEDs(0b111000);
}
else if (strcmp(command->movement_,"Rotieren") == 0 && (direction == LEFT || direction == RIGHT))
{
movement_function = rotate;
setLEDs(0b000111);
}
// execute the function, either move or rotate
if (movement_function)
{
movement_function(command->speed_,direction,command->distance_,true);
}
}
void readInput(void)
{
char receiveBuffer [MAX_SIZE+1];
clearReceptionBuffer();
uint8_t buffer_pos = 0;
while (1)
{
if(getBufferLength())
{
receiveBuffer[buffer_pos] = readChar();
if (receiveBuffer[buffer_pos] == '\n')
{
break;
}
buffer_pos++;
if (buffer_pos >= MAX_SIZE)
{
writeString_P("Too many characters entered!\n");
return;
}
}
}
buffer_pos++;
receiveBuffer[buffer_pos] = '\0';
// parse the receive buffer and store the values to the Command struct, parameters are separated by a ';'
Command command;
char* string = command.movement_;
uint16_t i = 0;
uint16_t k = 0;
while (1)
{
if (receiveBuffer[i] == ';') // delimiter was found
{
string[k] = '\0';
string += 20; //set the pointer to the next char* in the Command struct
k = 0;
i++;
continue;
}
if (receiveBuffer[i] == '\n')
{
string[k] = '\0';
break;
}
string[k] = receiveBuffer[i];
k++;
i++;
}
// convert string to integer
command.distance_ = atoi(command.distance_string_);
command.speed_ = atoi(command.speed_string_);
// debug: send the values back to the Raspberry Pi
writeString(command.direction_);
writeString(command.movement_);
writeInteger(command.speed_,DEC);
writeInteger(command.distance_,DEC);
executeCommand(&command);
}
int main(void)
{
initRobotBase();
powerON();
while(1)
{
readInput();
task_RP6System();
}
return 0;
}
Lesezeichen