Forum: Mikrocontroller und Digitale Elektronik 2 Konstruktoren falsches C++ oder Compilerfehler ?


von Frank O. (fop)


Lesenswert?

Ich versuche hier eine 4-stellige Siebensegmentanzeige mit einem Arduino 
Pro Mini anzusteuern, und wie immer dabei möglichst wenig selbst 
arbeiten zu müssen :-)

Genutzte Softwarepakete :
- Arduino AVR Boards Version 1.8.6 von Arduino
  nutzt g++ Version 7.3.0 im Verzeichnis 
avr-gcc\7.3.0-atmel3.6.1-arduino7
- Bibliothek uMuxOutputLib (https://github.com/Naguissa/uMuxOutputLib) 
Version 1.0.2
- Bibliothek uTimerLib (https://github.com/Naguissa/uTimerLib) Version 
1.7.2
- Arduino IDE 2.2.1
- Windows 11 Pro 64 Bit Version 23H2 22631.2861

Ich wollte die Multiplexfrequenz hochsetzen, aber wie sie sehen, sehen 
sie nix. Es kam kein Interrupt vom Timer. Das lag daran, dass die Dauer 
zwischen 2 Interrupts auf alles was mit 32 Bit geht gesetzt wurde. Das 
kam dadurch zustande, dass in der Methode attachInterrupt durch 0 
geteilt wurde, um diesen Wert auszurechnen.
Das wiederum lag daran, dass die private Variable _nmuxes des Objektes 
auf 0 stand. Häh, die hätte 4 sein sollen, weil das Objekt wegen der 
4-stelligen Anzeige so erzeugt wurde.
1
#include "Arduino.h"
2
#include "uMuxOutputLib.h"
3
int pins[8] = {6, 7, 8, 9, 10, 11, 12, 13};
4
int muxes[4] = {3, 2, 4, 5};
5
uMuxOutputLib muxer(8U, 4U, pins, muxes, 200U);
6
7
void setup() {
8
  muxer.attachInterrupt();
9
}

Ok, die Klasse hat 2 Konstruktoren, einen ohne Angabe der 
Multiplexfrequenz und einen mit. Der mit, lädt die gewünschte 
Multiplexfrequenz in eine private Variable des Objekts und ruft dann den 
anderen Konstruktor mit den restlichen Parametern auf. So der Plan, aber 
der Parameter nmuxes kommt nicht an. Im aufgerufenen Konstruktor ist der 
Parameter nmuxes 0, und so nimmt das Schicksal seinen Lauf.
1
// .h :
2
  class uMuxOutputLib {
3
    public:
4
      // Constructors
5
      uMuxOutputLib(uint8_t, uint8_t, int *, int *);
6
      uMuxOutputLib(uint8_t, uint8_t, int *, int *, unsigned int);
7
8
// .cpp :
9
// Static variable assignment
10
uMuxOutputLib * uMuxOutputLib::_instance = NULL;
11
12
13
/**
14
 * \brief Constructor
15
 *
16
 * @param npins Number of pins
17
 * @param nmuxes Number of muxes
18
 * @param pins array of pins for outputs
19
 * @param muxes array of pins for muxes
20
 */
21
uMuxOutputLib::uMuxOutputLib(uint8_t npins, uint8_t nmuxes, int *pins, int *muxes) {
22
  _npins = npins;
23
  _nmuxes = nmuxes;
24
// usw., usw.
25
}
26
27
28
/**
29
 * \brief Constructor
30
 *
31
 * @param npins Number of pins
32
 * @param nmuxes Number of muxes
33
 * @param pins array of pins for outputs
34
 * @param muxes array of pins for muxes
35
 * @param freq Refresh frequency (for all pins, will be multiplied by nmuxes to calculate end result)
36
 */
37
uMuxOutputLib::uMuxOutputLib(uint8_t npins, uint8_t nmuxes, int *pins, int *muxes, unsigned int freq) {
38
  _freq = freq;
39
  uMuxOutputLib(npins, nmuxes, pins, muxes);
40
}
Frage : Wo liegt der Fehler ? Dürfen überladende Konstruktoren sich so 
einander aufrufen und baut der gcc hier Murks oder was ?

von Harald K. (kirnbichler)


Lesenswert?

Frank O. schrieb:
> Dürfen überladende Konstruktoren sich so
> einander aufrufen

Dürfen sie. Das ist ok.

Aber vielleicht ist der Wert "200u", den Du verwendest, ungültig. Sieh 
mal im Quelltext nach, wie die Variable "_freq" normalerweise 
initialisiert wird.

von Sophie T. (sophie_t)


Lesenswert?

Versuchs mal bitte mit der member intialization und delegating 
constructor. So macht man das ab C++11.
1
uMuxOutputLib::uMuxOutputLib(uint8_t npins, uint8_t nmuxes, int *pins, int *muxes, unsigned int freq) : _freq{freq}, uMuxOutputLib(npins, nmuxes, pins, muxes) {}

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Frank O. schrieb:
> uMuxOutputLib::uMuxOutputLib(uint8_t npins, uint8_t nmuxes, int *pins,
> int *muxes, unsigned int freq) {
>   _freq = freq;
>   uMuxOutputLib(npins, nmuxes, pins, muxes);
> }
> Frage : Wo liegt der Fehler ?

Du erzeugst in deinem Konstruktor ein namenloses lokales Objekt vom Typ 
uMuxOutputLib, das danach sofort wieder zerstört wird. Dieses lokale 
Objekt hat nichts mit dem ersten zu tun. Somit landen die Parameter alle 
im Nirwana.

von Frank O. (fop)


Lesenswert?

Danke für die Tipps. Der Teil der Software ist ja nicht von mir. Deshalb 
habe ich das mal via Github an den Autor weiter gegeben.

von Frank O. (fop)


Lesenswert?

Was mir gerade so einfällt: es geht ja nicht ohne Frequenz. Wenn man 
keine angibt, wird ein Standardwert von 70 Hz angenommen. 
Praktischerweise ist ja die Frequenz auch der letzte Parameter. Also 
müsste es unter C++ doch möglich sein, die 70 als Standardwert 
vorzugeben und so aus den 2 Konstruktoren einen zu machen.

von Rolf M. (rmagnus)


Lesenswert?

Frank O. schrieb:
> Also
> müsste es unter C++ doch möglich sein, die 70 als Standardwert
> vorzugeben und so aus den 2 Konstruktoren einen zu machen.

Ja. Man könnte dem letzten Parameter diesen Wert als Default-Wert 
mitgeben.

von Oliver S. (oliverso)


Lesenswert?

Frank O. schrieb:
> Der Teil der Software ist ja nicht von mir. Deshalb
> habe ich das mal via Github an den Autor weiter gegeben.

Deren letzte Änderung am Repo war vor 4 Jahren. Seit dem hat da niemand 
mehr was dran gemacht, und anscheinend auch niemand den Fehler bemerkt.

Vielleicht suchst du dir eine andere lib.

Oliver

von J. S. (jojos)


Lesenswert?

Der richtige Weg wäre einen Fork zu erzeugen (ein Klick bei github). 
Dann diesen Fork mit git clone auf den eigenen Rechner holen, 
korrigieren und wieder nach github pushen. Dann kann man einen Pull 
Request an den Autor schicken. Der kann das dann übernehmen oder nicht, 
aber man hat den Fix für sich ordentlich behandelt und kommentiert.

von Naguissa N. (naguissa_n)


Lesenswert?

Hello,

I'm the creator of the lib. I got feedback and a proposal (thanks!).

I never faced that problem before, probably because I didn't use that 
parameter.

I'm working on it, but because computer/work/medical visits I was unable 
to do it yet. I'll try this night before going to sleep...


Cheers!

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.