Hi Golam,
I tested your code with two Arduino Pro Micro as I don't have Leonardos at hand.
It works.
One problem that newcomers have is that Demo-Codes are mostly rather small documented. And that the demo-codes don't give hints about possible hardware-problems or restrictions.
Additionally this demo-code shows
-
how to use debug-output that prints a fixed text the variable-NAME and the variable-VALUE all in one line.
-
there is even a "intervalled" version where you can define how often the output shall be printed. This is very handy for fast running loops
-
an easy to use non-blocking timing
-
how to use functions
and serial debugoutput that gives feedback about what lines of code have been executed
So here is the modified sender-code
// start of macros dbg and dbgi
// You don't have to understand immidiately what the macro-code
// inside these two macros does. Macros work on a different level than code
// just use them as described below
// with the macros you can add serial debug-output with a single line of code
// that does print a fixed text the variable-NAME and the variables VALUE
// if you already know these lines delete them
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope
#define dbgi(myFixedText, variableName,timeInterval) \
do { \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
} while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
// The I2C-Bus was designed for exchanging data over SHORT distances = SHORT wires
// 10cm up to 50 cm. Everything that goes beyond 1m can be problematic
// if you want to send/receive data over a longer distance with I2C there are
// specialised long distance I2C-chips available
// the easier solution is to use serial based on RS485 which is very good protected
// against electromagnetic noise
// the REAL code starts here but makes use of the macros above
#include <Wire.h>
// helperfunction telling the serial-monitor the sourcecode file and compiletime
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__));
Serial.print( F(" compiled ") );
Serial.print(F(__DATE__));
Serial.print( F(" ") );
Serial.println(F(__TIME__));
}
// helper-function for easy to use non-blocking timing
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 2;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
void setup(){
// one of the very rare cases where a delay makes sense
// an Arduino pro Micro needs some time to establish the serial connection
delay(2000);
Serial.begin(115200);
delay(2000);
Serial.println( F("Setup-Start") );
PrintFileNameDateTime();
Wire.begin(); // get on the bus
dbg("Wire.begin() done",0);
Wire.beginTransmission(9);
dbg("Wire.beginTransmission(9)",1);
byte busStatus = Wire.endTransmission();
dbg("busStatus = Wire.endTransmission()",busStatus);
if (busStatus != 0) {
Serial.print("Slave is not found.");
while (1);
}
Serial.print("Slave is found.");
}
void requestToSlave() {
dbg("entering requestToSlave()",10);
Wire.requestFrom(9, 5); //string to receive "ab01z"
dbg("Wire.requestFrom(9, 5); done",11);
Serial.print("received from slave: #");
for (int i = 0; i < 5; i++) {
char x = Wire.read();
Serial.print(x);
}
Serial.println("#");
}
void loop(){
BlinkHeartBeatLED(OnBoard_LED,500);
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
requestToSlave();
}
}
and here the modified receiver-code
// start of macros dbg and dbgi
// You don't have to understand immidiately what the macro-code
// inside these two macros does. Macros work on a different level than code
// just use them as described below
// with the macros you can add serial debug-output with a single line of code
// that does print a fixed text the variable-NAME and the variables VALUE
// if you already know these lines delete them
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope
#define dbgi(myFixedText, variableName,timeInterval) \
do { \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
} while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__));
Serial.print( F(" compiled ") );
Serial.print(F(__DATE__));
Serial.print( F(" ") );
Serial.println(F(__TIME__));
}
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod ){
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 13;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer,BlinkPeriod) ) {
digitalWrite(IO_Pin,!digitalRead(IO_Pin) );
}
}
// The I2C-Bus was designed for exchanging data over SHORT distances = SHORT wires
// 10cm up to 50 cm. Everything that goes beyond 1m can be problematic
// if you want to send/receive data over a longer distance with I2C there are
// specialised long distance I2C-chips available
// the easier solution is to use serial based on RS485 which is very good protected
// against electromagnetic noise
#include <Wire.h>
void setup(){
// one of the very rare cases where a delay makes sense
// an Arduino Leonardo needs some time to establish the serial connection
delay(2000);
Serial.begin(115200);
delay(2000);
Serial.println( F("Setup-Start") );
PrintFileNameDateTime();
Wire.begin(9); // get on the bus
dbg("Wire.begin(9) done",0);
Wire.onRequest(sendEvent);
dbg("Wire.onRequest(sendEvent); done",1);
}
void sendEvent() {
dbg("entering sendEvent()",10);
Wire.print("ab01z"); //sending this string: "ab01z" to Master when asked.
dbg("Wire.print("ab01z") done",11);
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED,500);
if ( TimePeriodIsOver(MyTestTimer,1000) ) {
}
}
best regards Stefan