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.