Frage zu speichern der serial.read()

vor 20 Wochen 6 Tage von lord-maricek

Moin,

ich habe bisher immer gelesen, dass der serial.read() Wert in einem byte gespeichert wird.

byte incoming = serial.read();

Gibt es eine Möglichkeit, den serial.read Wert in einem String zu speichern?

Philipp

23 Antworten auf “Frage zu speichern der serial.read()”


Darstellungsoptionen

Wähle hier deine bevorzugte Anzeigeart für Kommentare und klicke auf „Einstellungen speichern“ um die Änderungen zu übernehmen.
  1. uwe sagt:

    Hallo Philipp

    einige Faktoren die den sketch verändern: Weißt Du wieviele Bytes gesendet werden? Wird die gesendete Zeichenfolge durche in "enter" beendet oder ist das letzte Zeichen ein "0" (wie es in Strings bei Arduino ist)?

    Untenstehendes Beispiel für 4 übertragenen Zeichen:

    char Data[5];
    int inByte;
    int i;
    int zahl =0;
    ...
    in der loop funktion:

    inByte = 0;
    do {
    // Wenn Daten verfügbar 4 Zeichen in Data schreiben
    if (Serial.available()) {
    Data[i] = Serial.read();
    i++;
    }
    } while (i<4);
    // Abschließende Null für gültigen String
    Data[i] = 0;

    Wenn die übertragenen Zeichen eine mehrstellige Zahl sind dann kannst Du sie mit
    zahl = atof(Data);
    in eine Zahl umwandeln.

    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    moin,

    die Werte die vom Rechner kommen werden ca. so aussehen.

    151613191020

    An den Arduino kommen 2 Fahrtregler und ein paar Servos. Die benötigen ein PWM Signal von 1,0 bis 2,0 Millisekunden. Am Rechner werden dann immer die Schaler und Schieberstellungen überprüft und je nach Stellung ein Wert zwischen 1,0 und 2,0 zugewiesen. Die Variablen werden dann alle mal 10 genommen: 1,0; 1,6 usw. wird dann zu 10;16 usw. Die werden dann in einer Variable zu einer langen Zahl zusammengefasst. Also 1016 usw. Die werden dann zum Arduino gesendet und als String ausernandergenommen. Also:

    //beispiel
    string = serial.read() //1016
    servo1 = string[1];
    servo1 += string[2];
    servo2 = string[3];
    servo2 += string[4];
    servo1 = servo1 / 10;
    servo2 = servo2 / 10;

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    Also:
    Für die Pulsweite des PWM-Signals rechne mit µ-Sekunden, so kannst Du eine Integerzahl verwenden und brauchst keine Flieskommazahl.
    Also statt 1,0 bis 2,0 msek 1000 bis 2000 µsek.
    Der Arduino hat zwar PWM Ausgänge aber Du kannst nicht die Pulsdauer genau einstellen sonder in 256 Schritten von 0 bis 100% auch ist die Frequenz fix auf ca 490 Hz.
    Du wirst das PWM-Signal in SW programmieren müssen.

    Wenn ich das richtig verstanden habe werden 4 Zeichen gesendet, die jeweils 2 Stellen des PWM-Signals der beiden Servos sind.

    zum Code:
    char Data[3];
    char CharServo1[2];
    char CharServo2[2];
    int i;
    int servo1;
    int servo2;
    ...
    in der loop funktion:

    do {
    // Wenn Daten verfügbar 4 Zeichen in Data schreiben
    if (Serial.available()) {
    Data[i] = Serial.read();
    i++;
    }
    } while (i<4);

    i=0;
    // Data in 2 Strings teilen
    CharServo1[0]=Data[0];
    CharServo1[1]=Data[1];
    CharServo1[2]= 0; // Abschließende Null für gültigen String
    CharServo2[0]=Data[3];
    CharServo2[1]=Data[4];
    CharServo2[2]= 0; // Abschließende Null für gültigen String

    servo1 = atof(CharServo1); // String in Zahl umwandeln
    servo2 = atof(CharServo2);

    servo1 *= 100; // mit 100 multiplizieren um auf µsek zu kommen
    servo2 *= 100;

    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    moin,

    ich habe mich grad mal ein bisschen wegen Servo steuerung umgeschaut.
    Ich habe ein paar Sachen gefunden, aber wie kann den Servo mit den gegebenen usek steuern.
    Bei Fahrtreglern ist das mit PWM genauso, aber ich bin mir hier nicht ganz sicher ob man den auch an nen Arduino hängen kann.

    philipp

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    PWM heißt Puls Weiten Modulation: http://de.wikipedia.org/wiki/Pulsweitenmodulation . Ein Rchtecksignal mit konstanter Frequenz, (beim Arduino ca 490 Hz) hatt ein wählbares verhältnis zwischen der Ein-Zeit und der Aus-Zeit. Der risultierende mittelwert ist umso größer je größer die Ein-Zeit ist. Der Vorteil zu einer geregelten Gleichspannung ist daß dieVerlustleistung bei PWM minimal ist und nur durch die Ein- und Ausschaltverluste des Leistungstransistors gegeben sind.
    Servos und Fahrtenregler die man zB im Modelbau verwendet (hier sind Servos mit analogem Eingang gemeint) haben 3 Anschlüße: Masse, Versorgungspannung und eine Spannung die proportional zum mechanische Auslenkung ist; daß heißt bei 0 Volt ist der Servo in der einen Endstellung, bei einem Spannungswert der gleich der Versorgugsspannung ist am anderen Endwert (Vollausschlag) bei der Hälfte der Spannung auf der halben Ausschlag usw.
    Der Fartenregler ist nichts anderes als ein Leistungsschalter der aus dem Sollwert (Ansteuerungsspannung) den Motor mit PWM ansteuert.
    Der ATmega328 im Arduino2009 hat 6 PWM Ausgänge, die mit analogWrite angesteuert werden. http://arduino.cc/en/Reference/AnalogWrite . Das PWM-signal kann in 256 Stufen geregelt werden.
    Den Fahrtenregler mit dem Arduini anzusteuern müßte kein Problem sein; Schreib mir mal das Model Deines Fahrtenreglers.

    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    Ich habe grad mal versucht den Servo zu Steuern mit PC eingaben.
    Aber es geht nicht, wenn ich eine Eingabe ins Terminal mache geht er immer zu einer Seite mit voll auschlag aber er lässt sich niczht im Winkel stellen:

    #include

    Servo servo;
    int servo_normal = 89;
    int servo_wert;
    byte incomming;

    void setup()
    {
    servo.attach(2); // Servo an DigitalPin 2
    Serial.begin(9600);
    servo.write(servo_normal);

    }

    void loop()
    {
    if(Serial.available())
    {
    incomming = Serial.read();
    servo_wert = incomming * 10; //Wert aus dem Terminal mal 10

    servo.write(servo_wert);
    delay(15);
    Serial.println("Servo is moving");
    }
    }

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    Du multiplizierst den Ascii Wert des ersten Zeichens das Du übermittelst mit 10 und stellst damit den Servo.
    Ascii-Werte der Zahlen sind zwischen 48 und 57 dezimal darum stellst Du den Servo auf Werte um 500 also fast das doppelte des Vollausschlags.

    Grüße Uwe

    Antworten quote

  1. Raketopet sagt:

    hi
    ich hbae zwar noch nicht viel mit servos gemacht aber soviel ich weiss mus man den servo über PWM betreiben und der pin2 ist nicht PWM fähig.

    daher könte auch der volle ausschlag kommen den dein servo macht da du den in ja beschreibst und dan nur das letzte bit genommen wird und das ist ja endweder 1 oder 0 und somit 5v oder 0v
    das fürt dan zu einem vollen ausschlag.

    Antworten quote

  1. lord-maricek sagt:

    moin,

    der Pin 2 ist ein PWM PIN. Auf dem Nano Board steht ja auch D2.
    Ich habe eine Servosteuerung nochmal mit einem Array auf gebaut.
    Also ohne Terminal übertragung.

    int servo_positionen[] = {10,20,30... usw bis 180};

    Das hat wunderbar funktioniert.
    Kann es sein, dass ich den Byte wert vom serial.read() mit atof() erst in ein Integer konvertieren muss?

    Philipp

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    bezüglich "Kann es sein, dass ich den Byte wert vom serial.read() mit atof() erst in ein Integer konvertieren muss?":
    Entschuldige, hast Du das Listing, das ich Dir gestern geschrieben hatte, nicht gelesen?

    Raketopet hat recht; auf http://arduino.cc/en/Main/ArduinoBoardDuemilanove steht: "PWM: 3, 5, 6, 9, 10, and 11. Provide 8-bit PWM output with the analogWrite() function" und wenn Du Deinen Arduino 2009 anschaust, steht es auch draufgedruckt.

    Auf http://arduino.cc/en/Main/ArduinoBoardNano für den Nano stehen die gleichen Pins; für PWM definitiv nicht 2.

    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    sorry,
    ich bin noch nicht überall ganz durchgestiegen.
    Aber wie kommt es, dass ich an Pin 2 einen Servo in 10° Schritten betreiben kann?
    In diesem (Your text to link...) Tutorial ist der Servo auch an Pin2 angeschlossen.
    Mal ne frage: Was ist bedeutet das hier?

    map(analogValue, 0, 1023, 0, 179);

    was bedeuten die Zahlen und was muss man bei analogValue für nen Wert eintragen um einen Winkel zu errechnen?

    Philipp

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    Ok Du hast Recht in diesem Tutorial wird pin 2 als PWM-Ausgang verwendet.

    ABER (das übliche "aber" bei einem ja aber) es wird nicht die Funktion analogWrite verwendet sondern das PWM Signal wird durch periodisches, für eine bestimmte Zeit auf HIGH geschalteter Ausgang, generiert.
    Ist das gleiche wie mit digitalWrite aber auf alle Pins anwendbar, kann je nach Programmierung eien größere oder kleinere Auflösung haben (analogWrite hat 8 bit Auflösung, das heißt 256 verschiedene Werte), oder andere Frequenz, ist etwas aufwändiger in der Programmierung und bei größeren Programmen kann es leicht zu Timingproblemen kommen.

    Die Funktion Map() http://arduino.cc/en/Reference/Map Rechent in Deinem Beispiel eingelesenen Wert eines Sensors (der durch die Meßgröße seinen Widerstand ändert) in eine Augangswert für die Steuerspannung des Servos.

    Im Beispiel 4.1 wird die analoge Spannung an A0, welche von schätzungsweise 0,5 V bis 5 V geht ( wegen des zusätzlichen Widerstands von 10 kOhm) in Pulsweiten von 500µsek bis zu 2500µsek = 2,5msek umgerechnet bei einer Periodendauer von 20msek (das heißt ein Verhältnis von Ein zu Aus von 2,5% bis 12,5% Ein-Zeit)

    Im Beispiel 4.2 wird die Servo Library verwendet. Dies ist ein Teil des IDE 018.
    Der Sensorwert wird in einen Winkel von 0 bis 1879 grad umgerechnet ( von 0 bis Vollausschlag)und das Servo angesteuert. Mit der Library kannst Du an fast jedem digitalen Ausgang ein Servo ansteuern; an 12 von den 14 digitalen Ausgängen.

    Eine Vorschlag: wenn Du Fragen stellst bitte auch das Programm mitschicken des Du verwendest.

    Grüße Uwe

    Antworten quote

  1. chrimbo sagt:

    ich hab jetzt den ganzen fred nicht gelesen, aber wollte noch meinen Senf dazugeben :)
    falls nochmal jemand auf die idee kommt, Serielle daten zu speichern
    Stichwort Ringspeicher. In der Regel das Mittel der Wahl, wenn es um den UART geht

    gruß
    Ich^^

    Antworten quote

  1. lord-maricek sagt:

    moin,

    eine Frage nochmal, ich schreibe mir grade ne GUI zum Servo steuern. In Csharp kann man in einem Byte 255 Zeichen speichern. Müsste es dann nicht möglich sein, dass wenn ich jetzt ein Byte mit dem Wert 10 schicke, dass ich dann dieses Byte ganz einfach mit byte income = Serial.read() abfragen kann ohne lange schleifen?

    Philipp

    Antworten quote

  1. Raketopet sagt:

    eigentlich schon
    nur meine ich das wen man mit readbyte arbeitet das ganze dan als 8bit block verarbeitet wird.
    also das du dan die werte nucht mit 10(zehn) überbrüfst sondern mit dem binären wert 1010.

    MFG Raketo

    Antworten quote

  1. uwe sagt:

    hallo Philipp,

    ja kannst Du.
    Das Problem ist, wenn Du einen Wert über Tastatur und Terminal des IDE eingibst, dann werden die ASCII Code der Zeichen übertragen und nicht der Dezimalwert der Tastenkombination.
    Wenn Du die Tasten "1" "0" "enter" drückst dann wird die ASCII Werte der 3 Tasten über RS232 übertragen (dezimal: 49, 48, 13). Wenn Du die Zahlenwerte von einem anderen Programm schicken kannst, dann geht natürlich auch einfach den Dezimalwert 10 zu schicken.

    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    Moin,
    ich hatte das ja schon so hinbekommen, dass ich von einem Externen Programm mit Slider daten senden konnte und damit den Servo gesteuert. Nun habe ich mir überlegt mal mit Processing ein paar Daten zu senden und die dann an den Servo zu übergeben:
    Processing:

    import processing.serial.*;
     
    Serial sp;
     
    void setup()  {
      sp = new Serial(this, "COM3",9600);
      send();
      delay(2000);
      send();
    }
     
    void draw()  {
    }
     
    void send()  {
      sp.write((byte)10);
      delay(1000);
      sp.write((byte)20);
      delay(1000);
      sp.write((byte)30);
      delay(1000);
      sp.write((byte)40);
      delay(1000);
      sp.write((byte)50);
      delay(1000);
      sp.write((byte)90);
      delay(1000);
      sp.write((byte)130);
      delay(1000);
      sp.write((byte)180);
      delay(1000);
    }

    Arduino:
    #include <Servo.h>
     
    int inbyte;
    int po;
     
    Servo servo;
     
    void setup()  {
      servo.attach(2);
      Serial.begin(9600);
      servo.write(90);
    }
     
    void loop()  {
      if(Serial.available())  {
        inbyte = Serial.read()- '0';                                                   
        servo.write(inbyte);
      }
    }

    Das uploaden zum Arduino funtzt wunderbar, aber wenn ich dann das Processing Programm starte passiert garnichts. Nur die L SmdLED leuchtet auf und die RX Led blinckt kurz.

    Was ist falsch?

    Philipp

    Antworten quote

  1. uwe sagt:

    Hallo Philipp

    Daß das RX led alle Sekunde mal kurz aufleuchtet ist richtig.
    Hast Du versucht die inbyte- Werte auf der RS232 Schnittstelle zurückzuschicken und anzeigen zu lassen?
    böse frage: Der Servo ist am pin 2 angeschlossen?
    Schreib einen sketch der den Servo ansteuert und zwischen 2 Werten wechselt.
    zB;
    servo.write(10);
    delay(2000)
    servo.write(170);
    Grüße Uwe

    Antworten quote

  1. lord-maricek sagt:

    moin, der Servo ist angeschlossen und geht. Habe ich mit dem Example sweep aufprobiert. Die RX Led leuchtet nur einmal kurz auf wenn ich das Processing Programm starte und dann macht sie garnichts mehr.

    Antworten quote

  1. uwe sagt:

    Hallo Philipp
    Dan tippe ich auf einen Fehler im Ansteuerungsprogramm am PC oder falsche Com - Schnittstelle.
    Grüße Uwe

    Antworten quote

  1. Peter Ikier sagt:

    Hallo Philipp,

    in deinem Processing-Programm sendest du ein Byte mit Werten von 10, 20, 30,...
    dieses Byte empfängst du auf der Arduino-Seite mit "Serial.read()".
    Erklär mir bitte mal, warum du davon dann das Zeichen '0' (Dezimalwert ist 48) abziehst. Dadurch kriegst du Werte von -38, -28, -18, ...

    Gruß
    pi

    Antworten quote

  1. uwe sagt:

    Hallo Peter
    Das ist eine gute Frage.
    Philipp schreibt aber, daß das RX led nur 1x am Anfang blinkt.
    Grüße Uwe

    Antworten quote

  1. Peter Ikier sagt:

    OK, kreisen wir das Problem ein.

    @Philipp: Kannst du denn dein Programm von der seriellen Konsole in der IDE ansteuern?
    Sende mal: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", das sind die Dezimalwerte 65 und 123.
    Wenn der Servo damit hin- und hergeht weißt du dass dein Arduinoprogramm funktioniert.
    Die vielen Zeichen sorgen dabei dafür, dass du dem Servo etwas Zeit lässt zu reagieren.
    Bei 9600 BPS sendest du etwa 1000 Zeichen pro Sekunde, deswegen musst du mehrfach dasselbe Zeichen senden um in beobachtbare zeiträume zu kommen.

    Achtung: Am Ende einer solchen Übertragung wird immer das Zeichen der Eingabetaste gesendet, das ist der Dezimalwert 19, dei Servo fährt also dann von 123 auf 19 zurück.

    Gruß
    pi

    Antworten quote

Kommentar hinzufügen

Der Inhalt dieses Feldes wird nicht öffentlich zugänglich angezeigt.
Array
CAPTCHA
Diese Frage hat den Zweck zu testen, ob man ein menschlicher Benutzer ist und um automatisierten Spam vorzubeugen.
Mittela_ter:
Inhalt abgleichen