Hallo,
Ich brauche ein Objekt, das zur Laufzeit erstellt wird, welches andere
Objekte enthält, die zur Objekterstellung erstllt werden sollen. Das
ganze soll 1-x LEDs ansteuern.
Schlauerle in mir sagt: klar, zwei Klassen - eine LED() und eine
LEDController().
LEDController bekommt eine attach()-Methode in der LED-Objekte zu einer
Liste hinzugefügt werden.
So weit, so theoretisch. Nur dann steige ich mit den Pointern aus.
Bei einer "modernen" Sprache (bitte nicht hauen) würde ich in etwa
soetwas machen:
(VORSICHT! - PseudoCode)
1
publicclassLEDController
2
{
3
intledCount;
4
LEDLEDArray[10];
5
publicLEDController()
6
{
7
ledCount=0;
8
}
9
10
publicvoidattach(int_pin)
11
{
12
LEDArray[ledCount]=newLED(_pin);
13
}
14
15
publicLEDgetChannel(int_channel)
16
{
17
returnLEDArray[_channel];
18
}
19
20
21
}
22
23
publicclassLED
24
{
25
int_pin;
26
publicLED(intpin)
27
{
28
pinMode(pin,OUTPUT);
29
_pin=pin;
30
}
31
32
publicvoidblink()
33
{
34
digitalWrite(_pin,HIGH);
35
delay(250);
36
digitalWrite(_pin,LOW);
37
delay(250);
38
}
39
}
40
41
42
LEDControllerc1=newLEDController();
43
44
voidsetup()
45
{
46
c1.attach(D0);
47
c1.attach(D1);
48
c1.attach(D2);
49
}
50
51
voidloop()
52
{
53
c1.getChannel(0).blink();
54
}
In der richtigen Welt hab ich folgendes probiert:
test.ino
Aber - klar, funktioniert so nicht. Ich muss das irgendwie miteinander
verschwurbeln, krieg es aber nicht hin... Ich glaube zu wissen, dass die
Lösung Pointer hat - einfach nur, weil ich sogut wie keine habe :)
Ist ja schon nicht schlecht! Auf Pointer zu verzichten ist normalerweise
genau richtig.
Wahrscheinlich ist dein Problem jetzt, dass du nicht nur eine LED
blinken lassen willst, sondern alle gleichzeitig. Dazu ist deine blink()
Routine ungeeignet, weil sie sich zwei Sekunden mit einer LED
beschäftigt und der Zeit kann sonst nichts passieren. Du musst die
Funktion in eine Einschalt- und eine Ausschaltfunktion aufteilen und die
beiden von loop() in einer Schleife aufrufen.
Marcus W. schrieb:> Ich hab jetzt eine - wahrscheinlich völlig ungeeignete, dennoch> funktionierende Lösung:
Ich finde die gar nicht so schlecht. Du verwendest keine Pointer, die zu
Leak führen könnten.
Das Programm ist soweit funktional korrekt, folgende Tipps könnten es
aber noch verbessern. Ich setze mal C++11 als Sprachversion voraus. Frag
einfach, wenn etwas für dich noch nicht verständlich ist.
Du erzeugst immer eine Kopie der LED Klasse. Das ist jetzt nicht
schlimm, weil eh nur der Integer kopiert wird, führt aber zu Fehlern
wenn du dir einen Zustand in LED merken willst (z.B. für Toggle).
Außerdem kann man LED auch ohne LEDPin anlegen.
Man kann das Kopieren von Objekten verbieten indem man den
Kopierkonstruktor und den Zuweisungsoperator verbietet, allerdings
werden diese vom Vektor benötigt, damit dieser sich vergrößern kann.
1
classLED
2
{
3
private:
4
int_LEDPin;
5
6
public:
7
LED()=delete;// LED kann nicht ohne Parameter angelegt werden
8
LED(intnewLEDPin)
9
:_LEDPin(newLEDPin)// Initialisierungsliste (macht bei int keinen Unterschied, bei anderen Objekten schon)
10
{
11
pinMode(_LEDPin,OUTPUT);
12
digitalWrite(_LEDPin,LOW);
13
}
14
15
voidblink()
16
{
17
// ... Code unverändert
18
}
19
};
Verhinderung der Kopie.
1
voidattach(intpin)
2
{
3
// Das Element wird direkt erzeugt und nicht erst lokal
4
// erzeugt und dann kopiert. Aber selbst mit Zustand in LED
5
// wäre das kopieren kein Problem gewesen.
6
LEDList.emplace_back(pin);
7
}
8
9
// Referenz zurückgeben auf das Element im Vektor. Damit
10
// wirkt sich eine Zustandsänderung auf das Element im Vektor
11
// aus. Bei Kopie würde sich nur die Kopie ändern und das
12
// Element im Vektor bleibt unverändert.
13
LED&getChannel(intchannel)
14
{
15
// Wenn Channel außerhalb von LEDList liegt, dann ist das
Das war auch schon mein ganzes Problem. Ich hab das & reingesetzt und
schon funktioniert alles wie ich will.
Der ESP8266 hat total verückt gespielt, als ich das blinken auf
non-blocking umgestellt habe, weil der vector 1000x umkopiert wurde.
Mir ist es dann total um die Ohren geflogen und "nowTime-lastTime >=
2000" bzw "(240 - 0) >= 2000" hat aufeinmal 'true' ergeben.
Ein verdammtes Zeichen killt mir den ganzen Code! :)
Danke für die Hilfe. Die Initialisierung hab ich inzwischen auch
umgestellt.
Marcus W. schrieb:> Was ist eigentlich "besser", bzw wo liegt der Unterschied?
Für den Prozessor ist es kein Unterschied.
Bei einer Referenz ist der Zugriff immer gültig. Ein Pointer kann auch 0
sein. Als Anwender der Funktion kann ich die Referenz einfach verwenden,
den Pointer sollte ich prüfen.
Der Pointer ist sinnvoll, wenn du auch den Wert ungültig zurückgeben
willst, z.B. bei einem Index, der ungültig ist.
Marcus W. schrieb:> Der ESP8266 hat total verückt gespielt, als ich das blinken auf> non-blocking umgestellt habe, weil der vector 1000x umkopiert wurde.
Das kann ich aus deinem Code so nicht schließen. Es wird ja in LED nur
der int member kopiert. Im Fall der Referenz wir im Prinzip ein Pointer
auf die LED, der normalerweise auch so groß wie ein int ist, erzeugt.
Der Vektor wird niemals kopiert. Außerdem liegt beides auf dem Stack.
Das dürfte normalerweise keinen Unterschied machen, außer es ist ein
Debugbuild der beim Kopieren von Objekten noch mehr Checks einbaut.
Ich würde das blinken dem Controller überlassen. Die LED kann ja nur ein
oder aus sein. Das macht es auch einfacher verschiedene LEDs
gleichzeitig blinken zu lassen.