0

I am having some trouble connecting my 2 Arduino Nanos with I2C. I have this configuration:

  • SLAVE RECEIVER Nano with DS1037 and LCD 16x02 on I2C.
  • MASTER SENDER Nano.

After some time the Slave receiver prints on LCD random chars. If I delete the line including library RTCLIB.h everything is working except the clock. Thanks for your help :D

Slave receiver code:

#include <Wire.h> // include la libreria
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

LiquidCrystal_I2C lcd(0x3E, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
RTC_DS1307 RTC; // orologio

static int anno;
static int giorno;
static int mese;
static int ora;
static int secondo;
static int oldSecondo;
static int minuto;
static int oldMinuto;
static int annoGrezzo;

//------------------------------------------------------------
// si ripete la union esattamente come nel master
union Scomp_float {
  // si utilizza union x float
  float temp;
  char byte_s[4];
} S_float;

//------------------------------------------------------------
// si ripete la union esattamente come nel master
union Scomp_long {
  // si utilizza union x long
  long int mioL;
  char byte_sL[4];
} S_long;

//------------------------------------------------------------
//------------- byte temporanei
byte f0 = 0;   // contengono i byte ricevuti
byte f1 = 0;
byte f2 = 0;
byte f3 = 0;
byte a1 = 0;
//-------------------------------------------------------------
//  qui si introdurranno i dati ricomposti dopo la trasmissione
long int masterLong = 0;
float masterFloat = 0;
int masterInt = 0;
//--------------------------------------------------------------

void setup() {
  Wire.begin(80);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  lcd.begin(16, 2);
  Serial.begin(9600);           // start serial for output
  //-----------orologio-----------
  RTC.begin();
  // Check to see if the RTC is keeping time.  If it is, load the time from your computer.
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // This will reflect the time that your sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  //-----------fine orologio-----------
}

void loop() {
  //------------------------------------------------------------
  //   si stampano i dati ricevuti e ricomposti
  //------------------------------------------------------------
  Serial.println(masterInt);
  Serial.println(masterLong);
  Serial.println(masterFloat);
  DateTime now = RTC.now();
  annoGrezzo = now.year();
  anno = ( annoGrezzo % 100);
  mese = now.month();
  giorno = now.day();
  ora = now.hour();
  minuto = now.minute();
  lcd.setCursor(0, 0);
  lcd.print(masterInt);
  lcd.setCursor(0, 1);
  lcd.print(giorno);
  lcd.print(" ");
  lcd.print(mese);
  lcd.print(" ");
  lcd.print(anno);
  lcd.print("  ");
  lcd.print(ora);
  lcd.print(":");
  lcd.print(minuto);
  delay (1000);
  lcd.clear();
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  if (howMany == 2) {
    // se in arrivo due dati
    f0 = Wire.read(); // si leggono i byte
    f1 = Wire.read();
    masterInt =  ((f1 << 8) | f0); // si ricompone l'intero
  }

  if (howMany == 4) {
    // se in arrivo 4 dati è un float
    f0 = Wire.read();  // si leggono i byte
    f1 = Wire.read();
    f2 = Wire.read();
    f3 = Wire.read();
    S_float.byte_s[0] = f0; // si ricompone il float
    S_float.byte_s[1] = f1;
    S_float.byte_s[2] = f2;
    S_float.byte_s[3] = f3;
    masterFloat = S_float.temp;
  }

  if (howMany == 5) {
    // se in arrivo 5 dati è un long
    f0 = Wire.read();  // si leggono i byte
    f1 = Wire.read();
    f2 = Wire.read();
    f3 = Wire.read();
    a1 = Wire.read();
    S_long.byte_sL[0] = f0;  // si ricompone  il long
    S_long.byte_sL[1] = f1;
    S_long.byte_sL[2] = f2;
    S_long.byte_sL[3] = f3;
    masterLong = S_long.mioL;
  }
}

Master sender code:

#include <Wire.h> // si include la libreria
//---------------------------------------------------------
union Scomp_float {
 // si utilizza union x float
  float temp;
  char byte_s[4];
} S_float;
//---------------------------------------------------------
union Scomp_long {
 // si utilizza union x long
  long int mioL;
  char byte_sL[4];
} S_long;
//----------------------------------------------------------
// questi sono i dati che si vogliono trasmettere

long int mioLong = 1234567801;
float mioFlo = 123456.29;
//----------------------------------------------------------
byte a1 = 0; // conterrà i primo byte dell'int
byte a2 = 0; // conterrà il secondo byte dell'int
byte f0 = 0; // contengono i byte del float e del long
byte f1 = 0;
byte f2 = 0;
byte f3 = 0;
void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

void loop() {
  int mioInt = random(30000);
 //-----------------------------------------------------
 // trasmissione di un intero ( 2 byte)
 //-----------------------------------------------------
  a1 = byte(mioInt); // si scompone l'intero in 2 byte
  a2 = byte( mioInt >> 8);
  Wire.beginTransmission(80); // inzia trasmissione allo slave

  Wire.write(a1); //  invia un byte
  Wire.write(a2); //  invia il secondo byte
  Wire.endTransmission(); // stop transmitting
 //------------------------------------------------------
  delay (2000);
 //------------------------------------------------------
 // trasmissione intero lungo 4 byte
 //------------------------------------------------------
  S_long.mioL = mioLong; // si scompone in 4 byte
  f0 = S_long.byte_sL[0];
  f1 = S_long.byte_sL[1];
  f2 = S_long.byte_sL[2];
  f3 = S_long.byte_sL[3];
  a1 = 1; // si trasmette questo byte solo per segnalare allo slave
 // che stiamo trasmettendo un long
 // una volta scomposto si trasmettono i 4 byte
  Wire.beginTransmission(80); // trasmette allo slave
  Wire.write(f0); // invia un byte
  Wire.write(f1); //
  Wire.write(f2); //
  Wire.write(f3); //  invia un byte
  Wire.write(a1);
  Wire.endTransmission(); // fine trasmissione
 //-------------------------------------------------------
  delay (2000);
 //------------------------------------------------------
 //   trasmissione di un float 4 byte
 //------------------------------------------------------
  S_float.temp = mioFlo; // si scompone in 4 byte
  f0 = S_float.byte_s[0];
  f1 = S_float.byte_s[1];
  f2 = S_float.byte_s[2];
  f3 = S_float.byte_s[3];
 // una volta scomposto si trasmettono i 4 byte
  Wire.beginTransmission(80); // trasmette allo slave
  Wire.write(f0); // invia un byte
  Wire.write(f1); //
  Wire.write(f2); //
  Wire.write(f3); //  invia un byte
  Wire.endTransmission(); // fine trasmissione
 //-------------------------------------------------------
  delay (3000);
}
//------ end master ----------------------------------
  • 1
    AFAIK you can't control the I2C if you are a slave. Slaves only respond to the master's requests, but can't start a communication (for instance to an LCD). If you want your slave to control the LCD screen, then make another I2C bus where the slave is the master, or make the master control the LCD directly. Or connect the master and the slave through another bus (SPI, serial, ...) and make the slave the new master... – frarugi87 Feb 1 '17 at 11:36
  • can help me to convert this to Master reader/Slave receiver i try without result... tnks for help – Francesco Valla Feb 1 '17 at 14:34
0

i partially resolve the problem with this:

MASTER RECEIVER code:

#include <Wire.h> // include la libreria
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

LiquidCrystal_I2C lcd(0x3E, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
RTC_DS1307 RTC; // orologio

static int anno;
static int giorno;
static int mese;
static int ora;
static int secondo;
static int oldSecondo;
static int minuto;
static int oldMinuto;
static int annoGrezzo;
char t[10] = {};
char v[10] = {};

void setup()
{
  Wire.begin();                // join i2c bus with address #4
  lcd.begin(16, 2);
  Serial.begin(9600);           // start serial for output

  //-----------orologio-----------

  RTC.begin();
  // Check to see if the RTC is keeping time.  If it is, load the time from your computer.
  if (! RTC.isrunning())
  {
    Serial.println("RTC is NOT running!");
    // This will reflect the time that your sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  //-----------fine orologio-----------




}

void loop()
{
  //------------------------------------------------------------
  //   si stampano i dati ricevuti e ricomposti
  //------------------------------------------------------------
  Wire.requestFrom(8, 3);
  int i = 0;
  while (Wire.available()) {
    t[i] = Wire.read(); // every character that arrives it put in order in the empty array "t"
    i = i + 1;
  }
  Wire.requestFrom(8, 3);
  i=0;
  while (Wire.available()) {
    v[i] = Wire.read(); // every character that arrives it put in order in the empty array "v"
    i = i + 1;
  }
  Serial.println(t);
  DateTime now = RTC.now();
  annoGrezzo = now.year();
  anno = ( annoGrezzo % 100);
  mese = now.month();
  giorno = now.day();
  ora = now.hour();
  minuto = now.minute();
  lcd.setCursor(0, 0);
  lcd.print(t);
  lcd.setCursor(5,0)
  lcd.print(v);
  lcd.setCursor(0, 1);
  lcd.print(giorno);
  lcd.print(" ");
  lcd.print(mese);
  lcd.print(" ");
  lcd.print(anno);
  lcd.print("  ");
  lcd.print(ora);
  lcd.print(":");
  lcd.print(minuto);


  delay (1000);
  lcd.clear();
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()

SLAVE SENDER code:

#include <Wire.h> // si include la libreria 
//---------------------------------------------------------

char t[10];
char v[10];

void setup()
{
  Wire.begin(8); // join i2c bus (address optional for master)
   Wire.onRequest(requestEvent);
}




void loop()
{
 int mioInt = random(30000);
 int mioInt2 = 1234;
  dtostrf(mioInt, 3, 2, t); //convers the float or integer to a string. (floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, empty array); 
  dtostrf(mioInt2, 3, 2, v);
//------------------------------------------------------
delay (500);
}
void requestEvent() {
  Wire.write(t);
  Wire.write(v);
}
//------ end slave    ----------------------------------

now my problem is the second variable T im unable to receive it on Master. Thanks for help

  • Only the Master is now the Master and the RTC, the I2C display and the Slave Nano are all Slaves. That is good, there will be no more collisions on the I2C bus. You have to know what kind of data you want to transmit. A zero terminated string is not the best option. You could send two integers at once or a struct with values. It is easier to send a single data package. In the Slave, the requestEvent() is run from an interrupt. Therefor the variabeles that you send must be made 'volatile' and the if they are used in the loop() the interrupts have to be turned off temporarily in the loop(). – Jot Feb 1 '17 at 15:23
  • how? im a little bit confused, with one no problem its the second the problem.. i understand how it work with one. thanks for reply – Francesco Valla Feb 1 '17 at 15:32
  • For example with "int x[2];". Transmit them with "Wire.write((char *)x, 4);". In the Master, request 4 bytes, use also a "int x[2];" and you could use "Wire.readBytes((char *)x, 4);" to read the data into the integers. The problem you have is not the second one, it is the way you use the two strings. Therefor a single package will be better. – Jot Feb 1 '17 at 15:38
  • If this solved your problem please accept your own answer, other Stack Exchange considers the question not answered appropriately. – Nick Gammon Sep 2 '17 at 7:33
0

I don't know what your problem is, but you have a gross error at LiquidCrystal_I2C lcd(0x3E, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);. You have a I2C LCD display but you are using it as an old-style LCD initialization.

The correct initialization for and I2C LCD display is

LiquidCrystal(0x2A, 16, 2);

You have to replace 0x2A for the correct I2C address of your LCD display (Use a I2C scanner sketch for that).

You have to check the API of your libraries first (usually a .h file):

    /**
     * Constructor
     *
     * @param lcd_addr  I2C slave address of the LCD display. Most likely printed on the
     *                  LCD circuit board, or look in the supplied LCD documentation.
     * @param lcd_cols  Number of columns your LCD display has.
     * @param lcd_rows  Number of rows your LCD display has.
     * @param charsize  The size in dots that the display has, use LCD_5x10DOTS or LCD_5x8DOTS.
     */
LiquidCrystal_I2C(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t lcd_rows, uint8_t charsize = LCD_5x8DOTS);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.