Arduino mit Processing steuern

Hallo zusammen :slight_smile:

in meinem Projekt, würde ich gerne mehrere Motoren, von Processing aus steuern. Das Ziel war eigentlich, dass ich nur Variabeln von Processing zum Arduino schicke, und dass dann der Arduino den Sketch selbst hat, um zu wissen, was mit den Daten anfangen.

nun bin ich aber daran gescheitert. Ich habe keine Ahnung, was an meinem Sketch nicht stimmt:

(zum Testen habe ich einfach mal 2 leds genommen)

Arduino Code:

char incomming;
int incommingCounter = 0;
int arrayCounter = 0;
const char d = ',';
char *pch;
const char *delimiters = &d;

int led1;
int led2;

int led1P = 13;
int led2P = 12;

void setup()
{
  Serial.begin(9600);

  pinMode(led1P, OUTPUT);
  pinMode(led2P, OUTPUT);
}

void readSerial()
{
  int bufferSize;
  char incommingBuffer[bufferSize];
  char *data = &incommingBuffer[bufferSize];
  while(Serial.available())
  {
    incomming = Serial.read();
    if(incomming != '\r')
    {
      bufferSize = Serial.readBytesUntil(d, incommingBuffer, k);
    }
    else
    { 
      pch = strtok(data, delimiters);
      while (data != NULL)
      {
        value[arrayCounter++] = atoi(pch);
        pch = strtok (NULL,  delimiters);
      }
      
      led1 = value[1];
      led2 = value[2];
    }
  }
}

void loop ()
{
  if (led1 == 111)
  {
    digitalWrite(led1P, HIGH);
  }
  else if (led1 !=111)
  {
    digitalWrite(led1P, LOW);
  }
  if (led2 = 222)
  {
    digitalWrite(led2P, HIGH);
  }
  else if (led2 != 222)
  {
    digitalWrite(led2P, LOW);
  }
}

Processing Code:

import processing.serial.*;
Serial myPort;

void setup()
{
  size (500, 500);
  println(Serial.list());
  myPort = new Serial(this, "/dev/tty.usbserial-A9007U0O", 9600);
}

void draw()
{
  int led1 = 111;
  int led2 = 222;
  
  myPort.write(str(led1));
  myPort.write(",");
  myPort.write(str(led2));
  myPort.write(",");
  myPort.write("\r");
  
  delay(1000);
}

ich wäre sehr dankbar, wenn sich jemand den code schnell durchschauen könnte.

Gruss Jonas

Deine Einlese-Funktion kann nicht funktionieren. Du machst da mehrere katastrophale Fehler

  int bufferSize;
  char incommingBuffer[bufferSize];
  char *data = &incommingBuffer[bufferSize];

1.) bufferSize ist undefiniert. Das muss zur Compile-Zeit feststehen!
2.) die dritte Zeile ist völlig unnötig. Die Variable für den Puffer ist schon ein char* !! In C sind Arrays Zeiger auf das erste Element.
3.) readSerial() wird nirgends aufgerufen was ich so sehe
4.) Dein String wird nicht mit NULL terminiert
5.) Du entfernst mit Serial.read() schon Zeichen aus dem Eingangspuffer. Diese kannst du danach nicht mit readBytesUntil() einlesen, da sie schon weg sind.
6.) Selbst wenn es gehen würde, liest readBytesUntil nur bis zum Komma. Bei strtrok() willst du aber den ganzen String auf einmal einlesen und danach splitten. Das ist eine Hybrid-Version zwischen den zwei Möglichkeiten, die beides nicht richtig macht.

Dann ein weiteres großes Problem:
die serielle Übertragung ist langsam und dauert bei 9600 Baud ca. 1ms pro Zeichen! Du kannst also nie while(Serial.available() machen). Das liest ein Zeichen ein und bricht dann ab weil der Rest noch unterwegs ist.

Mach es so:

const int SERIAL_BUFFER_SIZE = 31;
char serialBuffer[SERIAL_BUFFER_SIZE];

void loop()
{
   if(readSerial() == true)
   {
   }
}

bool readSerial()
{
	static byte index;

	if(Serial.available() > 0)
	{		
		char c = Serial.read();
		
		if(c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
		{
			serialBuffer[index++] = c;
		}
		else if(c == '\r')
		{
			serialBuffer[index] = '\0';
			index = 0;
			return true;
		}
	}
	return false;
}

Und Teste erst mal ob die Zeile ganz ankommt, bevor du sie mit strtok() bearbeitest.

Das ruft die Funktion ständig auf und schaut ob was da ist. Es ist also völlig egal wie lange die Übertragung dauert. Wenn die Funktion dann true zurück gibt ist sie fertig und man kann den String verarbeiten

Und strtok() will einen String an Delimitern. Also:

pch = strtok(serialBuffer, ",");

Hier wieder: Strings sind Zeiger auf das erste Element und damit schon ein char*

Und "incoming" schreibt man mit einem "m" :wink:

hey!

Zuerst mal riiiesen Dank für deine Hifle. ich weiss, dass ich sozusagen keine Ahnung vom programmieren habe, und desshalb habe ich ja auch fehler erwartet.. :wink:

das ist jetzt vielleicht noch eine dümmere Frage: aber wie soll ich testen, ob die Zeile ganz angekommen ist, wenn die serielle Schnittstelle ja schon besetzt ist..? Dann kann ich ja nicht " Serial.print()" kommen...

Dann habe ich noch ein weiteres Probelm, was mit dem i2C bus zu tun hat: ich kann mein Gerät (ein Druck- und Temperatursensor) nicht mit dem klassischen Wire-master_reader auslesen..

Vielleicht weiss ja jemand auch hier auf die schnelle, was das für ein Problem ist. Im Anhang befindet sich das Datenblatt mit rechts auf der 2. Seite dem Kommunikationsbeschrieb.

Der Code fürs Arduino ist der gewohnte:

#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(0x40, 6);    // request 6 bytes from slave device #2

  while(Wire.available())    // slave may send less than requested
  { 
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  }

  delay(500);
}

Vielen Dank für die Hilfe

Jonas

4ld_9ld_g.pdf (522 KB)

-Jonas-:
das ist jetzt vielleicht noch eine dümmere Frage: aber wie soll ich testen, ob die Zeile ganz angekommen ist, wenn die serielle Schnittstelle ja schon besetzt ist..? Dann kann ich ja nicht " Serial.print()" kommen...

Doch kannst du. Empfangen und Senden sind zwei getrennte Leitungen. Daher kannst du einfach Serial.println(serialBuffer) machen.

Am besten du lässt erst mal Processing weg und verwendest den normalen Serial Monitor. Tippe etwas ein und schaue was der Arduino zurück sendet.

Vielleicht weiss ja jemand auch hier auf die schnelle, was das für ein Problem ist. Im Anhang befindet sich das Datenblatt mit rechts auf der 2. Seite dem Kommunikationsbeschrieb.

Und dein Code machst was völlig anderes.

Eine Messung wird glaube ich angefordert wenn du das machst:

Wire.beginTransmission(ADR);
Wire.write(0xAC);
Wire.endTransmission();

Dann fehlen die 6ms Wartezeit. Und erst dann kannst du die Daten mit requestFrom() und read() auslesen. Und zwar 5 Bytes, (1 Status, 2 Druck, 2 Temp). Nicht 6.

So 100%ig sicher bin ich mir dabei aber auch nicht.

Danke für die richtig schnelle Antwort! :slight_smile:

Aber was macht denn der Code, der das Beispiel zeigt..? ich dachte das sei das :~

ich probier das gleich mal alles aus.. :slight_smile:

Dein Code liest einfach 6 Bytes ein. Aber du musst erst mal eine Messung anfordern, dann warten (oder komplizierter das Status Byte auslesen oder die Status Leitung abfragen) und dann das Ergebnis auslesen.

Ich habe noch mal am Kommunikationszeugs mit Processing herumgebastelt (bzw. eingefügt was du mir gesagt hasst XD)

jetzt habe ich aber noch das Problem, dass ich, wenn ich den delay() im void draw() von Processing unter 500 setze, funktioniert gar nichts mehr.. weshalb ist denn das so?!

hier die Codes:
Processing:

import processing.serial.*;
Serial myPort;

int firstValue, secondValue;



void setup()
{
  size (500, 500);
  println(Serial.list());
  myPort = new Serial(this, "/dev/tty.usbmodem1411", 9600);
}

void draw()
{
  background(51);
  
  int led1 = mouseX;
  int led2 = mouseY;
  
  myPort.write(str(led1));
  myPort.write(",");
  myPort.write(str(led2));
  myPort.write(",");
  myPort.write("\r");
  
  text(firstValue, 10, 30);
  text(secondValue, 10, 60);
  
  delay(500);
}

void serialEvent(Serial myPort)
{
  if (myPort.available() > 0)
  {
    String completeString = myPort.readStringUntil(10);
    if (completeString != null)
    {
      trim(completeString);
      String seperateValues[] = split(completeString, ',');
      firstValue = int(seperateValues[0]);
      secondValue = int(seperateValues[1]);
    }
  }
}

und der Arduino:

const int SERIAL_BUFFER_SIZE = 31;
char serialBuffer[SERIAL_BUFFER_SIZE];

void setup()
{
  Serial.begin(9600);
}

void loop()
{
   if(readSerial() == true)
   {
     Serial.print(serialBuffer);
     Serial.print(',');
     Serial.println();
   }
}

bool readSerial()
{
  static byte index;

  if(Serial.available() > 0)
  {		
    char c = Serial.read();
		
    if(c >= 32 && index < SERIAL_BUFFER_SIZE - 1)
    {
      serialBuffer[index++] = c;
    }
    else if(c == '\r')
    {
      serialBuffer[index] = '\0';
      index = 0;
      return true;
    }
  }
  return false;
}

wäre mal wieder Dankbar um Hilfe XD
LG

Serenifly:
Dein Code liest einfach 6 Bytes ein. Aber du musst erst mal eine Messung anfordern, dann warten (oder komplizierter das Status Byte auslesen oder die Status Leitung abfragen) und dann das Ergebnis auslesen.

Ahhh okk ja ich seh's

Danke :smiley:

Setze vielleicht mal die Baudrate auf 115200. Aber auch bei 9600 sollte eigentlich Zeit sein um etwas mehr zu senden.

Dann funktioniert gar nichts mehr :~ :smiley:

Sonst hat hier niemand eine Idee, was das Problem sein könnte, komm' da echt gerade nicht mehr weiter... :~

LG

Kann ich so jetzt auch nicht sagen.

Da du sowieso Probleme mit dem Programmieren des Protokolls hast (auch wenn es erst mal funktionieren) würde, wäre Firmata eine Option:
http://playground.arduino.cc/Interfacing/Processing

Damit kann man den Arduino direkt vom PC aus fernsteuern. Das Protokoll wird einem schon abgenommen und man sagt auf dem PC "setzt diesen Ausgang" etc.

ja das habe ich mir auch schon angeschaut. Das geht aber nicht, da der Arduino autonom bleiben muss. Es muss die Möglichkeit geben, ein "Notfallsystem" zu programmieren, dass in Gang gesetzt wird, wenn der Arduino über eine gewisse Zeit nicht mehr mit dem PC verbunden ist.

Was du auch probieren kannst ist auf die ganze String Geschichte zu verzichten und direkt Binärdaten zu senden.

Du kannst Werte von 0-255 in einem Byte schicken. Für einen 16 Bit Integer (auf dem PC short, nicht int!) müsstest du also den Integer in High-Byte und Low-Byte aufteilen:

short data = 1234;
byte highByte = (byte) (data & 0xff);
byte lowByte = (byte) ((data >>> 8) & 0xff);

Auf Arduino Seite:

int data = word(highByte, lowByte);

Warnung:
Java ist Big Endian! Dadurch ist die Byte-Ordnung anders herum als auf der Arduino Seite.

EDIT:
Aber wenn man es auf beiden Seiten per Hand macht, sollte das keine Rolle spielen. :slight_smile: Wenn man aber irgendwo Konverter Klassen von Integer zu Byte Array o.ä. hat, dann muss man aufpassen.

Auf dem Weg kann man auch Kommandos schicken, z.B. im ersten Byte. Oder ein Byte als Längenfeld verwenden wenn man eine Nutzlast variabler Länge hat.

Wenn du erst mal nur 4 Bytes schickst, kannst du einfach auf Serial.available() >= 4 abfragen und direkt vier mal read() machen.

Du kannst Werte von 0-255 in einem Byte schicken. Für einen 16 Bit Integer (auf dem PC short, nicht int!) müsstest du also den Integer in High-Byte und Low-Byte aufteilen:

short data = 1234;

byte highByte = (byte) (data & 0xff);
byte lowByte = (byte) ((data >>> 8) & 0xff);


Warnung:
Java ist Big Endian! Dadurch ist die Byte-Ordnung anders herum als auf der Arduino Seite.

Da hast du dich leider etwas verguckt. Innerhalb von Java sollte es gar nicht interessieren, weil es da keine Pointer gibt, die man missbrauchen kann. Wo es drauf ankommt (NIO Buffer etc), kann man rauskriegen oder einstellen, auf was für Hardware Java gerade läuft.
Nach meinem Verständnis ist das Low Byte das niederwertigste Byte, wo immer es im Speicher stehen mag.

short data = 0xAFFE;
byte lowByte = (byte) (data & 0xff);  // ergibt 0xFE
byte hiByte   = (byte) ((data >> 8) & 0xff);  // ergibt 0xAF

In welcher Reihenfolge Binär-Daten übertragen werden, muss man natürlich festlegen, wenn man nicht nur Einzel-Bytes überträgt.

Der Fluch, wenn man zwar arabische Zahlen verwendet, Texte aber weiter falschrum (links nach rechts) schreibt :wink:

michael_x:
Da hast du dich leider etwas verguckt. Innerhalb von Java sollte es gar nicht interessieren, weil es da keine Pointer gibt, die man missbrauchen kann.

Das hat rein gar nichts mit Pointern zu tun. Auf die Byte Ordnung muss man da sehr wohl achten. Ich bin da schon mal drauf reingefallen als ich ein Java Program auf einem µC mit einem C# System auf dem PC verbunden habe. :slight_smile:
Ich habe das dann auf dem PC herumgedreht indem ich eine Klasse runtergeladen habe bei der man bei der Konvertierung von Byte Array <-> Integer die Endianess auf Big Endian umstellen kann.

Was stimmt ist das man je nach verwendeter Klasse die Byte-Ordnung auch in Java ändern kann, wenn man z.B. einen Integer in ein Byte Array wandelt . Ich wollte es aber erst mal so einfach wie möglich halten, ohne zusätzliche Klassen wie ByteBuffer ins Spiel zu bringen.

Was den Code oben betrifft. Kann sein dass ich mich da mit Low/High vertan habe. Das habe ich nur schnell von hier kopiert:

Da wird das erst mal nur in ein Array geschrieben.

Auf das ausmaskieren kann man wahrscheinlich auch verzichten.

ein Java Program auf einem µC mit einem C# System auf dem PC verbunden

Das ist ja auch nicht "innerhalb Java" .
In C legt man sich halt mit Pointern am leichtesten auf die Nase.

Aber ich wollte Jonas eigentlich nicht verunsichern.
Auf dem Arduino müsste ein Firmata sketch um die Autonom-Funktionen erweitert werden.
Das wäre dann eigentlich die Hauptaufgabe.
Ob dazu eine "universelle" Firmata/Processing Kommunikation oder was selbstgestricktes Spezielles kommt, ist nach meiner Einschätzung eher eine Frage der Vorliebe als von Gut/Schlecht.

michael_x:
Das ist ja auch nicht "innerhalb Java" .

Das hier auch nicht.

Habe nochmal drüber nachgedacht:
Wenn man es sowie in dem Code oben auf beiden Seiten komplett per Hand macht, sollte es ohne Probleme gehen. Die Probleme fangen an sobald man auf einer Seite einen automatischen Konverter auf Byte Array Basis oder sowas wie einen I/O Stream verwendet. Die erwarten eine Byte Ordnung, die man nicht immer ändern kann.

Anyways...

Auf dem Arduino müsste ein Firmata sketch um die Autonom-Funktionen erweitert werden.

Habe mit Firmata praktisch noch nichts richtiges gemacht, aber ja. Es sollte eigentlich ohne große Probleme möglich sein, dass der Arduino von sich aus werkeln kann und trotzdem noch Firmata-Kommandos nebenbei empfängt.

Da gibt es in loop() wohl eine Zeile wie "Wenn Firmata Daten da sind, bearbeite sie". Wenn nicht macht man was anderes.

Ob dazu eine "universelle" Firmata/Processing Kommunikation oder was selbstgestricktes Spezielles kommt, ist nach meiner Einschätzung eher eine Frage der Vorliebe als von Gut/Schlecht.

Auch der Programmier-Kenntnisse. Was fertiges zu verwenden ist hier wahrscheinlich einfacher.

ok, danke für eure Anregungen :smiley:

ich werde mir das Firmata-Zeugs wohl noch mal anschauen.. :wink:

PS: der Drucksensor mit i2c funktioniert so weit! :slight_smile:

soooo ich habe das Problem so weit für mich gelöst. ist erst mal etwas Spielerei.. die richtige Anwendung wird ab jetzt darauf aufgebaut.. :))

fals es jemanden interessiert, oder er die gleichen Probleme hatte, hier die Codes, die ich gebraucht habe. man kann damit Befehle von Processing zum Arduino senden und gleichzeitig Sensordaten vom Arduino an Processing senden.

wie ihr sicher schon gemerkt habt, bin ich ein Anfänger was programmieren angeht, meine Version hier ist also garantiert noch verbesserungsfähig. Das ganze ist garantiert schlanker zu lösen. Gerade was globale/ lokale Variablen angeht, habe ich den Durchblick überhaupt nicht :D. Wer Lust hat kann ja gerne auch Anregungen geben :wink:

Das wär's bis jetzt mal :slight_smile:

Arduino Code:

// benötigte Libraries:
#include <Wire.h>  // für I2C Übertragungen

int led1 = 13;
int led2 = 12;

int ldrP = A0;           // der Pin, an dem das LDR ausgelesen wird

int Umdrehungen = 0;    // die Vareibel, die es dann zurück gibt.
boolean booleanReadMotorumdrehungen = true;

float T;             // speichert die Temperatur des Drucksensors
float P;             // speichert den Druck des Drucksensors


byte c[5];                                  // speichert die erhaltenen Bytes (Status Byte, MSB-Druck, LSB-Druck, MSB-Temperatur, LSB-Temperatur) zwischen
unsigned long millisReadDrucksensor0 = 0;   // speichert millis();
unsigned long millisReadDrucksensor1 = 0;   // speichert millis();
unsigned long intervalReadDrucksensor = 7;  // gibt an, wie lange die Pause zwischen Anfrage und Auslesen ist
boolean booleanReadDrucksensor = true;

const int SERIAL_BUFFER_SIZE = 64;
char serialBuffer[SERIAL_BUFFER_SIZE];

const int INCOMMING_DATA_SIZE = 10;
int array[INCOMMING_DATA_SIZE];

boolean booleanSerialCommunication = false;

void setup()
{
  Serial.begin(9600);
  Wire.begin();

  // definiert die Pins als OUTPUT oder INPUT:
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
}

void loop()
{
  readDrucksensor();
  
  if (Serial.available() > 0)
  {
    static byte index;
    char inByte = Serial.read();
    
    if(inByte >= 34 && inByte < 65 && index < SERIAL_BUFFER_SIZE - 1 && booleanSerialCommunication == false)
    {
      serialBuffer[index++] = inByte;
    }
    
    else if(inByte == '\n' && booleanSerialCommunication == false)
    {
      serialBuffer[index] = '\0';
      index = 0;
      booleanSerialCommunication = true;
    }
    else if(inByte == 'A')
    {
      Serial.print(T);
      Serial.print(",");
      Serial.print(P);
      Serial.print(",");
      Serial.print(readMotorenumdrehungen());
      Serial.print('\n');
    }
  }
  
  if (booleanSerialCommunication == true)
  {
    encodeSerial();
    booleanSerialCommunication = false;
  }
  
  
  analogWrite(led1, array[0]/12);
  analogWrite(led2, array[1]/12);
  
}

void encodeSerial()
{
  char stringBuffer[SERIAL_BUFFER_SIZE+1];
  int INDEX = 0;
  char *str;
  char *p;
  strncpy(stringBuffer, serialBuffer, SERIAL_BUFFER_SIZE);
  for( str = strtok_r(stringBuffer, ",", &p); str; str = strtok_r(NULL, ",", &p))
  {
    array[INDEX++] = atoi(str);
  }
}

void readDrucksensor()
{

  millisReadDrucksensor1 = millis();

  if (booleanReadDrucksensor == true)
  {
    Wire.beginTransmission(0x40);
    Wire.write(0xAC);
    Wire.endTransmission();

    millisReadDrucksensor0 = millisReadDrucksensor1;

    booleanReadDrucksensor = false;                  
  }

  if(millisReadDrucksensor1 - millisReadDrucksensor0 > intervalReadDrucksensor)
  {
    Wire.requestFrom(0x40, 5);

    while(Wire.available())
    {
      for(int i = 0; i < 5; i++)
      {
        c[i] = Wire.read();
      }
    }

    // fügt MSB und LSB der neu erhaltenen Daten zusammen
    int Prel = (c[1]*256) + c[2];
    int Trel = (c[3]*256) + c[4];

    // Skaliert die zusammengefügten Daten in "bar"
    P = map(Prel, 16384, 49152, 0, 10000);
    T = map(Trel, 384, 64384, -10000, 30000);
    P /= 1000.0;
    T /= 200.0;

    booleanReadDrucksensor = true;
  }
}

int readMotorenumdrehungen()
{
  int ldr = analogRead(ldrP);

  if(ldr > 30 && booleanReadMotorumdrehungen == true)
  {
    booleanReadMotorumdrehungen = false;
  }

  if(ldr < 30 && booleanReadMotorumdrehungen == false)
  {
    Umdrehungen++;
    booleanReadMotorumdrehungen = true;
  }
  return Umdrehungen;
}

void returnSerial()
{
  Serial.print('H');
  Serial.print(',');
  for(int i = 0; i < INCOMMING_DATA_SIZE; i++)
  {
    Serial.print(array[i]);
    Serial.print(',');
  }
  Serial.print('\n');
}

Processing Code:

import processing.serial.*;

Serial uBootPort;  // Create object from Serial class

int startx = 50;
int starty = 250;
int breite = 30;
int hoehe = -200;
int V = 0;
short speed = 0;



boolean establishContact = false;

float fgcolor;      // Fill color
float xpos, ypos;   // Starting position of the ball

char HEADER = 'H';


void setup() {
  size(750, 750);
  String portName = Serial.list()[0];
  uBootPort = new Serial(this, "/dev/tty.usbmodem1411", 9600);

  uBootPort.bufferUntil('\n');
  
  
  
  smooth();
}

void draw() {
  
  if (millis() > 2000 && establishContact == false)
  {
    uBootPort.write('A');
    establishContact = true;
  }
  
  if (establishContact == true)
  {
    uBootPort.write(speed + "0");
    uBootPort.write(',');
  
    uBootPort.write(speed + "0");
    uBootPort.write('\n');
  }
  
  
  background(252, 234, 194);
  noStroke();

  fill(252, 234, 210);
  rect(startx, starty, breite, hoehe);

  fill(255, 166, 82);
  rect(startx, starty, breite, -V);

  fill(0, 0, 0);

  text(xpos, 150, 30);
  text(ypos, 150, 60);
  text(fgcolor, 150, 90);

  String s = "Hauptantrieb";

  text("Hauptantreib", 50, 40);
  text(speed, 50, 270);
}

void serialEvent(Serial uBootPort) { 
  // read the serial buffer:
  String myString = uBootPort.readStringUntil('\n');
  // if you got any bytes other than the linefeed:
  if (myString != null)
  {
    myString = trim(myString);
    // split the string at the commas
    // and convert the sections into floats:
    float sensors[] = float(split(myString, ','));
    // print out the values you got:
    for (int sensorNum = 0; sensorNum < sensors.length; sensorNum++) {
      print("Sensor " + sensorNum + ": " + sensors[sensorNum] + "\t");
    }
    // add a linefeed after all the sensor values are printed:
    println();
    if (sensors.length > 1) {
      xpos = sensors[0];
      ypos = sensors[1];
      fgcolor = sensors[2];
    }
    // send a byte to ask for more data:
    uBootPort.write('A');
  }
}

void mouseDragged()
{
  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY > starty + hoehe) && (mouseY < starty)) {
    V=(starty-mouseY);
  }

  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY > starty) && (mouseY < starty + 10)) {
    V=0;
  }

  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY < starty+hoehe) && (mouseY > (starty+hoehe)-10 )) {
    V=starty-(starty + hoehe);
  }
  speed = (short)(int(map(V, 0, starty+hoehe, 0, 255))/4);
}

void mousePressed()
{
  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY > starty + hoehe) && (mouseY < starty)) {
    V=(starty-mouseY);
  }

  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY > starty) && (mouseY < starty + 10)) {
    V=0;
  }

  if ((mouseX > startx) && (mouseX < startx + breite) && (mouseY < starty+hoehe) && (mouseY > (starty+hoehe)-10 )) {
    V=starty-(starty + hoehe);
  }
  speed = (short)(int(map(V, 0, starty+hoehe, 0, 255))/4);
}