2 Masters 1 Slave -...
 
Notifications
Clear all

2 Masters 1 Slave - I2C

15 Posts
3 Users
1 Likes
2,393 Views
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

Hi

I need to share 1 LCD display between 2 Arduinos. I remember Bill saying in one of his video that it is possible but subject to the condition that it is known which master is sending data to the slave.

My idea is simple assign pins D2 on both masters as INPUT "lcdSense" and pins D3 as OUTPUT "lcdWrite". D2 of one master would be connected to D3 of the other. When master A is to send data to LCD, it will first sense "lcdSense" to check if master B is not writing data to the LCD. If the sense signal is LOW, it will make its "lcdWrite" pin HIGH to tell master B that master A is writing data. After finishing writing data to LCD master A will make its "lcdWrite" pin LOW. Master B will use the LCD in similar fashion. I don't know if it will work or not.

Or guide me how to do it. Thanks


   
Quote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

I think you should try it your way first. It could be a great learning experience and I would love to know how it turns out!

An alternative approach to investigate might be to just connect the LCD display to one of the Arduinos, pass only the data you want displayed from the other Arduino and have the first on display the information when you want it. If needed the two boards could be separated much farther a part and serial data passed between them.

Best of luck, please post back how it turns out.


   
Abu-Hafss reacted
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

@ruplicator

Thanks for encouraging me.

I have done it successfully in Proteus, I don't know how will it behave physically.

Here are the codes:

// ------------ Sketch for Arduino A -------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

const byte lcdSense = 2;
const byte lcdWrite = 3;
int counter = 0;

void setup()
{
pinMode(lcdSense, OUTPUT);
digitalWrite(lcdSense, HIGH);
pinMode(lcdSense, INPUT);
pinMode(lcdWrite, OUTPUT);

//while(lcdSense == HIGH);
//{}
digitalWrite(lcdWrite, HIGH);
lcd.init();
lcd.backlight();
}

void loop()
{
counter++;
while (lcdSense == HIGH)
{}
digitalWrite(lcdWrite, HIGH);
lcd.setCursor(0,0);
lcd.print(counter);
digitalWrite(lcdWrite, LOW);
delay(200);

}

2 Masters
 
// -------------- Sketch for Arduino B -----------------------
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

const byte lcdSense = 2;
const byte lcdWrite = 3;
int counter = 0;

void setup()
{
pinMode(lcdSense, OUTPUT);
digitalWrite(lcdSense, HIGH);
pinMode(lcdSense, INPUT);
pinMode(lcdWrite, OUTPUT);

//while(lcdSense == HIGH);
//{}
digitalWrite(lcdWrite, HIGH);
lcd.init();
lcd.backlight();
}

void loop()
{
counter = counter + 2;
while (lcdSense == HIGH)
{}
digitalWrite(lcdWrite, HIGH);
lcd.setCursor(0,2);
lcd.print(counter);
digitalWrite(lcdWrite, LOW);
delay(100);

}

   
ReplyQuote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

I'm not familiar with the outcome of connecting the A4 and A5 output lines together with another processor 's  A4 and A5 lines but it may work just fine. You may have already looked at the specifications and concluded it will work.

Excerpt from you code below: I'm not sure the first 3 lines will set up your sense lines the way you want. I believe they should be replaced with pinMode(lcdSense, INPUT_PULLUP);    If the pin is  defined by pinMode as INPUT and you do a digitalWrite to HIGH it will set the pullup but if it is set by pinMode to OUTPUT  then redefined to input I don't believe the pullup will be set. However, you don't really need a pull-up since one since line is connected to the other's output line and in that case just remove the first two lines.

I love the concept of your project/code and thanks for including the code and schematic. It made it much easier to understand what you were trying to do.

 

void setup() 
{
  pinMode(lcdSense,          OUTPUT);
  digitalWrite(lcdSense,       HIGH);
  pinMode(lcdSense,           INPUT);
  pinMode(lcdWrite,          OUTPUT);
 
  //while(lcdSense == HIGH);
  //{}
  digitalWrite(lcdWrite, HIGH);
  lcd.init();       
  lcd.backlight();  
} 

   
ReplyQuote
(@starnovice)
Member
Joined: 5 years ago
Posts: 110
 

He should have pullup resisters on the I2c lines.

Pat Wicker (Portland, OR, USA)


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

@ruplicator

I had written that sketch about a month ago, I don't remember exactly why I had included those two lines. I resumed working on this project after a long gap. I should have put some remarks. But the fact is that the setup won't work without those lines.


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

@starnovice

Right now, I am simulating on Proteus. Without the pull-up resistors, it is working perfectly in the simulator. However, adding a pull-resistor to the SCL line does not make it work.

 


   
ReplyQuote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

I believe starnovice is right about the input resistors. Bill indicated that the Arduino boards have open collector outputs  on the SDA and SCL. (He wrote: "You should also note that Arduino has open-collector outputs." in the article https://dronebotworkshop.com/i2c-arduino-raspberry-pi/ )  This most likely will not make your project work because you may have multiple problems.

You might want to make sure the LCD still works with just one processor. If that still works you might want to try add back in the second one. There is a good possibility that because you are using the LCD library that both processors are set to master. You may need to get to a lower level control to switch the two processors between being masters.

Take a look at this link that discusses how to use master/slave set up. https://www.arduino.cc/en/Tutorial/MasterWriter

 


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

Though the setup works physically for these testing codes but it doesn't seems to be reliable for some complex codes. Nevertheless, it was a great learning experience.

Now I will try to work on Ruplicator's suggestion in post #2. Or guide me if some other possibility.


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

I am considering to use I2C bus for communication between the 2 arduinos as demonstrated by Bill in the last part of his video. In that case the data will be transmitted to the slave unit and an I2C LCD need to be hooked up with the slave. Wouldn't the slave Arduino be acting as master to the LCD? How will I do that when I have defined to use that Arduino as slave. Please help me understand this issue clearly.

 


   
ReplyQuote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

I like the way your handshake protocol works between the two processors so I would suggest keeping that. I was wondering if  that could be used to assign and unassign a master unit. But I haven't found away the high level library your using to drive the LCD allows you to that. The library that I mentioned in a earlier post has a "begin()" function. When that function is used with an address it sets the processor unit to a slave and when it is used without an address it makes the unit a master. Using your handshake protocol with the begin() function to switch between master and slave might solve the problem of having two masters on the I2C buss at the same time. 


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

I have just finished revising my actual project sketches using I2C bus between a Master and a Slave Arduino. The data is transmitted from Master to Slave and then display data on LCD. However, while simulating on Proteus, the LCD on I2C is not responding. When I tried LCD without I2C, it worked perfectly. I have to use I2C LCD because the components are already soldered. 😥 

So, now the problem is how to access LCD with the Slave Arduino?

The LCD address 0x27 is valid as I have been accessing the LCD. I have also tried with I2C Slave Address 9 but not working.

Here is the part of the code on the Slave:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Bounce2.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

#define HeaterArduino 8 // Address for I2C Slave Arduino
.
.
.
.
.
void setup()
{
.
.
.
Wire.begin(HeaterArduino); // Initialize I2C as Slave
Wire.onReceive(receiveTemp); // Routine to execute when Rx

//--- Initialize LCD ------
lcd.init();
lcd.backlight();
.
.
}

   
ReplyQuote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

I don't think you can send from a slave to a slave. That's why the suggestion, when a processor needs to display something it lowers the handshake line to indicate that it is going to become a master. Then it would issue the "begin()" statement and become the master. It would transmit the data to the LCD and when complete, it could issue a statement like begin(8) to set it's self back to a slave with an address of 8 (the other processor could have a slave address like 9) and set the handshake line back high. Both processors and the LCD would be in slave mode until one of the processors needed to use the LCD.


   
ReplyQuote
(@abuhafss)
Member
Joined: 4 years ago
Posts: 25
Topic starter  

Finally, I managed to get my project in working order by sending the data from slave arduino to master arduino which displays the data on LCD.


   
ReplyQuote
Ruplicator
(@ruplicator)
Member
Joined: 4 years ago
Posts: 127
 

Congratulations! That's a good solution that uses the  components as they were designed to be used.


   
ReplyQuote