This is my first ever post in arduino forum. I am stuck badly in a problem. I need to set one UNO as master writer and other as slave receiver. I tried the basic example which comes with IDE but it doesnot run perfectly.
In the basic example the master is supposed to write continuously from x=0 and incrementing each time the loop runs. And slave has to display the received byte as " x = …"
However i only get x = 1. however what expected is someting like
x = 0
x = 1
x = 2
… so on
Please any one has some experience of using uno as master writer and uno as slave receive ?
I have attached the screen shot for simulation.
Hi, welcome to the forum.
First of all: simulations often don’t work very well. They will cost time and frustration. Stay in the real world 8)
Can you give a link to the sketch that you use ? Is it the MasterWriter example ? https://www.arduino.cc/en/Tutorial/MasterWriter
Sorry, but that example is not very good. The receiveEvent() function is an interrupt handler and should be very short. No delay or Serial function should be used.
Let’s make a simple Master Writer, just a counting byte:
Wire.begin(); // join i2c bus (address optional for master)
byte x = 0;
Wire.beginTransmission(4); // transmit to device #4
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting
In the Slave, set a global variable and a flag. Use the flag to communicate between the interrupt handler and the loop(). If it doesn’t work, I can test it.
volatile byte x;
volatile boolean flagReceived = false;
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
flagReceived = false;
Serial.println(x); // print the character
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
x = Wire.read(); // receive byte as a character
flagReceived = true;
Well first of all i would like to thank you for your reply and appreciate it a lot. Yes you are right in saying that simulation quite often dont run as expected.
The example you pointed out is the one i was trying to simulate. I tried your code on the simulator as well but same result. For first two byte transferred i receive an ACK and for the rest other i get ACK for address packet but for data packet/frame it sends a NACK. Actually i dont have hard ware right now so i was just trying for a proof of concept.
What i actually want is that master first polls the slaves (for which i2c polling function is available) and if there is some conflict between any two slave addresses the master dynamically changes the address of slave at runtime so that there is no conflict between slaves.
This example was just first step as i was planning to simulate whole my task but the problem is that slave receiver sends NACK to data frames except for first two bytes.
I have attached the simulation image in which ACKs are marked in red box
Could you kindly suggest me any other ways in order to accomplish this?
I can try to find two Arduino Uno boards and run my test sketches, but only after you have tried it (with real Arduino boards).
On this forum there are always many problems with simulators. It is like I wrote before: they will cost time and will cause frustration. Do not assume that the outcome makes any sense at all. Trust me, it is a total waste of time. For example a timing problem between an Arduino board and a sensor is something that a simulator can not handle.
Simulators are okay for OpAmps and transistors and so.
Two Slaves with the same I2C address will always be a problem. They will probably respond just as fast to the address, so you would never know that there are two Slaves.
The Arduino Wire library is not written to handle collisions.
I think it can not be done.
The datasheet of the ATmega328P microcontroller has a section about collision on the I2C bus. But I still don't know if it is possible to have two Slaves with the same address.
It is allowed to send data to every Slave. Nick Gammon tried the 'broadcast' : Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino
Could that be used to detect if two Slaves have the same address ? I don't know. I don't think so.
I think what you want is what the SMBus has : System Management Bus - Wikipedia
However, there is no library for the SMBus for the Arduino.
Thanks once again.
Actually my requirement is such that i can change address of any slave at runtime. I put it to you like this.
Master powered up and polled the slaves on i2c bus. it stored their addresses but it found that one address of a slave is repeating so it will immediately tell the slave that you need to change your address and lets say 14 is your new address. So now the slave will get address 14.
Could i achieve it using i2C?
That reads like there are two 14s. How does one change and not the other?
You are right. i did not think about this. So it will be a problem. How i can accomplish my requirement.
"I think it can not be done"
When every Slave starts with a special address, like 0x22, then the Master can detect that address and assign a new address to it. Or every Slave could have a button to initialize. Or some special ID is stored in EEPROM.
That is only possible for one Slave at a time.
However, when two Slave modules have the same I2C address, then everything is bound to go wrong. I think it can not be fixed, once that happens. The I2C bus was never designed for that.
Thats not a good news :(.
Do you have any other approach in mind through which such a task could be done?
Can you tell about the project. How many Slave modules did you have in mind ? Can modules randomly be connected and disconnected ? Or will there be only one new module at power up ? With long wires ?
It is possible to use a mux and switch between a few I2C busses. But that is not a nice solution.
The OneWire bus is designed to attach more devices to it, and it will never go wrong, because every chip has an unique identifier.
With a serial daisy-chain, many modules can be linked together.
The best solution might be a 'net' of wireless modules.