multiple i2c can't work with arduino uno - arduino

I am trying to connect 2 I2C modules to arduino uno. GY86(HMC5883L,MS5611,MPU6050) and BMP085 or any other I2C module. When i test each one separately it works ok but when both are connected to the I2C bus port, Every thing ruins. th moment i connect the BMP module, GY86 starts to output wrong numbers. I also tested my GY86 with DS1307 module. same thing happens and the moment i connect them, the DS starts to output wrong random output. i tried to apply a pull up resistor for SDA and SCL but didn't work. Whats the problem?

I2C at the Hardware Level
Signals
Each I2C bus consists of two signals: SCL and SDA. SCL is the clock signal, and SDA is the data signal. The clock signal is always generated by the current bus master; some slave devices may force the clock low at times to delay the master sensing more data.
Unlike UART or SPI connections, the I2C bus drivers are "open drain", meaning that they can pull the corresponding signal low, but cannot drive it high. Thus, there can be no bus contention where one device is trying to drive the line high while another tries to pull it low, eliminating the potential for damage to the drivers or excessive power dissipation in the system. Each signal line has a pull_up resistor on it, to restore the signal to high when no device is asserting it low.
Resistor selection varies with devices on the bus, but a good rule of thumb is to start with 4.7k and adjust down.
Signal Levels
Since the devices on the bus don't actually drive the signals high, I2C allows for some flexibility in connecting devices with different I/O voltages. In general, in a system where one device is at a higher voltage level than another, it may be possible to connect the two devices via I2C without any level shifting circuitry in between them. The trick is to connect the pull_up resistor to the lower of the two voltages. This only work in some cases, where the lower of the two system voltages exceeds the high-level input voltage of the higher voltage system - for example, a 5V Arduino and a 3.3V accelerometer.
Protocol
Communication via I2C is more complex that with UART or SPI solution. The signalling must adhere to a certain protocol for the devices on the bus to recognize it as valid I2C communications.
Basics
Messages are broken up into two types of frame: an address frame, where the master indicates the slave to which the message is being sent, and one or more data frames, which are 8-bit data messages passed from master to slave or vice versa. Data is placed on the SDA line after SCL goes low, and is sampled after the SCL line goes high. The time between clock edge and data read/write is defined by the devices on the bus and will vary from chip to chip.
Start Condition
To initiate the address frame, the master device leaves SCL high and pulls SDA low. This puts all slave devices on notice that a transmission is about to start. If two master devices wish to take ownership of the bus at one time, whichever device pulls the SDA low first wins the race and gains control of the bus. It is possible to issue repeated starts, initiating a new communication sequence without relinquishing control of the bus to other masters.
Address Frame
The address frame is always first in any new communication sequence. For a 7-but address, the address is clocked out most significant bit (MSB) first, followed by a R/W bit indicating whether this is a read (1) or write (0) operation.
The 9th bit of the frame is the NACK/ACK bit. This is the case for all frames (data or address).
Once the 8 bit of the frame are sent, the receiving device is given control over SDA. If the receiving device does not pull the SDA line low before the 9th clock pulse, it can be inferred that the receiving device either did not receive the data or did not know how to parse the message. In that case, the exchange halts, and it's up to the master of the system to decide how to proceed.
Data Frames
After the address frame has been sent, data can begin being transmitted. The master will simply continue generating clock pulses at a regular interval, and the data will be placed on SDA by either the master or the slave, depending on whether the R/W bit indicated a read or write operation. The number of data frames is arbitrary, and most slave devices will auto-increment the internal register, meaning that subsequent reads or writes come from the next register in line.
Stop Condition
Once all the data frames have been sent, the master will generate a stop condition. Stop conditions are defined by a 0->1 (low to high) transition an SDA after a 0->1 transition on SCL, with SCL remaining high. During normal data writing operation, the value on SDA should not change when SCL is high, to avoid stop condition.

I think several devices have same address. That's why you receive bad data. Usually I2C devices have extra pins to setup lower bits of addr. Do it and don't forget to change corresponding software definitions.
Update:
MPU6050 has input pin, which specifies LSB of I2C addr. You need tie this pin to high level 3.3V. Otherwise MPU6050 will have same addr as DS1307. I know it for sure, because work with both ICs a lot. To do it you need broke wire between 9nth pin of MPU6050 and Gnd. And solder it through resistor >3k to 3,3V. Or not use DS1307. From memory there is ds1302 rtc module.
You should find datasheets for all ICs you use and check what are their I2C addresses. The board consists of three parts, so you must know those 3 addresses.

Related

Using Serial Peripheral Interface (SPI) to talk to several slaves simultaneously

I have four Atmega328p in a single board and I want one of them send the same data (i.e. sensor readings) to the other three simultaneously. I'm not interested in a bidirectional communication. I read this thread (How can I broadcast data to multiple SPI slaves and how it works?) about SPI broadcasting, and someone mentioned not being possible because in SPI communication is full duplex and MISO and MOSI lines are active at the same time. However, I was wondering if I could just let the MISO lines unconnected and all SS pins pulled low, so I could broadcast a message to all slaves simultaneosly, taking into account that I do not need any type of response from the slaves to the master.
So, is this possible? Or how else could I work around this problem? I was also considering on using UART's Tx line and connect all the receivers in parallel to it, but I'm not sure that would work too.
Thanks for your attention.

Sending fixed voltage to serial port

I need to monitor if a door is opened. I have a sensor that continues to generate +5V DC as long as the door is shut but drops down to 0V once the door is opened.
I now need to connect the sensor's output wire to PC's serial port and write a program that continuously polls the port.
My thought is that various serial-io parameters such as baud rate, etc., does not matter in my case. For each byte that I read, I expect the value to be 255 (logical 1s) when the door is closed. Otherwise, I will assume that the door has been opened. Is there any flaw in this logic?
I went through Sending a voltage to RS232. It appears I just need to connect the wire to pin 2 (RX). However, for the serial port to receive a logical 1, it seems the voltage needs to be between -3V and -12V. As the voltage my sensor generates is positive, I am thinking I will connect the sensor wire to pin 5 (GND) instead and connect pin 2 to ground. In effect, I inverted the voltage. Will this work?
If this logic is flawed, I may have to buy a voltage inverter.
Finally, I was told that one should not connect anything to pin 5 on a motherboard's serial port. Apparently, it is hardwired to get grounded to the chassis. Is this true? Regards.
Like mentioned in the comments, constant high would not produce 255 bytes.
I would implement this by connecting the GND to GND and connecting the +5 Vdc to the CTS pin, which can be queried for his HIGH / LOW state.
But this is only a hack, you really should use some microcontroller.

Arduino: Packet loss on Serial communication

I am trying connect multiple Arduino Mega Boards via their Serial pins to allow communication between the boards. I want to be able to connect an arbitrary amount of arduinos by daisy-chaning them and I want one board to be the master, taking control over the actions of the other boards. The master should be determined dynamically by the boards. I am aware that the daisy chaining method introduces delays to the communication due to the forwarding of packets, but so far I am planning on connection 4 boards at most. In the future this might increase to maybe 10 boards. My boards all have a separate power source, since they are connected to some other hardware which has its own power source.
My idea was to connect the boards in such a way, that the master would be determined by the wireing of the boards. I thought about having the "Serial" port as 'To-Master' serial port and the "Serial1" port as "To-Child" serial port. The boards send hello messages on the "To-Master" serial port and the master replies if it received such a message on the "To-Child" serial port. If no answer is received after some seconds, the board determines itself to be the master.
I wired the boards up by connecting the ground pins, and wiring RX1 of the master to TX0 of the child and TX1 of the master to RX0 of the child:
Basically my setup is working, since the boards do detect each other and exchange hello messages and replies. There is however a significant amount of packet loss or corruption which I would like to eliminate.
As a simple measure of packet verification, I begin each packet with a "magic number". The receiving board looks for this byte and only tries to read a packet after receiving this byte. Any other bytes received are simply discarded.
As it seems, it happens quite often that something is received on either serial port that does not start with the magic number and is therefore discarded. The timestamps of these events are however consistent with the timestamps of sending of the other board meaning that the packet was at least partially transmitted but somehow the magic byte got corrupted or discarded.
Is this a known problem with the arduinos serial ports?
Can it be related to my wiring?
Are there any measures I can take to ensure a save delivery of the packets?
Can it be a problem of the boards not reading the signal at the correct time (I used a baud rate of 9600)?
I also looked into I2C communication, but I did not find any resource or information if it is possible to dynamically choose the master for this type of communication. Also in the documentation it stated, that it is important that all devices share a common power source which is not possible in my scenario. However, the basic master-slave principle of this I2C conforms with my requirements, as I have a master that sends commands to all other boards. Could I2C be utilized in my case?
Thank you for your thoughts!
Here is a discussion about multi-master I2C topology of Arduinos, seems that it is supported (haven't tested it myself). - http://forum.arduino.cc/index.php/topic,13579.0.html
You can test SPI as well, here is a comparison between the two - http://components.about.com/od/Theory/a/Selecting-Between-I2c-And-Spi.htm.
Slave might be selected with generic GPIOs
I don't know any known implementation of multi-clients on top of Serial bus (usually it is intended for peer2peer communication only) - even though, your configuration seems reasonable, I would be considering other options.
BTW, from your comment about different power sources, I assume your boards are away from each-other. Have you considered very cheap ($2) RF modules, such as nRF24L01+ (http://maniacbug.wordpress.com/2011/11/02/getting-started-rf24/). THere is a library for networking those in multi-node network
Might be better off with I2C or SPI like people have suggested here.
However, to address your question directly, it is most likely wiring. I am assuming you are using cheap jumper wires to plug directly into the Arduino Headers. Noise on this connection is the most likely problem or garbled serial messages. Try implementing with twisted pair cables and connecting directly to the board.
SPI or I2C might have better error correction than your customer serial protocol. I would see the other answers for that.

Gathering/reading data from sensors on two different baud rates with Arduino

I want to use an Arduino to gather data from two sensors. This seems easy when the required baud rate for two sensors is the same. However, I'm stumped as how to go about doing this when two different rates are required.
For example, suppose I want to use a barometer and a GPS sensor at the same time. I imagine I'd have to modify something lower-level for one of the sensors (possibly in the libraries or supporting functions), but where do I begin?
Having a look at the provided material, I can see that your hardware use serial communications. The barometer uses an I²C port and the GPS a serial port.
The "communication speed" (or baud rate) does not have to be exactly the same for all devices. Indeed, your sensors may have different sample rate or different needs, and thus does not need to communicate with the central unit with the same frequency.
I would suggest to go step by step. Try first with the GPS sensor. I think serial ports are easier to start with. Try first (a) to communicate directly with the GPS through your computer (you can use your Arduino to set up a USB-serial connection), and later (b) try to write some code which communicates in the same way with the GPS but now from Arduino.
Simple method for Doing this. You have two Serial Port
SoftwareSerial
hardwareserial
In software Serial is one You communicate Directly . in hardware serial you configured for particular pin as Tx and Rx pin. SO barometer you can use SoftwareSerial and for GPS you can use Hardware Serial.
[1]: http://arduino.cc/en/Reference/SoftwareSerial
[2]: http://forum.arduino.cc/index.php?topic=49645.0

I2C, pullup resistors (STM32 discovery)

I am sending my data trought I2C (using DMA every 1s).
I´ve added two pullup-resistors to SCK and SDATA.
There are now slaves, so because no respond, master send only slave adress and thats all.
Its testboard so sometimes happend thats I loose these pullup resistors for a while.
When this happend I get no data more and SCK ticks so fast as posible for this frequency.
There is no way how to fix it, pullpups back didnt help, I have to reset my board.
I cant explain this behaviour and its totally kill the bus.
As you have seen already by yourself, pullup resistors are vital for the i2c bus, both in the sda and scl lines. It is usually obvious that the sda line is bidirectional, what is not so obvious is that the scl is also somewhat bidirectional, since slaves can maintain the line low to throttle down the speed of the bus.
In many cases the bus can become locked because of a collision or other physical problem like loosing your pullups, in such a case, some slaves don't release the bus properly because they understand that they are still being addressed. This situation can be fixed by the master sending output SCL pulses and finally a stop condition when the lines are released. However if you say that there are no slaves, this probably is not your case.
I'm afraid that your problem might have to do with the master's i2c peripheral not seeing the lines go high when expected because the pullups are disconnected temporarily. The best solution I can think in your case is that you should make sure that you don't loose those pull ups. The best way to achieve this is to connect two or three resistors in parallel in each line, this way all two/three would have to be disconnected to leave the bus "unpulled". Use two 10k resistors in parallel for SDA and another two for SCL.

Resources