Werte aus dem Arduino weiterverarbeiten in C++ (Visual Basic)

Hallo liebes Forum,

kurz Vorstellung:

C++ Grundkenntisse,
Matlab ausreichende Kenntnisse,

was habe ich:

Einen Arduino Mega mit einem Dehnungsmesstreifen angeschlossen

Wie weit bin ich gekommen:

Daten die der DMS sendet kommen im Seriellen Monitor an und werden korekt angezeigt (Hoffe das die Werte auch wirklich stimmen :slight_smile: )

Was will:

Ich würde gerne die Daten die der Arduino sendet, weiterverabreiten. Was heist das genau?:

Die Daten die vom DMS über den Arduino an den PC geschickt werden mit C++ so weiterverarbeiten, dass ich später mit den empfangenen Daten alles machen kann, was mir MS Express 2013 erlaubt (Graphische Darstellung, Koordinatensystem erstellen, Programme aufrufen, falls ein bestimmter Wert vom DMS angekommen ist usw.)

Nun was habe ich bis jetzt gemat:

Eine Verbindung vom Arduino zu MS Expsress sowie zu Atmel Studio konnte ich bislang leider nicht erreichen. Mein Ziel war mit den Befhelen von der Arduino Bibliothek die Werte austzullesen, diese zu definieren und einfach in C++ diese Daten weiterzuverarbeiten.

Da ich ein blutuger Anfänger bin was C++ anbelangt habe ich eine Verständnisfrage:

Warum kann die Arduinosoftware keine C++ Befehle (so wie sie in MS Express oder Atmel Studio eingegeben werden) nicht verarbeiten? Allein die Funktion cin oder cout ist hierbei nicht möglich?

Nun zu meiner Frage: Wie bekomme ich es hin das ich den Arduino in C++ programmieren kann, sodass ich die Befehle, die mir in MS Express bekannt sind, eingeben kann?

Wäre wirklich dankbar für eine Hilfestellung. ICh benötige kein Codes hier oder ähnliches lediglich einen Hinweis, wie ich es Anstellen kann, das der Arduino das macht, wie ich es in MS Express eingeben kann.

Danke im Voraus!

Gruß

Nico

Befasse dich erst mal mit den Arduino Grundlagen und arbeite ein paar Beispiele aus dem Bereich Kommunikation durch. Was du machen willst, geht natürlich, aber dir fehlen klar die elementarsten Kenntnisse.
Anderseits sagst du dass die Daten im Serial Monitor ankommen. Also liegt dein Fehler auf der PC Seite. Um in .NET Serial Daten zu empfangen gibt es die SerialPort Klasse:

Da stehen Beispiele dabei wie das geht. Vor allem das hier:

ReadLine() ist auch sehr praktisch um eine ganze Zeile einzulesen die mit einem Linefeed und/oder Carriage Return abgeschlossen ist:

Auf dem Arduino gehen Dinge wie die Standard Template Library und I/O Streams nicht. Punkt. Vieles andere geht dagegen. Auch komplexere Dinge wie Templates oder diverse C++11 Features (wenn man die Config Dateien anpasst).

Höre auf dich strikt auf die Standard C++ Syntax festzulegen. Der Arduino hat eine eigene API. Statt dem hier:

cout << "test" << endl;

einfach das:

Serial.println("test");

Das nervt wenn man Ausgaben zusammenstückeln muss, aber dazu gibt es das:
http://arduiniana.org/libraries/streaming/
Und schon hat man einfache C++-artige Output Streams

Komplexere I/O Streams mit dem auch die C++ Stream Formatierung funktionieren gibt es in der SdFat Klasse (da geht auch Input):

Was die Arduino-seitige Behandlung von Strings betrifft. Da nimmt man nicht C++, sondern C. Auf dem Arduino gehen die meisten der Standard String und Konvertierungs-Funktionen aus string.h und stdlib.h. Also z.B. strtok() um Strings zu splitten oder atoi() für Integer und atof() für Floats. Aber du willst wohl erst mal nur Daten an den PC schicken.

Ansonsten geht das alles. Ich habe mit dem Arduino und C# Zwei-Wege-Kommunikation mit 500.000 Baud am Laufen. Anweisungen und Daten werden in beide Richtungen gesendet und geparst.

C# ist hier übrigens weit besser und von der Syntax her ähnlich wie C/C++. Wenn du nicht schon Visual Basic kannst, sondern erst noch eine Sprache für .NET lernen musst, fang lieber mit C# an.

Hi Faraday,

erstmal vielen Dank für die ganzen Tipps und Links!

Die Infos waren sehr nützlich. Auf den ersten Blick sehe ich, dass noch ein schönes, knackiges stück Arbeit vor mir liegt, sehr gut.

Mal schaune wie weit ich kommen werde, amsonsten

Gruß

Nico

Der SerialDataReceived Event Handler ist eigentlich der Standard Weg. Das sollte erst mal gehen.

Ich habe aber bei mir gemerkt dass er viel zu unzuverlässig ist. Keine Ahnung woran das liegt, da er ihn einer andren Anwendung wo ich Daten mit Bluetooth übertragen habe problemlos funktioniert hat.

Eine andere Option ist daher einfach zu Pollen. Wenn die Verbindung gestartet wird, startet man auch einen Timer (C#):

private SerialPort _serialPort;
private System.Timers.Timer _timer;

public override void Connect()
{
  try
  {
      _serialPort = new SerialPort(_comPort, _baudRate, Parity.None, 8, StopBits.One);
      _serialPort.NewLine = "\r\n";
      _serialPort.Open();

      _timer = new System.Timers.Timer(100);
      _timer.Elapsed += DataReceived;
      _timer.Start();
  }
  catch (InvalidOperationException)
  {
      //Fehler Behandlung. z.B. Anzeige auf GUI
  }
}

Dadurch wird alle 100ms DataReceived() aufgerufen. Und dort fragt man einfach ob ob Daten da sind:

private void DataReceived(Object source, ElapsedEventArgs e)
{        
  try
  {
     while (_serialPort.BytesToRead > 0)
     {
        string str = _serialPort.ReadLine();

        //hier dann etwas mit dem String machen

     }
  }
  catch(Exception ex)
  {
  }
}

Das sieht zwar primitiv aus, aber funktioniert sehr, sehr zuverlässig und reagiert vor allem viel schneller auf eintreffende Daten als der normale EventHandler. Die ich NewLine = "\r\n" gemacht habe muss man dann bei jedem Datentelegramm hinten in CR/LF anhängen. Das macht Serial.println() von sich aus. Oder man verwendet << endl bei der Streaming Library.

Noch was:
Wenn du eine Windows Forms Anwendung hast, musst du wegen dem Thread Zugriff aufpassen. Wenn du aus dem Serial EventHandler direkt auf eine GUI Komponente zugreifst, gibt es Mecker. Also immer mit BeginInvoke() arbeiten:

      public void TextBoxPrint(string text)
      {
         if (communicationOutput.InvokeRequired)
         {
            communicationOutput.BeginInvoke((MethodInvoker)delegate
            {
               communicationOutput.AppendText(text);
            });
         }
         else
         {
            communicationOutput.AppendText("\n");
         }
      }

Hier für eine RichTextBox namens communicationOuput, aber das geht genauso mit anderen Komponenten wie Labels (um z.B. die Farbe zu ändern):

      private void UpdateLabel(Label label, Color color)
      {
         if (label.InvokeRequired)
         {
            label.BeginInvoke((MethodInvoker)delegate
            {
               label.BackColor = color;
            });
         }
         else
            label.BackColor = color;
      }

Hallo,

sobald ich neue Ergebnisse bekommen habe, werde ich sie mal hier Posten.

Ich habe feststellen können, dass es nur "dürftige" Informationen zum Thema "Arduino Datenverarbeitung" im Internet gibt.

Also falls jemand auf dasselbe Problem kommen sollte, kann er sich auch gerne bei mir melden, aber jetzt erstmal an die Arbeit.

Gruß
Nico
PS: Es besteht auch ein Toolpackage von Matlab für den Arduino. Was da aber man alles machen kann weiß ich leider nicht, da muss ich mich erstmal schlau machen.

nidgo:
Ich habe feststellen können, dass es nur "dürftige" Informationen zum Thema "Arduino Datenverarbeitung" im Internet gibt.

Das liegt wohl eher daran, dass alles, was nach der seriellen Übertragung geschieht, nicht mehr mehr mit dem Arduino zu tun hat. Evtl. etwas großflächiger suchen. Den Suchbegriff Arduino kannst du dann auch weglassen.

Woher die seriellen Informationen kommen ist doch vollkommen egal. Ob das jetzt ein Arduino, irgendein anderer Mikrocontroller, ein Bluetooth Dongle, ein anderer PC oder irgendein Messgerät mit RS-232 Schnittstelle ist, die Vorgehensweise ist genau die gleiche.

Zur seriellen Schnittstelle in .NET gibt es massenweise Informationen und Code im Internet. Die Doku von Microsoft zu .NET ist auch sehr gut. Du musst nur Konsolen-Anwendungen von Windows Forms unterscheiden. Der meiste Beispiel Code auf MSDN ist für Konsolen Anwendungen. Aber das lässt sich auch sehr leicht auf GUIs übertragen (siehe oben wegen dem Thread Zugriff).
Ein Problem ist wie gesagt dass die SerialPort Klasse generell nicht sehr gut ist. Das liest man immer wieder mal. Wenn es Probleme mit der Zuverlässigkeit des Event Handlers gibt, ist daher die Timer Variante zu empfehlen. Aber grundlegend dass man überhaupt mal was empfängt geht es auch normal über den EventHandler.

Wenn du immer noch bei .NET bist, dann lass den Arduino erst mal ständig etwas Text senden. Und gib diesen Text dann entweder in einem Konsolen Fenster oder bei einem GUI auf einer RichTextBox aus. Ohne da irgendwie groß Daten zu verarbeiten. Wenn das mal geht kann man sich steigern.

Hallo Leute,

kurzer Stand der Dinge.

Daten kommen endlich am PC an!
Also falls jemand mit C++ arbeiten möchte:

-Arduino über COM3 am PC verbunden
-Am Arduino ein DMSensor auf A0 angeschlossen
-Auf dem Arduino folgender Code:

http://arduino.cc/en/tutorial/graph

-Code für Visual Basic

Die Daten,die ankommen weisen die gleichen Werte und Struktur auf, wie wenn ich Sie auf dem Arduino anzeigen lassen über den Seriellen Monitor. Also die erste Stuffe des Datenempfangs sind nun vollbracht.

Nächste Aufgabe wird es jetzt sein, wie bereits oben von Serenifly mir empfohlen wurde, über die Timer Variante weiterzuarbeiten. Da es zu Problemen mit der o.g. Methode kommen kann.

Ich gebe Bericht wie weit ich gekommen bin.

Gruß
Nico

nidgo:
-Code für Visual Basic

Das ist Visual C++! Nicht Visual Basic. Ein großer Unterschied.

Man kann in .NET mit C#, C++ oder VB programmieren (oder auch F#). Die Sprachen benutzen alle die gleichen Klassen und Ressourcen und werden in den gleichen Bytecode für die Common Language Runtime übersetzt.

Der Code ist übrigens für eine Konsolen Anwendung. Bei einem GUI hat man keine while-Schleifen, sondern alles ist Event-gesteuert.