Ik probeer te begrijpen hoe #ifdef en #ifndef werkt.
Als ik het goed begrijp kunnen globale variabelen alleen buiten een procedure gedeclareerd worden.
Ik kom er niet uit of het mogelijk om met #... zo'n globale variabele te declareren. Mijn kennis van de Engelse taal is daar niet toereikend voor.
Is er iemand die mij wegwijs kan maken?
Ik sluit een stuk van een programma in wat prima functioneert als ik #ifndef MASTER (en #endif) weglaat, nu wil ik dat graag met een variabel die afhandelijk is of MASTER al dan niet gedefineerd is.
Ik hoop dat er iemand is die mij op weg wil helpen.
Je laat het belangrijke deel van je programma weg, namelijk hoe answer gebruikt wordt.
Het gaat fout als de compiler je programma compileert voor MASTER. answer is dan onbekend maar de compiler komt het tegen in je programma en breekt zijn nek daarover.
E.g.
void Ssetup()
{
Serial.println(answer);
}
Om dat te voorkomen, zul je de functies Ssetup() en Sloop() ook conditioneel moeten compileren. BV
Het probleem doet zich voor in de Slave listing, niet bij Master.
Ik zal de volledige listing hier neerzetten. incl. alle comments etc.
De tabbladen Master en Slave zet ik hier ook volledig.
Zoals je kan zien is er bij de Master geen gebruik van answere vandaar dat ik het (nog steeds) niet begrijp maar je oplossing werkt wel. Dank!!!
De reden waarom ik het in 1 programma wil is; dat ik op het punt sta van een modelbaan in een museum allerlei seinen, sensoren, wissels en treinen te moeten gaan aansturen/uitlezen. Daar werken meerdere mensen aan en wordt er nogal eens wat gewijzigd dus moet ik zowel software van de Master en de Slave ook muteren. Vergeet ik iets, dan hoop ik met compileren daarop gewezen te worden. In dat geval is het makkelijk om // voor #define Master weg te halen zodat de hele Slave opnieuw wordt gecompileerd.
Ik ben een redelijke newbee en weet geen andere manier maar sta open voor andere oplossingen/ suggesties
1e Tabblad
/*
Samengevoegd I2C Master en Slave Demo van DroneBot Workshop 2019
Demonstreert het gebruik van de I2C bus
Master sends character and gets reply from Slave
voor Slave software, disable #define MASTER
https://dronebotworkshop.com/i2c-arduino-arduino/
op 16:33 voor vervolg
*/
// Libraries ---------------------------------------------------------
#include <Wire.h> // voor de i2c bus
// Objecten ----------------------------------------------------------
// Constanten --------------------------------------------------------
#define MASTER
#define SLAVE_ADDR 9
#define ANSWERSIZE 5 // Slave antwoord size
// globale variabelen ------------------------------------------------
//#ifndef MASTER
String answer = "Hello";// Define string with response to Master
//#endif
// Programma =========================================================
void setup()
#ifndef MASTER
{ Ssetup();
}
#else
{ Msetup();
}
#endif
void loop()
#ifndef MASTER
{ Sloop();
}
#else
{ Mloop();
}
#endif
// Einde Programma en compile directive ==============================
#if !defined(__AVR_ATmega2560__)
#error "Oeps! Zorg ervoor dat 'Arduino Mega' is geselecteerd als board in het menu."
#endif
Tabblad Master
void Msetup()
{ Wire.begin(); // Initialiseert I2C communicatie als Master
Serial.begin(9600); // Setup serial monitor
Serial.println("I2C Master Demonstration");
}
void Mloop()
{ delay(50);
Serial.println("Write data to slave");
Wire.beginTransmission(SLAVE_ADDR); // Write a charatre to the Slave
Wire.write(0);
Wire.endTransmission();
Serial.println("Receive data");
Wire.requestFrom(SLAVE_ADDR, ANSWERSIZE); // Read response from Slave Read back 5 characters
String response = "";
while (Wire.available()) // Add characters to string
{ char b = Wire.read();
response += b;
}
Serial.println(response); // Print to Serial Monitor
}
tabblad Slave
void Ssetup()
{ Wire.begin(SLAVE_ADDR); // Initialize I2C communications as Slave
Wire.onRequest(requestEvent); // Function to run when data requested from master
Wire.onReceive(receiveEvent); // Function to run when data received from master
Serial.begin(9600); // Setup Serial Monitor
Serial.println("I2C Slave Demonstration");
}
void Sloop()
{ delay(50);
}
void receiveEvent()
{ while (0 < Wire.available()) // Read while data received
byte x = Wire.read();
Serial.println("Receive event"); // Print to Serial Monitor
}
void requestEvent()
{ byte response[ANSWERSIZE]; // Setup byte variable in the correct size
for (byte i = 0; i < ANSWERSIZE; i++) // Format answer as array
response[i] = (byte)answer.charAt(i);
Wire.write(response, sizeof(response)); // Send response back to Master
Serial.println("Request event"); // Print to Serial Monitor
}
Het is belangrijk om te definiëren welke gegevens over de I2C bus gaan. Het eenvoudigste is een enkele byte, maar het kan ook een array van variabelen zijn of een 'struct'.
Een leesbare tekst is een slechte oplossing, maar als je daarvoor kiest dan is ook daar een goede beschrijving voor nodig.
Het is beter om geen String object en geen Serial functies in de onRequest en onReceive handler te gebruiken.
Tot mijn stomme verbazing is de oplossing super simpel maar eest wat anders.
1- De Tabbladen Master en Slave zijn letterlijke kopieën van de site dronebot workshop zie de link
Ik heb alleen wat nederlands commentaar toegevoegd / vertaald.
Dan de oplossing waar ik bij toeval achter kwam en onvoorstelbaar simpel is.
Bij meerdere tabbladen is het blijkbaar mogelijk om op zichzelf staande programma's te gebruiken die met een directive afhankelijk gecompileerd kunnen worden.
Ter verduidelijking mijn laatste volledige listings.
Eerste tabblad
/* Samengevoegd programma om 2 arduino mega's met elkaar te laten communiceren.
De oorspronkelijke Master en Slave software is van dronebot workshop en de tutorials zijn te vinden op:
https://dronebotworkshop.com/i2c-arduino-arduino/
Het geheel bestaat uit 3 tabbladen waarvan tabblad Master en tabblad Slave letterlijk zijn overgenomen
van voornoemde tutorials en voor dit samengestelde programma voorzien van de compile directive #ifdef Master
en #ifndef Master.
Voor mijn persoonlijk gebruik heb ik de directive toegevoegd die een foutmelding geeft ingeval er een ander
board dan een Mega gekozen is. Deze directive heb ik voor het plaatsen op het forum tijdelijk disabled met
multiline comment tekens.
Dit tabblad bevat alleen de define Master waardoor de compiler de software voor het Master board wordt
gegenereerd. Wordt deze constante verwijderd of met single qoute als commentaar gemaakt, dan wordt de Slave
software gegenereerd.
*/
// Constanten ------------------------------------------------------------
#define MASTER
// Programma =======================================================
Tweede tabblad
#ifdef MASTER
/*
I2C Master Demo
i2c-master-demo.ino
Demonstrate use of I2C bus
Master sends character and gets reply from Slave
DroneBot Workshop 2019
https://dronebotworkshop.com/i2c-arduino-arduino/
*/
// Libraries --------------------------------------
#include <Wire.h> // voor de i2c bus
// Objecten --------------------------------------
// Constanten --------------------------------------------------------
#define SLAVE_ADDR 9
#define ANSWERSIZE 5 // Slave antwoord size
// globale variabelen ------------------------------------------------
// Programma =========================================================
void setup()
{ Wire.begin(); // Initialiseert I2C communicatie als Master
Serial.begin(9600); // Setup serial monitor
Serial.println("I2C Master Demonstration");
}
void loop()
{ delay(50);
Serial.println("Write data to slave");
Wire.beginTransmission(SLAVE_ADDR); // Write a charatre to the Slave
Wire.write(0); // hiermee vraag je de slave om data
Wire.endTransmission(); // stopt zenden
Serial.println("Receive data");
Wire.requestFrom(SLAVE_ADDR, ANSWERSIZE); // Read response from Slave Read back 5 characters
String response = ""; // maakt variabele leeg
while (Wire.available()) // Add characters to string
{ char b = Wire.read(); // leest karakter uit slave
response += b; // plakt gelezen karakter aan reeds ontvangen karakters
}
Serial.println(response); // Print to Serial Monitor
}
// Einde Programma en compile directive ==============================
#endif
/*
#if !defined(__AVR_ATmega2560__)
#error "Oeps! Zorg ervoor dat 'Arduino Mega' is geselecteerd als board in het menu."
#endif
*/
Derde tabblad
#ifndef MASTER
/*
I2C Slave Demo
i2c-slave-demo.ino
Demonstrate use of I2C bus
Slave receives character from Master and responds
DroneBot Workshop 2019
https://dronebotworkshop.com/i2c-arduino-arduino/
*/
// Libraries ---------------------------------------------------------
#include <Wire.h>
// Objecten ----------------------------------------------------------
// Constanten --------------------------------------------------------
#define SLAVE_ADDR 9
#define ANSWERSIZE 5 // Slave antwoord size
// globale variabelen ------------------------------------------------
String answer = "Hello"; // Define string with response to Master
// Programma =========================================================
void setup()
{ Wire.begin(SLAVE_ADDR); // Initialize I2C communications as Slave
Wire.onRequest(requestEvent); // Function to run when data requested from master
Wire.onReceive(receiveEvent); // Function to run when data received from master
Serial.begin(9600); // Setup Serial Monitor
Serial.println("I2C Slave Demonstration");
}
void loop()
{ delay(50); // Time delay in loop
}
void receiveEvent() // het karakter dat de master zend
{ while (0 < Wire.available()) // Read while data received
byte x = Wire.read();
Serial.println("Receive event"); // Print to Serial Monitor
}
void requestEvent() // de 5 karakters die de master wil ontvangen
{ byte response[ANSWERSIZE]; // omdat 5x een byte wordt verwacht moet het antwoord uit 5 bytes bestaan
for (byte i = 0; i < ANSWERSIZE; i++) // hier wordt hello omgezet in een array van 5x een byte
response[i] = (byte)answer.charAt(i); // hier worden de bytes 1 voor 1 klaat gezet
Wire.write(response, sizeof(response)); // Send response back to Master
Serial.println("Request event"); // Print to Serial Monitor
}
// Einde Programma en compile directive ==============================
#endif
/*
#if !defined(__AVR_ATmega2560__)
#error "Oeps! Zorg ervoor dat 'Arduino Mega' is geselecteerd als board in het menu."
#endif
*/