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 ?
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.
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) {}
|
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.
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.
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.
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.
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
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.
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.
|