Fehler: multiple definition of ....

Da fummle ich schon den ganzen Tag an meiner Lib, alles läuft gut bis super, bis ....

Keine Ahnung mehr was ich genau gemacht habe, aber plötzlich meckert der Kompiler rum wie folgt: MegaStepper\MegaStepper.cpp.o:(.bss.Motor+0x0): multiple definition of `_Motor' Serial_Test_2_ino.cpp.o:(.bss._Motor+0x0): first defined here *l:/_install/3_soft/prog/arduino/arduino_1-52/arduino-1.5.2/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions*

_Motor ist ein Array aus Motordaten. Hieß erst Motor und war mit der zugejörigen typedef struct innerhalb einer Klasse. Dann hab ich mal umbenannt und auch noch nach global ausserhalb der Klasse gelegt. Ich vekomme diese beknackte Fehlermeldung nicht weg - viel schlimmer: Ich kann mir keinen Reim drauf machen und was doppelt definiert ist defintiv nichts.

und auch noch nach global ausserhalb der Klasse gelegt.

Deshalb erzeugt jetzt jeder, der die include-Datei verwendet, einen _Motor Bei zwei cpp oder ino Dateien ist das einer zuviel ;)

Wenn es "global ausserhalb der Klasse" sein muss ( warum ?), verwende ``` extern ``` in der include Datei und definiere den _Motor in einer deiner .cpp Dateien.

Als C++ Programmierer sollte man stattdessen innerhalb der Klasse static verwenden.

D.h.: Meine MegaStepper.cpp (logo !?) und das Sketch (zum einbinden der Klasse) verwenden ja die .h Datei - und beide legen einen "_Motor" an ? Aber eine ebenfalls ausserhalb der Klasse angelegte funktion wie ISR(TIMER1_OVF_vect) nur einmal ? Was soll das denn ....

Wie soll den so was funktionieren mit static oder extern ?

Problem ist hier: Anscheinend kann man keine ISR mit einer Funktion einer (eigenen) Klasse belegen. Jedenfalls habe ich nach ewiger Sucherei dazu nix gefunden. Wahrscheinlich wieder das neulich besprochene Probleme pointer2funtion - pointer2member ? Oder kann man durch eifrige Zeigerbiegerei eine ISR docht vielleicht hierhin umleiten: MegaStepper::MyISR ?

Anderer Lösungsversuch war: _Motor ist global und die Klasse füllt/berechnet da ein einige Werte. Die ISR selbst nimmt nun diese Werte aus _Motor, schaltet Pins, decrementiert einen Zähler und das wars eigentlich auch schon.

Nächste Idee: Im Sketch definiere ich eine Funktion als CallBack/Wrapper, welche wiederum (m)eine interne ISR-Funktion in der Klasse ruft. Das kann man ja gleich beim initialisieren setzen. Die eigentliche ISR ruft dann die CallBack-Funktion und somit die interne ISR auf. Das klappt ja auch - jatte ich schon mal probiert. Empfinde ich allerdings als irgendwie "von hinten durch die Brust ins Auge". Zudem habe ich pro Interrupt dann 2 Funktionsaufrufe mehr - keine Ahnung wie sich das bei ggf. zeitkritischen, kurzen Int's verhält.

Oder hat noch jemand ne andere Idee ?

Keiner weiß was ? :cold_sweat:

Ist das Thema noch aktuell ?

Bastel doch um dein Motor folgendes drum herum, dann hast du nie wieder Probleme mit doppelten Motoren:

#ifndef _MOTOR_DEF
#define _MOTOR_DEF
  //hier den code wo motor angelegt wird
#endif
  1. Ich fürchte, Jomelos #ifndef hilft hier nicht wirklich, da in zwei cpp/ino Dateien _MOTOR_DEF zunächst undefiniert ist. Diese Konstruktion wird zusätzlich benötigt, damit du nach Belieben include-Dateien ineinander verschachteln kannst.

  2. In der include Datei werden globale Variable als extern deklariert. Da wo sie zu Hause sind ( welche der code-Dateien du auswählst, ist Geschmackssache ) , werden sie definiert.

  3. ISR können keine Methoden einer Klasse sein, sondern nur "normale" Funktionen, ohne Rückgabe und Aufruf-Parameter.

( Im Sommer sitzen nicht alle immer vor dem Computer, sorry )

Moin zusammen !
… zu viel Sonne auf den Kopf kann auch schädlich sein. :grin:

Stimmt: Diese Einbettung mit ‘define ifndef’ funktioniert nicht.
Hatte ich mir bei Zeiten aus der Messenger.h schon abgekupfert (habe das als Gerüst genommen).

Das mit den ISR ist mir ja auch aufgefallen - deshalb sollte _Motor auch ausserhalb der Klasse liegen, was ja eben doppelte Definition verursachte.
Also wieder rein damit in die Klasse und weiter nach Lösungen gesucht.

In der TimerThree.cpp hab ich etwas entdeckt:
Dort steht in der TimerThree.cpp gleich zu Anfang

#include "TimerThree.h"
TimerThree Timer3;              // preinstatiate

Also sinngemäß gleiches bei mir reingebastelt und die Instanziierung im Sketch weggelassen - siehe da: ich kann folgendes machen

#include <Streaming.h>
#include "MegaStepper.h"

char version[] PROGMEM =  "Mega-Stepper V 1.0, 2013-07-14 by TERWI";

MegaStepper MegStep = MegaStepper();      // preinstatiate
... 

int MegaStepper::StepMotor(int motor)
{ .... handling der jeweiligen ISR in einer Routine bezogen auf _Motor[motor]
}

/*
ISR(TIMER1_OVF_vect)   
{
  MegStep.StepMotor(0);
}
*/

ISR(TIMER3_OVF_vect)   
{
  MegStep.StepMotor(1);
}

ISR(TIMER4_OVF_vect)   
{
  MegStep.StepMotor(2);
}

ISR(TIMER5_OVF_vect)   
{
//  MegStep.StepMotor(3);
}

Wie zu sehen ist, ist die 1. ISR ausmarkiert. Ich benutze diese nämlich z.Zt. zum testen noch im eigentlich Sketch.
Das der Kompiler keinen 2. Aufruf zulässt, scheint korrekt zu sein und macht auch Sinn.

Sehr eigenartig ist folgendes:
Die 4. ISR vom Timer5 lässt sich auch so einbinden - kein Problem. Allerdings (bisher !) nur OHNE den Aufuf meiner Funktion darin.
Nahm ich die beiden Slashes da weg, erschien immer eine ewig lange Fehlermeldung.
Das funktionierte seit Tagen nicht…
Eben grade noch mal die Slashes raus und kompiliert: Häääh ? Funktioniert ! Verstehe ich nicht.