Hi,
folgendes Szenario: Ich habe 2 Arduino Megas, auf denen das gleiche Programm laufen soll. Da ich aber eine unterschiedliche Pin Belegung auf beiden habe, möchte ich über eine boolean Variable am Anfang des Sketches die Pinbelegung einstellen können, quasi:
Leider funktioniert das nicht: Eine If/ Else Abfrage vor setup() geht nicht und wenn ich die Pin Belegung im Setup mache, kann er im loop nicht auf die Variablen zugreifen (was not declared in this scope)...
Wie löst man das Problem?
Grüße
Du sparst Dir damit Code und vor allem Speicher, weil die Werte nicht als Variable im Speicher stehen müssen, sondern vom Präprozessor beim compilieren schon ersetzt werden.
Um zwischen den Arduinos zu wechseln musst Du dann nur noch das "#define ARDUINO1" auf "#define ARDUINO2"
Beide oben vorgestellten Varianten sind eine gute Lösung - erfordern aber jeweils ein manuelles Eingreifen in den Code um zu sagen, auf welchen Arduino man nun übertragen will.
Ein dritter "Trick" wäre eine Kombination von allem - in Verbindung mit einem freien Pin auf beiden Boards: Bei Arduino1 wird z.B. Pin 10 auf GND gelegt, auf Arduino2 wird Pin 10 via 10 kOhm auf 5V gelegt. Dieser Pin wird im Programm abgefragt - und steuert das Verhalten. Spart die Eingriffe in den Code und minimiert das Risiko, den "falschen" Code zu übertragen.
Serial.begin(9600);
if (switch_arduino) {
int i = 1;
} else {
int i = 2;
}
}
Bis auf Serial.begin ist das natürlich Unfug. Die beiden lokalen Variablen i sind weg, noch bevor setup zu Ende ist.
2 Arduino Megas, auf denen das gleiche Programm laufen soll
Wenn du es strikt meinst, ist natürlich eine Konstante (globale Variable)boolean switch_arduino = true;verkehrt, denn du musst die für jeden der beiden Arduinos unterschiedlich setzen und neu kompilieren/hochladen.
Dann ist die vorgeschlagene #ifdef Lösung besser.
Wenn du es ernst meinst mit "identisches Programm", müsstest du in setup etwas abfragen, woran du die beiden unterscheiden kannst.
const byte DETECTPIN=20; // Bei Arduino1 auf HIGH, bei Arduino2 auf LOW
byte motorpin; // kann leider nicht const sein
void setup() {
bool switch_arduino = digitalRead(DETECTPIN);
if (switch_arduino) {
// Arduino 1
motorpin=5;
...
} else {
// Arduino 2
motorpin=6;
...
}
Serial.begin(9600);
Serial.print(F("Start Arduino"));
Serial.println(switch_arduino?"1":"2");
}
Whandall:
Du könntest die Pinbelegung in den EEPROM legen und hättest damit nur einen Kode ohne Trickserei.
Das ist gut, wenn das Projekt final ist und sich nicht mehr ändert. Ansonsten ist der Aufwand die Daten im EEPROM aktuell zu halten recht groß, wenn sich mal was ändert. Ist ja jedesmal ein eigener Sketch der die Konfig (abhängig davon welcher Arduino) in den EEPROM schreibt.
Die Idee mit dem freien PIN ist gut. Der wird mit INTERNAL_PULLUP als Eingang gesetzt. Bei einem Arduino ist er auf Masse (GND) gelegt und auf dem anderen nicht. Dann kann der Code selbst entscheiden auf welchem Arduino er läuft.
Ich habe schon Ähnliches programmiert und es so gelöst, wie whandall es vorschlägt.
Benutze entweder einen freien Pin, um die beiden Arduinos per Jumper als Arduino Nr. 1 oder Nr. 2 zu identifizieren, oder lege jeweils einen entsprechenden „Hinweis“ im EEPROM ab.
mkl0815:
Das ist gut, wenn das Projekt final ist und sich nicht mehr ändert.
Wenn vom Start weg klar ist, dass es zwei Arduinos braucht und man nur einen Wert ins EEPROM schreibt, der die Arduinos identifiziert, muss man das nur einmal machen. Der Aufwand hierfür (einen eigenen Sketch für das Schreiben ins EEPROM) ist überschaubar.
Ich habe das mal bei einer Handvoll Arduinos so gemacht. Dort war am Anfang des EEPROMs lediglich eine andere I²C-Adresse abgelegt.
ok, ich muss mich entschuldigen. Ich musste feststellen, dass es Abweichungen im Code zwischen Arduino1 und Arduino2 gibt (Bei Arduino1 lese ich digital und bei Arduino2 analog), mein Code soll also ähnlich sein. Habe jetzt auch mein Fehler entdeckt: Die Deklaration meiner Variablen i erfolgte nur lokal in der Funktion setup.
Daher würde ich das jetzt wie folgt lösen:
boolean switch_arduino = false;
//true = arduino 1
//false= arduino 2
int i; //const geht nicht
void setup() {
Serial.begin(9600);
if (switch_arduino) {
i = 1;
} else {
i = 2;
}
}
void loop() {
Serial.println(i);
//gleicher Code
//...
//unterschiedlicher Code
if (switch_arduino) {
//Code Arduino1
} else {
//Code Arduino2
}
}
Edit: Die Idee mit der Abfrage eines Pins ist für die Entscheidung einer Variablendeklaration ist gut, aber ich werde das einfach mit meiner boolean switch_arduino lösen, die ich vor dem Compilieren händisch änder, bevor der Sketch hochgeladen wird.
ausgeführt wurde, wird eine Wertzuweisung von pin_pulse und pin_direction nicht mehr übernommen :(... (d.h. mein stepper ist als "stepper(1, NULL, NULL);" definiert
michael_x:
Alternativ kannst du auch eine eigene Klasse von Accelstepper ableiten, die dann die Methode setPins hat...
Das wird vermutlich leider nicht klappen, denn die Pins sind als private nicht als protected deklariert. Damit kann eine Klasse die von Accelstepper ableitet nicht direkt auf die Attribute zugreifen.
über #define deklariere ich meine Konstanten (Pin Belegung), boolean switch_arduino deklariert meine Variablen (Geschwindigkeit, Beschleunigung). Bisher klappt es mit Arduino 2, Arduino 1 werde ich erst nächste Woche testen können (ist in einem Versuchsaufbau integriert)
Noch ein Tippchen: Verwende nicht #define sondern z. B. const byte.
Das Problem mit #define ist, dass der Präprozessor dabei eine einfache „suchen und ersetzen“-Funktion ausführt. Dabei wird die Typprüfung des Compilers umgangen.
Andererseits: Wenn's auf diese Weise funktioniert ...