Nutzung der StandardCplusplus-Lib

Moin, ich bins mal wieder :slight_smile:

Da ich in der Sprache C++ doch etwas bewanderter bin, als in reinem C (mit Arduino-Dialekt), habe ich nach ner Möglichkeit gesucht, die standard library irgendwie zu nutzen (Container und so). Glücklicherweise hatte dieses Bedurfnis anscheinend schon jemand vor mir, sodass ich auf diese Lib gestossen bin: GitHub - maniacbug/StandardCplusplus: Standard C++ for Arduino (port of uClibc++).

Die sah mir recht praktisch aus und hat alles, was ich im Moment brauche. Passt also.

Als es nun ans einbinden ging, wurde das ganze schon etwas schwieriger. Wo genau gehört der Ordner nun hin? Ein kurzer Blick in die Readme sagt: Im Sketchbook muss es nen Ordner mit dem Namen "libraries" geben. Bei mir war dies leider nicht der Fall. Na gut, der ist schnell erstellt, und der StandardCplusplus-Ordner war schnell reinkopiert.

Doch die Ernüchterung folgte sofort, als ich eines der beiden Beispiel-Programme (string_vector) testen wollte:

#include <StandardCplusplus.h>
#include <serstream>
#include <string>
#include <vector>
#include <iterator>

using namespace std;

// <iostream> declares cout/cerr, but the application must define them
// because it's up to you what to do with them.
namespace std
{
  ohserialstream cout(Serial);
}

vector<string> strings;

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

  strings.push_back("Hello,");
  strings.push_back("world!");
  copy(strings.begin(),strings.end(),ostream_iterator<string>(cout," "));
  cout << endl;
}

void loop(void)
{
}

// vim:cin:ai:sts=2 sw=2 ft=cpp
string_vector:12: error: 'ohserialstream' does not name a type
string_vector:15: error: expected constructor, destructor, or type conversion before '<' token
string_vector.cpp: In function 'void setup()':
string_vector:21: error: 'strings' was not declared in this scope
string_vector:23: error: 'ostream_iterator' was not declared in this scope
string_vector:23: error: 'string' was not declared in this scope
string_vector:23: error: 'cout' was not declared in this scope
string_vector:23: error: 'copy' was not declared in this scope
string_vector:24: error: 'endl' was not declared in this scope

Anscheinend wurde also keine der Dateien, die eingebunden werden sollten, gefunden.

Ich gehe davon aus, dass ich den StandardCplusplus-Ordner an den falschen Ort kopiert habe. Hier gibts bestimmt jemande, der die Lib auch nutzt...Wo ist der richtiger Ort für den Ordner? Habe ich irgendwas falsch gemacht?

Ich hoffe, dass mir auch diesesmal wieder geholfen wird :smiley:
Valentin

Da ich in der Sprache C++ doch etwas bewanderter bin, als in reinem C (mit Arduino-Dialekt)

Die Arduino-IDE ist reines C++, was Du ansprichst, ist die STL (Standard Template Library), die heute normalerweise bei einer C++-Entwicklungsumgebung integriert ist, aber nicht wirklich Teil der Sprache selbst. Dass es sich bei dem "Arduino-Dialekt" (ist eigentlich auch nur eine Library und etwas Wrapper-Code) um C handelt, ist ein falsches Gerücht, das sich aber scheinbar hartnäckig zu halten scheint.

Die STL birgt insofern Probleme, als dass sie nicht wirklich brauchbar im Embedded-Bereich ist. Microcontroller haben im Gegensatz zu heutigen PCs keine Speicher-Verwaltungs-Chips (MMU), die eine logische Abstraktionsschicht über den physischen Speicher legen und somit Speicherbereiche anders ansprechen können, als nur über die direkte physische Adresse (so wird auch virtueller Speicher erst möglich).

Auch ist der Speicherausbau eines normalen Microcontrollers (2kB beim UNO) nicht im Entferntesten vergleichbar mit dem heutiger PCs (Faktor 106 und mehr). Die String-Klasse in der Arduino-IDE (bzw. Library) ist aus diesem Bereich entlehnt und sie ist wahrscheinlich das grösste Ärgernis der ganzen IDE. Ständige Neu-Allokation von Speicher fragmentiert den zur Verfügung stehenden Teil so schnell, dass kein vernünftiges Arbeiten möglich ist. Jeder erfahrende Arduino-Programmierer wird Dir deshalb mit Sicherheit von der String-Klasse abraten.

Da fast alle anderen Bestandteile der STL mit ähnlichen Problemen in der Embedded-Programmierung verbunden sind, wird sie normalerweise nicht eingesetzt. Dies hat nichts mit der Sprache, sondern mit der Eignung zu tun. Du kannst für den Arduino also sehr wohl objekt-orientiert (mit C++-Syntax) programmieren, aber solltest die Resourcen-Beschränkungen immer im Hinterkopf haben.

Wenn Du C++ mit all den neuen Libraries und Sachen wir Templates o.ä. im Embedded-Bereich verwenden willst, musst Du eine Leistungsklasse hochsteigen und wirst wahrscheinlich bei einem Linux-System wie dem RaspberryPi landen. Mit den dort vorhandenen 256MB RAM kannst Du all die netten STL-Dinge einsetzen, ohne gleich an der Speicherdecke anzustossen.

pylon:
Die Arduino-IDE ist reines C++, was Du ansprichst, ist die STL (Standard Template Library), die heute normalerweise bei einer C++-Entwicklungsumgebung integriert ist, aber nicht wirklich Teil der Sprache selbst. Dass es sich bei dem "Arduino-Dialekt" (ist eigentlich auch nur eine Library und etwas Wrapper-Code) um C handelt, ist ein falsches Gerücht, das sich aber scheinbar hartnäckig zu halten scheint.

Wieder was gelernt :smiley:

Die STL birgt insofern Probleme, als dass sie nicht wirklich brauchbar im Embedded-Bereich ist. [...]

Das heisst, dass sich Container wie z.B. std::vector oder std::map nicht nutzen lassen? Wäre das nicht etwas komisch, dass sich die library dann überhaupt gibt? :smiley:

Valentin

Das heisst, dass sich Container wie z.B. std::vector oder std::map nicht nutzen lassen? Wäre das nicht etwas komisch, dass sich die library dann überhaupt gibt?

Nur weil etwas existiert, ist es noch lange nicht wirklich brauchbar. Die String-Klasse ist auch in der IDE vorhanden, sollte aber nicht verwendet werden, weil sie mehr Probleme bereitet, als sie löst. Zudem habe ich nicht gesagt, dass sie sich nicht nutzen lassen, ich sage, ich rate von der Benutzung (natürlich von einigen sehr, sehr speziellen Fällen abgesehen) ab.

Ich denke, Dein sehr kurzes Beispielprogramm würde man auch zum kompilieren und evtl. sogar laufen bringen, aber in einem realen Arduino-Programm würde ich es nicht einsetzen.

Gut, dann versuche ich etwas weiter auszuholen, vlt. kann man mir dann besser helfen, bzw. verraten, wie man mein Problem umgeht.

Ich schreibe momentan an einem Framework, womit ich den Arduino vom Pc aus steuern kann. Ich sage dem Board also über den Serial-Anschluss, an welchen Pin wieviel Strom gelegt werden soll. Auslesen, an welchem Pin wieviel Strom liegt ist natürlich auch möglich. Das sieht dann so aus:

#include "Board.h"

#include <iostream>

int main()
{
	Ard::Board mega("Com2");

	Ard::OutputPin o(13, Ard::DIGITAL, mega.GetSerial());
	mega.AddPin(o);

	Ard::InputPin i(0, Ard::ANALOG, mega.GetSerial());
	mega.AddPin(i);

	while(true)
	{
		auto k = i.ReadVoltage();
		o.SetVoltage(k);
	}
}

Nun gab ich mich natürlich nicht damit zufrieden, einfach nur Spannungen an Pins zu legen. Ich will auch Servos/Stepper etc. ansteuern können. Da ich es nun nicht unbedingt als nötig ansehe, die Servo-Lib neu zu implementieren, sieht die Ansteuerung von Servos intern so aus:

Servo s; // global
void loop()
{
  if(operation == servo)
  {
    s.attach(pin);
    s.write(map(value, 0, 255, 0, 180));
  }
}

Diese Methode funktioniert mit nur einem angesteuerten Servo sehr gut. Sobald aber mehrere Servos angeschlossen sind, kann man das vergessen (was eigentlich auch abzusehen war). Dieses Problem wollte ich nun umgehen, indem ich ne map habe, und teste, ob der Servo bereits "existiert", wenn nicht, dann wird ein neuer hinzugefügt. Wenn ja, dann wird der bestehende Servo genommen, und auf die neue Position gesetzt.

Jetzt habe ich aber keine map zur Verfügung. Was soll ich machen? Klar, ich könne das ganze mit nem Array in Übergrösse umgehen, elegant ist aber was anderes.

Könnt ihr mir da aushelfen? :smiley:

Valentin

Dieses Rad wurde schon mehrfach erfunden. Google mal nach "Arduino Firmata" und "Arduino Bitlash" :wink:

Hm, ich sehe bei beidem nicht so ganz, inwiefern mir die beiden Stichworte helfen sollen. Auf interessante Ergebnisse bin ich trotzdem gestossen :D.

Arduino Firmata sieht mir eher nach nem Protokoll aus, bzw. ner Library auf Board-Seite. Auch sehr interessant, dennoch ist das Serialisieren und versenden nicht das Problem.

Arduino Bitlash sieht auch ganz interessant aus, ist aber auch nicht direkt was ich suche :S.

Valentin

//edit: Ich sehe gerade, dass der Sourcecode von Bitlash doch hilft. Die haben das ansteuern von Servos also so implementiert, dass sie einfach zu beginn ein Array mit der maximalen Anzahl an nutzbaren Servos erstellen. Das war aber eigentlich das, was ich vermeiden wollte :D.

Geht das wirklich nicht eleganter?

Elegant ist meistens nur von aussen. Es läuft im Endeffekt immer auf die Speicherreservierung hinaus.
Entweder du schnappst dir den maximal möglichen Bereich oder du baust eine Erweiterungsroutine ein.
Wenn deine Routine mehr Platz/Rechenzeit verbraucht als der maximal nötige Speicherbereich, dann hast
du zu viel optimiert. Und die zuvor gedachte Eleganz ist auf ein Mal futsch.