Forum: PC-Programmierung [C++] Paralleler Zugriff auf Variable und einige Fragen zu C++ <=> Homepage


von Thomas P. (tommy2002)


Lesenswert?

Hallo,

bevor ich zu meinem Problem komme, möchte ich euch schildern was ich 
überhaupt mache.
Ich habe mit C++ eine Software für das Raspberry Pi geschrieben. Diese 
ist wesentlich in zwei Funktionen unterteilt:

1. Eine Funktion regelt den kompletten I²C verkehr, an dem einige 
Sensoren und DAC's hängen.
D.h. I²C auslesen und den Wert in eine Membervariable einer Klasse 
speichern, oder Membervariable auslesen und über I²C an DAC schreiben.
2. Die andere Funktion bietet eine Ausgabe der aktuellen Sensorwerte auf 
der Konsole. Das Programm läuft auch so, wie ich es mir vorstelle.

Alle Werte werden grundsätzlich in Membervariablen von Klassen 
gespeichert, dem Thread habe ich die Referenz der Klassen übergeben.

Diese beiden Funktionen sind durch Threads voneinander entkoppelt und 
laufen völlig unsynchronisiert. Dies würde ich auch gerne so 
beibehalten.



Meine Frage ist nun: Was passiert, wenn ich in der einen Funktion z.B. 
eine Variable lese und die andere Funktion zu dem selben Zeitpunkt die 
selbe Variable beschreiben möchte?
Ist dies theoretisch überhaupt möglich, die CPU arbeitet doch sowieso 
alles zyklisch ab?


Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die 
Variablen auf einer Homepage auszugeben? Mir geht es hier viel mehr um 
die Schnittstelle. Für C++ gibt es eine schöne SQL API, jedoch halte ich 
es ein wenig übertrieben für ca. 10 Werte eine ganze Datenbank 
anzulegen.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Thomas P. schrieb:
> Ist dies theoretisch überhaupt möglich, die CPU arbeitet doch sowieso
> alles zyklisch ab?

ja ist es, du musst dafür sorgen das das nicht passiert. Dafür kann man 
z.b. eine Mutex verwenden.

> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben?
ich habe meinem Programm einfach http beigebracht. Dann kann ich sehr 
einfach mit Javascript auf mein Programm zugreifen.

Wenn du die werte nicht speichern musst, dann ist das der einfachste 
Weg. Wenn du sie eh irgendwo speichern musst, dann würde ich es über 
eine SQL-DB machen.

von Mark B. (markbrandis)


Lesenswert?

Thomas P. schrieb:
> Meine Frage ist nun: Was passiert, wenn ich in der einen Funktion z.B.
> eine Variable lese und die andere Funktion zu dem selben Zeitpunkt die
> selbe Variable beschreiben möchte?
> Ist dies theoretisch überhaupt möglich, die CPU arbeitet doch sowieso
> alles zyklisch ab?

Wenn verschiedene Prozesse auf dieselbe Ressource zugreifen (z.B. auf 
eine Datei, auf einen Speicherbereich), dann braucht man Mechanismen zur 
Synchronisierung. Die bekommt man vom Betriebssystem. Stichworte dafür 
sind unter anderem Semaphoren und Mutex.

> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben? Mir geht es hier viel mehr um
> die Schnittstelle. Für C++ gibt es eine schöne SQL API, jedoch halte ich
> es ein wenig übertrieben für ca. 10 Werte eine ganze Datenbank
> anzulegen.

Wenn Du die Variablen nur einmal anzeigen und danach "vergessen" willst, 
musst Du sie auch nicht in eine Datenbank stecken. Ein Webserver kann 
seine Daten ja auch von woanders her bekommen, z.B. über eine 
Ethernet-Verbindung.

Was für einen Webserver verwendest Du?

von foo (Gast)


Lesenswert?

Hallo,

für dein erstes Problem solltest Du dir einmal Mutex angucken.

https://de.wikipedia.org/wiki/Mutex

Dein Beispiel liest sich so, als wären die Zugriffe nicht zu häufig und 
auch nicht besonders lang, da kann man auch ein sehr einfaches 
busy-waiting selbst implementieren.
1
// Memebervariable
2
bool busy = false;
3
4
...
5
6
void machwas() {
7
  while(busy);
8
  busy = true;
9
  // irgendwelche Operationen
10
  busy = false;
11
}

Zum zweiten: Wie wäre es mit Sqlite?

von Eric B. (beric)


Lesenswert?

Thomas P. schrieb:
> Meine Frage ist nun: Was passiert, wenn ich in der einen Funktion z.B.
> eine Variable lese und die andere Funktion zu dem selben Zeitpunkt die
> selbe Variable beschreiben möchte?

Chaos!

> Ist dies theoretisch überhaupt möglich, die CPU arbeitet doch sowieso
> alles zyklisch ab?

Das ist sehr wohl möglich. Die CPU kann zwar nur 1 Ding gleichzeitig 
machen (wenn's nicht ein multi-Core CPU ist), aber Zugriff auf Variablen 
ist nicht immer atomär. Um z.B. eine Variable um 1 zu erhöhen sind u.U. 
3 Schritte notwendig:

1. Lese variable aus dem RAM
2. Inkrementiere den Wert
3. Schreibe neue Wert zurück.

Zwischen jeden von diesen SChritten kann dein Thread unterbrochen werden 
von anderen Threads. Abhilfe schaffen hier Mutexes oder Semaphoren.

> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben?

Mit einem Webserver.

> Mir geht es hier viel mehr um
> die Schnittstelle. Für C++ gibt es eine schöne SQL API, jedoch halte ich
> es ein wenig übertrieben für ca. 10 Werte eine ganze Datenbank
> anzulegen.

SQLite vielleicht? oder schreibe die Werte einfach in einer Textdatei 
und lese die im Webserver aus.

von (prx) A. K. (prx)


Lesenswert?

Thomas P. schrieb:
> Meine Frage ist nun: Was passiert, wenn ich in der einen Funktion z.B.
> eine Variable lese und die andere Funktion zu dem selben Zeitpunkt die
> selbe Variable beschreiben möchte?

Wenn eine skalare "volatile" Variable maximal 32 Bits gross ist und 
nicht mit Gewalt misaligned wurde, dann sind einzelne lesende und 
schreibende Zugriffe des ARM im RasPI atomar. In dem Fall ist es 
möglich, die Variable ohne Mutex zu lesen.

Voraussetzung dafür ist aber, dass der schreibende Thread immer korrekte 
Werte und keine unkorrekten Zwischenzustände schreibt und der lesende 
Thread nie schreibt.

: Bearbeitet durch User
von Thomas P. (tommy2002)


Lesenswert?

Danke erst einmal für die vielen Antworten. Das ganze ist übrigens eine 
Studienarbeit. Letztendlich soll es ein Labornetzteil werden, welches 
man über ein Webinterface ansteuern kann. Momentan arbeite ich an dem 
Prototypen und befasse mich mit der Regelungstechnik. Parallel dazu 
plane ich das Webinterface.

Mark B. schrieb:
> Was für einen Webserver verwendest Du?

Ich wollte Apache als Webserver nutzen. Würde es jetzt auch mit einer 
Datenbank lösen. Fande dies nur ein wenig wie mit Kanonen auf Spatzen 
geschossen, bzw. war dies die Aussage von meinem Betreuer. Dem konnte 
ich aber zustimmen.
Der Webserver, sowie die ganze Software läuft auf dem Raspberry Pi

Programmieren wollte ich das ganze mit HTML, CSS, PHP, SQL, Javascript

Ich werde diese Thematik wohl nochmals ansprechen, da ich die C++ API 
sehr angenehm finde, so müsste ich das Rad auch nicht neu erfinden. Dann 
wohl im Zusammenhang mit Sqlite.


Aber nochmal zurück zu der Synchronisierung. Etwas verstehe ich noch 
nicht so ganz
Ich meine, die CPU macht doch nichts anderes als auf den Adressbus des 
RAM die Adresse zu schreiben, dann "CHIP ENABLE" auf "1" setzen und 
schließlich den Wert vom Datenbus lesen. Anschließend wieder "CHIP 
ENABLE" auf "0". Dazwischen wird die CPU doch nicht unterbrochen?
Also, sofern ich doch wirklich nur einen Kern nutze kann doch eigentlich 
nichts passieren?

Ich meine klar, die Abarbeitung der beiden Threads wäre vollkommen 
zufällig. Aber das wäre für meinen Fall nicht schlimm, denn es ist nur 
eine Anzeige. Bei Bedarf habe ich geplant über die Konsole mit
1
std cin<< ...
 einen Wert für die DAC zu übergeben. Dies aber wirklich sehr selten.
Deswegen geht es mir wirklich nur darum, was passiert wenn z.B. zwei 
Kerne in dem selben Moment auf eine Ram Adresse zugreifen. Normal müsste 
dies doch aber sowieso verhindert werden oder nicht?

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Thomas P. schrieb:
> Ich meine, die CPU macht doch nichts anderes als auf den Adressbus des
> RAM die Adresse zu schreiben, dann "CHIP ENABLE" auf "1" setzen und
> schließlich den Wert vom Datenbus lesen. Anschließend wieder "CHIP
> ENABLE" auf "0". Dazwischen wird die CPU doch nicht unterbrochen?

Das ist zwar etwas arg vereinfacht dargestellt, aber im Prinzip korrekt, 
solange es sich um Datentypen handelt, die vom Compiler als ein einziges 
Speicherwort behandelt werden, und so lange nur ein Prozessorkern im 
Spiel ist.

Bei einem AVR an Stelle des ARM ist freilich bereits ein 16-Bit Datentyp 
nicht mehr atomar, weil 2 unterbrechbare Zugriffe erfolgen.

> Also, sofern ich doch wirklich nur einen Kern nutze kann doch eigentlich
> nichts passieren?

Es sei denn zu baust beispielsweise sowas:
  var <<= 8;
  var |= c;
Denn dann entsteht ein ungültiger Zwischenzustand.

Bei Verwendung mehrerer Kerne lohnt sich ein Blick in das von dem 
Prozessor und dem entsprechenden Speicherbereich definierten "memory 
consistency model". Weil dann deine Vereinfachung nicht mehr greift - es 
gibt dank der Caches nicht nur eine Speicherstelle für eine bestimmte 
Adresse, sondern potentiell mehrere.

: Bearbeitet durch User
von Daniel A. (daniel-a)


Lesenswert?

http://en.cppreference.com/w/cpp/atomic/atomic

Thomas P. schrieb:
> C++ API

Was soll das sein, meinst du die STL?

von Zeno (Gast)


Lesenswert?

Thomas P. schrieb:
> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben? Mir geht es hier viel mehr um
> die Schnittstelle. Für C++ gibt es eine schöne SQL API, jedoch halte ich
> es ein wenig übertrieben für ca. 10 Werte eine ganze Datenbank
> anzulegen.

Schreibe einfach die Daten in JSON-Notation in eine Textdatei auf die 
der Webserver Zugriff hat. Auf der Webseite benötigst etwas Javascript 
und auf dem Server ein Script in PHP, Perl oder Python - C geht wohl 
auch.
Ist alles kein Hexenwerk und Du findest genug Beispiele im Netz. Google 
einfach nach JSON.

Zeno

von Thomas P. (tommy2002)


Lesenswert?

Daniel A. schrieb:
> Was soll das sein, meinst du die STL?

Ich meinte damit eigentlich eine SQL API für C++.

Zeno schrieb:
> Schreibe einfach die Daten in JSON-Notation in eine Textdatei auf die
> der Webserver Zugriff hat. Auf der Webseite benötigst etwas Javascript
> und auf dem Server ein Script in PHP, Perl oder Python - C geht wohl
> auch.
> Ist alles kein Hexenwerk und Du findest genug Beispiele im Netz. Google
> einfach nach JSON.
>
> Zeno

Werde mich da mal einlesen, danke!

von Klaus (Gast)


Lesenswert?

Thomas P. schrieb:
> Programmieren wollte ich das ganze mit HTML, CSS, PHP, SQL, Javascript

Ist ja ein ganz schöner Zoo. In node.js, serverseitigem Javascript, ist 
ein Webserver das "Hello World". Hier ein Beispiel:
1
//Lets require/import the HTTP module
2
var http = require('http');
3
4
//Lets define a port we want to listen to
5
const PORT=8080; 
6
7
//We need a function which handles requests and send response
8
function handleRequest(request, response){
9
    response.end('It Works!! Path Hit: ' + request.url);
10
}
11
12
//Create a server
13
var server = http.createServer(handleRequest);
14
15
//Lets start our server
16
server.listen(PORT, function(){
17
    //Callback triggered when server is successfully listening. Hurray!
18
    console.log("Server listening on: http://localhost:%s", PORT);
19
});
das stammt von hier, aber andere finden sich zu Hauf
http://blog.modulus.io/build-your-first-http-server-in-nodejs

Diesen HTML, CSS und eventuel nötiges clientside Javascript ausliefern 
zu lassen, ist kein wirkliches Problem. Ein paar tausend Werte in einem 
serverseitigen Javascript Array zu halten, ist kein Hexenwerk. Dieses 
als json in einen File zu schreiben, wenn man sich mal etwas merken 
will, auch nicht. Das einzige, was fehlt, ist das Auslesen des I2C 
Busses. Aber auch dafür gibt es bestimmt etwas

https://www.npmjs.com/package/i2c-bus

Das ganze könnte also ein einziges node.js Programm sein. C++, Apache, 
PHP und SQL kommen da nicht mehr vor.

MfG Klaus

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Thomas P. schrieb:
> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben? Mir geht es hier viel mehr um
> die Schnittstelle. Für C++ gibt es eine schöne SQL API, jedoch halte ich
> es ein wenig übertrieben für ca. 10 Werte eine ganze Datenbank
> anzulegen.

Ja, man kann eine Datenbank als Middleware verwenden (spanabhebende 
Datenverarbeitung), Sie ist aber eigentlich für Persistenz gedacht.

Link doch einfach eine HTTP Library zu deinem bestehenden C++ Programm 
und lass das Programm selbst die HTTP requests beantworten. Dann 
entfällt auch die Notwendigkeit, für Interprozesskommunikation.

mfg Torsten

P.S.: Wenn sich die Variablen nach Änderung automatisch in der 
Web-Oberfläche aktualisieren sollen, dann könntest Du z.B. Sioux: 
https://github.com/TorstenRobitzki/Sioux verwenden.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Thomas P. schrieb:
> Für C++ gibt es eine schöne SQL API

Es gibt schon seit Urzeiten Cookies, und seit HTML5 gibt es 
localstorage. Da muss man sich halt einlesen. Zuerst mal wäre die Frage, 
ob die Werte überhaupt länger gespeichert werden müssen als die 
Anwendung läuft bzw. die Seite angezeigt wird.

Georg

von Thomas P. (tommy2002)


Lesenswert?

Klaus schrieb:
> Ist ja ein ganz schöner Zoo.

;-)

Danke für die restlichen Infos Klaus!

Klaus schrieb:
> Das einzige, was fehlt, ist das Auslesen des I2C
> Busses. Aber auch dafür gibt es bestimmt etwas

Sehr sehr sehr ungern! Ich habe mir da einen Wolf geschrieben und nun 
steht alles in C++. AD-Wandler auslesen, DA-Wandler beschreiben, habe 
auch einen I2C <=> HD44780 Display Adapter gebaut und die Software 
geschrieben um ein LCD am Bus zu betreiben. Das möchte ich jetzt ungern 
über den Haufen werfen.


Georg schrieb:
> Da muss man sich halt einlesen.

Genau! Ich studiere (zum Glück?/leider?) Elektrotechnik ;-). 
Webprogrammierung wird nicht gelehrt. Aus dem Grund bin ich froh über 
die vielen Tipps, da ich nicht auf Anhieb weiß wonach ich wirklich 
suchen soll und welches Tool mir die Funktionen bietet. Jedoch bereitet 
mir dieses Gebiet neben der Regelungstechnik in der letzten Zeit viel 
Spaß.

Georg schrieb:
> Zuerst mal wäre die Frage,
> ob die Werte überhaupt länger gespeichert werden müssen als die
> Anwendung läuft bzw. die Seite angezeigt wird.

Jain, im Moment nicht ABER, ich könnte mir in Zukunft eine Funktion 
vorstellen, die mir in einem Graphen z.B. die Leistungskurve der letzten 
5 Minuten anzeigt. Da wäre es schon von Vorteil 100-500 Messwerte über 
paar Minuten zu speichern. Aber ansonsten sollten nur die aktuellen 
Werte angezeigt werden.

: Bearbeitet durch User
von Klaus (Gast)


Lesenswert?

Thomas P. schrieb:
> Sehr sehr sehr ungern! Ich habe mir da einen Wolf geschrieben und nun
> steht alles in C++.

Kenn ich, ging mir auch oft so. Ich habs später aber immer bereuht. Beim 
zweiten Mal schreibt man meist besseren Code. Buch das erste Mal als 
Trainingseinheit ab.

MfG Klaus

von Karl Käfer (Gast)


Lesenswert?

Thomas P. schrieb:
> Ich habe mit C++ eine Software für das Raspberry Pi geschrieben. Diese
> ist wesentlich in zwei Funktionen unterteilt:
>
> 1. Eine Funktion regelt den kompletten I²C verkehr, an dem einige
> Sensoren und DAC's hängen.
> D.h. I²C auslesen und den Wert in eine Membervariable einer Klasse
> speichern, oder Membervariable auslesen und über I²C an DAC schreiben.
> 2. Die andere Funktion bietet eine Ausgabe der aktuellen Sensorwerte auf
> der Konsole. Das Programm läuft auch so, wie ich es mir vorstelle.
>
> Alle Werte werden grundsätzlich in Membervariablen von Klassen
> gespeichert, dem Thread habe ich die Referenz der Klassen übergeben.
>
> Diese beiden Funktionen sind durch Threads voneinander entkoppelt und
> laufen völlig unsynchronisiert. Dies würde ich auch gerne so
> beibehalten.

Wie lange dauert eine Abfrage aller Sensoren? Wenn die Antwort "weniger 
als 500 Millisekunden" ist, dann kannst Du Dir den ganzen Zinnober mit 
Multithreading, Synchronisierung etc. sparen.

Und warum C++? Machst Du irgendwelche aufwändigen Berechnungen, riesige 
Speicheroperationen, oder irgendetwas in der Art? Ich meine, den größten 
Teil der Zeit wartet Dein "leseSendordaten()"-Thread doch eh nur darauf, 
daß die Sensoren ihre Antworten liefern. Wofür?

Donald E. Knuth wußte schon in den Siebzigern: "Premature optimization 
is the root of all evil". Versteh' mich bitte nicht falsch, ich mag C++ 
auch, aber Du betreibst damit eine Laufzeitoptimierung, die an dieser 
Stelle höchstwahrscheinlich gar nicht nötig ist, sondern nur unnötige 
Fehlerquellen beinhaltet, die Wartbarkeit einschränkt und den Aufwand 
für die Entwicklung erhöht.

> Meine Frage ist nun: Was passiert, wenn ich in der einen Funktion z.B.
> eine Variable lese und die andere Funktion zu dem selben Zeitpunkt die
> selbe Variable beschreiben möchte?
> Ist dies theoretisch überhaupt möglich, die CPU arbeitet doch sowieso
> alles zyklisch ab?

Nein, tut sie nicht. Der Kernel (genauer: der Scheduler) verwaltet -- 
auch auf einem Single-Core -- die CPU-Zeit und teilt sie den Threads für 
Dich vollkommen unvorhersehbar zu bzw. entzieht sie ihnen. Wenn das in 
genau dem Zeitpunkt passiert, in dem der Thread ein read-modify-write 
auf eine Variable macht, oder mitten in einem Schreibzugriff, der 
mehrere Zyklen dauert, ... there be dragons.

> Dann noch eine kleine Frage: Wie ist es am einfachsten möglich die
> Variablen auf einer Homepage auszugeben? Mir geht es hier viel mehr um
> die Schnittstelle.

Wenn Du mich fragst:
1
#!/usr/bin/env python
2
from flask import Flask, render_template
3
from smbus import SMBus
4
from collections import OrderedDict as odict
5
6
app = Flask(__name__)
7
8
# name, address, command, converter/validator
9
app.config['sensors'] = (
10
  ('sens1', 0x30, 3, lambda val: val),
11
  ('sens2', 0x40, 6, lambda val: val),
12
  ('sens3', 0x50, 9, 
13
   lambda val: 3.5 * val if val > 3 and val < 6 else -1),
14
)
15
app.config['bus'] = SMBus(0)
16
17
@app.route('/')
18
def index():
19
  result = odict()
20
  for name, addr, cmnd, conv in app.config['sensors']:
21
    result['name'] = conv(app.config['bus'].read_byte_data(addr, cmd))
22
  return render_template('index.html', sensors=result)
23
24
if __name__ == '__main__':
25
  app.run()

Die Funktion "index()" ist ein Request-Handler, der beim Aufruf der 
Root-Seite ("/") aufgerufen wird, dann die konfigurierten Sensoren 
ausliest, die gelesenen Werte mit den konfigurierten Validator- und 
Konvertierfunktionen (siehe Sensor 'sens3') behandelt, die Ergebnisse 
dann in das Template 'index.html' einsetzt und zuletzt die solcherart 
erzeugte Webseite ausliefert. Natürlich kann dieses Skript erweitert 
werden, um Eingaben über HTML-Formulare entgegenzunehmen und an Deine 
DACs zu übergeben.

Dazu dann noch ein kleines Systemd-User-Unitfile zum Starten, Stoppen 
etc., und fertig ist die Laube.

> Für C++ gibt es eine schöne SQL API,

Welche denn, wenn ich fragen darf?

> jedoch halte ich es ein wenig übertrieben für ca. 10 Werte eine ganze
> Datenbank anzulegen.

Eine Datenbank ist sinnvoll, wenn Du die Daten dauerhaft persistieren 
willst, sonst nicht. Wenn Du nur eine Momentanaufnahme haben willst, ist 
eine Datenbank so überflüssig wie ein Kropf und kein Ersatz für eine 
ordentliche Interprozesskommunikation -- für so etwas gibt es UNIX- und 
Netzwerk-Sockets, (Named) Pipes, Shared Memory, ... und wenn Du auf die 
Daten mit sehr vielen Prozessen gleichzeitig zugreifen willst, dann ist 
ein simpler Key-Value-Store wie Redis viel sinnvoller.

Der Memory Footprint von Redis ist winzig im Vergleich zu einem echten 
Datenbankserver wie PostgreSQL, Redis kann veraltete Daten nach einer 
gewissen Zeit automatisch wieder vergessen und ist als In-Memory-System 
um Größenordnungen schneller als jeder Datenbankserver.

von Thomas P. (tommy2002)


Angehängte Dateien:

Lesenswert?

Karl Käfer schrieb:
> Wie lange dauert eine Abfrage aller Sensoren? Wenn die Antwort "weniger
> als 500 Millisekunden" ist, dann kannst Du Dir den ganzen Zinnober mit
> Multithreading, Synchronisierung etc. sparen.

Die AD-Wandler werden maximal 20-50 mal in der Sekunde ausgelesen. Im 
Prinzip kann ich mir das mit dem Multithreading sparen. Ich benötige das 
Multithreading nur, falls ich mir über die Konsole via SSH die Messwerte 
anzeigen lassen möchte, oder um DAC Werte zu schreiben.

Karl Käfer schrieb:
> Und warum C++? Machst Du irgendwelche aufwändigen Berechnungen, riesige
> Speicheroperationen, oder irgendetwas in der Art? Ich meine, den größten
> Teil der Zeit wartet Dein "leseSendordaten()"-Thread doch eh nur darauf,
> daß die Sensoren ihre Antworten liefern. Wofür?

Dazu eine Vorgeschichte.
Geplant ist eine Labornetzteilplatine welche mir geregelt 0-25V, 0-2,5A 
liefern kann. Die Platine soll inklusive Kühlrippe im Prinzip alles 
beinhalten. Das heißt wiederum, ich kann diese modular aufbauen. Lasse 
ich mir nun z.B. 4 Platinen entwickeln, kann ich über Klassen ganz 
einfach in meinem Code eine weitere Platine erzeugen mit allen 
Memberfunktionen und Variablen. Ich übergebe einfach nur an den 
Konstruktor die Adressen von den DAC und ADC und fertig. Das gleiche 
gilt natürlich auch für den LCD.

Ich habe mal ein Blockschaltbild angehangen.

Karl Käfer schrieb:
>> Für C++ gibt es eine schöne SQL API,
>
> Welche denn, wenn ich fragen darf?

Mysql bietet für C++ fertige header an, die man in seinen Code einfach 
einbindet.

von Karl Käfer (Gast)


Lesenswert?

Thomas P. schrieb:
> Karl Käfer schrieb:
>> Wie lange dauert eine Abfrage aller Sensoren? Wenn die Antwort "weniger
>> als 500 Millisekunden" ist, dann kannst Du Dir den ganzen Zinnober mit
>> Multithreading, Synchronisierung etc. sparen.
>
> Die AD-Wandler werden maximal 20-50 mal in der Sekunde ausgelesen.

Dann dauert ein Lesezyklus also maximal 50 ms -- das merkst Du weder auf 
der Kommandozeile, noch im Webbrowser.

> Im
> Prinzip kann ich mir das mit dem Multithreading sparen. Ich benötige das
> Multithreading nur, falls ich mir über die Konsole via SSH die Messwerte
> anzeigen lassen möchte, oder um DAC Werte zu schreiben.

Wenn das ohnehin über ein Webinterface zugänglich ist, kannst Du dieses 
Webinterface über ein Kommandozeilenprogramm benutzen. Der w3m und 
andere Kommandozeilenbrowser existieren, dann sieht die Sache sogar gut 
aus, und verskripten kannst Du sowas ganz einfach und mit jeder 
Skriptsprache. Und obendrein fallen dabei auch noch diverse andere nette 
Schnittstellen mit minimalem Konfigurationsaufwand aus der Tüte: Seriell 
über Stiftleiste und/oder USB, WLAN, ...

> Karl Käfer schrieb:
>> Und warum C++? Machst Du irgendwelche aufwändigen Berechnungen, riesige
>> Speicheroperationen, oder irgendetwas in der Art? Ich meine, den größten
>> Teil der Zeit wartet Dein "leseSendordaten()"-Thread doch eh nur darauf,
>> daß die Sensoren ihre Antworten liefern. Wofür?
>
> Dazu eine Vorgeschichte.
> Geplant ist eine Labornetzteilplatine welche mir geregelt 0-25V, 0-2,5A
> liefern kann. Die Platine soll inklusive Kühlrippe im Prinzip alles
> beinhalten. Das heißt wiederum, ich kann diese modular aufbauen. Lasse
> ich mir nun z.B. 4 Platinen entwickeln, kann ich über Klassen ganz
> einfach in meinem Code eine weitere Platine erzeugen mit allen
> Memberfunktionen und Variablen. Ich übergebe einfach nur an den
> Konstruktor die Adressen von den DAC und ADC und fertig. Das gleiche
> gilt natürlich auch für den LCD.
>
> Ich habe mal ein Blockschaltbild angehangen.

Das spricht für Objektorientierung, aber nicht unbedingt für C++. 
Python, Perl und andere Skriptsprachen können ebenfalls objektorientiert 
benutzt werden, und das oben von mir gezeigte Python-Flask-Skript 
benutzt mit den anonymen lambda-Funktionen für die Konvertierung und 
Validierung ja auch so etwas wie eine Objektorientierung für Arme. 
Natürlich kann man sowas auch in richtige Python-Klassen verpacken:
1
class Sensor(object):
2
  def __init__(self, address, command, validator):
3
    self.address = address
4
    self.command = command
5
    self.validator = validator
6
7
  def read(self, bus):
8
    res = bus.read_byte_data(self.address, self.command)
9
    return (name, self.validator(res))
10
11
## usage:
12
adc1 = Sensor(0x30, 3, lambda val: val)
13
wert = adc1.read(app.config['bus'])

Das kannst Du ganz genau so modular zusammentackern wie mit C++, zu 
einem Bruchteil der Zeit, des Aufwandes und potentieller Fehlerquellen.

Nun verstehe ich natürlich, daß Du die bereits investierte Arbeit und 
Zeit nicht wegwerfen willst, wer macht sowas schon gerne. Aber ich 
befürchte, daß Du Dir die Sache durch Deine ursprüngliche 
Designentscheidung und Dein Festhalten daran unnötig verkomplizierst. 
Andererseits ist das, was Du Dir ausgedacht hast, eine schöne Übung in 
Multithreading und Synchronisation, Interprozesskommunikation, 
Schnittstellendesign und C++.

Wenn Du Zeit hast und etwas lernen willst, dann magst Du vielleicht 
einfach beide Varianten implementieren, Deine und meine. Dann hast Du 
einen ziemlich guten Lernerfolg in C++ und UNIX-Systemprogrammierung und 
siehst andererseits auch mal, wie sich sowas schnell, einfach, effizient 
und robust umsetzen läßt. Viel Spaß und Erfolg dabei!

> Karl Käfer schrieb:
>>> Für C++ gibt es eine schöne SQL API,
>>
>> Welche denn, wenn ich fragen darf?
>
> Mysql bietet für C++ fertige header an, die man in seinen Code einfach
> einbindet.

Oh, MySQL. Ich dachte, Du meintest eine generische SQL Api wie SQLAPI, 
nur in hübscher. Ich persönlich habe MySQL vor vielen Jahren den Rücken 
gekehrt und setze lieber auf PostgreSQL, für das es mit libpqxx eine 
(wie ich finde) sehr schöne, moderne und elegante C++-Api gibt. Aber, 
wie gesagt, für eine reine Interprozesskommunikation würde ich keine 
Datenbank benutzen, sondern entweder die klassischen UNIX-Technologien 
oder einen modernen in-memory KeyValue-Store wie Redis. ;-)

von Zeno (Gast)


Angehängte Dateien:

Lesenswert?

Thomas P. schrieb:
> Sehr sehr sehr ungern! Ich habe mir da einen Wolf geschrieben und nun
> steht alles in C++. AD-Wandler auslesen, DA-Wandler beschreiben, habe
> auch einen I2C <=> HD44780 Display Adapter gebaut und die Software
> geschrieben um ein LCD am Bus zu betreiben. Das möchte ich jetzt ungern
> über den Haufen werfen.

Wenn Du das schon alles gemacht hast, dann behalte es. Sehe in Deinem C 
Programm einfach nur noch ne Möglichkeit vor, die gewünschten Daten in 
eine Datei zu schreiben. Wenn Du es auf einer Webseite darstellen 
willst, dann ist, wie schon geschrieben, die JSON-Notation eine 
geeignete Methode. Ich habe mal ein Beispiel für so eine Datei 
angehängt. Das ist eine Datei von meiner Wetterstation.
Auf der Webseite benötigst Du etwas Javascript um
-einen Request an den Server zu senden (Daten abholen)
-die (JSON) Daten auswerten
-die dekodierten Daten in der Webseite darstellen.

Auf dem Webserver benötigst Du ein Programm/Script um auf den Request 
antworten zu können. Da gibt es diverse Möglichkeiten. Einige hatte ich 
ja schon genannt. Klaus hatte ja noch serverseitiges Javascript genannt 
aber da kenne ich mich nicht so aus. Ich meine da auch mal was gelesen 
zu haben, daß es bei serverseitigem JS Sicherheitsprobleme geben kann. 
Aber wie gesagt ich kenne mich damit nicht so aus.

Nach diesem beschriebenen Prinzip funktioniert meine Wetterwebseite 
schon einige Jahre. Übrigens auch auf einem Pi.

Zusätzlich zur JSON-Datei schreibe ich die Daten in eine RRD-Datenbank 
und in eine fortlaufende CSV-Datei. Es gibt für jeden Tag eine 
CSV-Datei.

Zeno

von Peter II (Gast)


Lesenswert?

Zeno schrieb:
> Wenn Du das schon alles gemacht hast, dann behalte es. Sehe in Deinem C
> Programm einfach nur noch ne Möglichkeit vor, die gewünschten Daten in
> eine Datei zu schreiben

da muss er aber darauf achten, das es möglichst nicht auf dem SD-Karte 
landet, sonst ist sie recht schnell defekt.

Man kann auch memcache verwenden, dafür gibt es eine C(++) Api und PHP 
kann auch darauf zugreifen. Dann läuft alles im RAM ab.

von Zeno (Gast)


Lesenswert?

Peter II schrieb:
> da muss er aber darauf achten, das es möglichst nicht auf dem SD-Karte
> landet, sonst ist sie recht schnell defekt.
>
> Man kann auch memcache verwenden, dafür gibt es eine C(++) Api und PHP
> kann auch darauf zugreifen. Dann läuft alles im RAM ab.

Das hast Du natürlich recht und Dein Vorschlag vermeidet dies. Ich weiß 
ja nicht was er mit den Daten machen will. Wenn es über Memory läuft 
sind sie nach dem Ausschalten natürlich weg. Man kann ja auch ne 
USB-Platte an den Pi hängen. Nachteil man brauch für die Platte extra 
Netzteil.

Ich habe es bei mir so gelöst: Bei mir sind es mehrere Pi die die Daten 
einsammeln. Diese hängen natürlich im Netzwerk. In diesem gibt es ein 
NAS-Platte für Datensicherung und so nen Kram. Auf dieser habe ich 
NFS-Space eingerichtet, auf den die Pi's und der Webserver Lese- und 
Schreibzugriff haben. Die Pi's und der Webserver mounten diesen Space 
und können darüber problemlos Daten austauschen. Auf dem NFS-Space 
liegen auch die erwähnten RRD-Datenbanken. NFS ist zwar eine ältere 
Sache aus der Unixwelt, funktioniert aber sehr zuverlässig und ist in 
meinem Fall ideal.

Zeno

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.