1

strong textschematic**<code>strong text</code>**i have Vector nav100 IMU sensor that sends data serially UART.I want to receive data from it using ATmega32 and then store data in AT24c1024 EEprom using I2C,then using another ATmega32 to read the saved data on AT24c1024 EEprom using I2C to control a servo motor..so,the AT24c1024 EEprom is then shared between the two microcontrollers...i have serached the internet about how to share one External serial EEprom,i found that......(On way would be for the two mcrocontrollers to have an output line as an input to the other. A master that is "using" the EEPROM perhaps pulls his output low (or high - your choice) to say "I'm using it at the moment". The other reads his input first before going near the EEPROM if he finds the line active he backs off until it is set inactive by the other master.i tried this solution but i failed...can any one help me on this solution ? Thanks in advance...... this is my code

{

    //the first MCU fristly check the pin
    //if high,then write,then set it low to allow read
    //the second MCU fristly check the pin
    //if low ,then write,then set it high to allow write

    //for the MCu that will write
    //first it will check for the pin ,if it is LOW,
    //then it can write data to EEprom
                     DDRA=0x00;//configure portA as input
            if(PINA==0x00)//check for the pin, if LOw,then wirte
    {                            
        byte_write(data);
        _delay_ms(10);
    //After writing set the pin as high to allow the second MCU to read
        DDRA=0xff;//configure portA as output
        PORTA=0xff;//set the pin as high
        _delay_ms(10);}

    //for the MCu that will read,i set adelay of 10 ms
    // to allow the first MCU to write some data

                         _delay_ms(1000);//delay from the data to be written on the EEprom
                 DDRA=0x00;//configure portA as input
        if(PINA==0x01)//check for the pin, if HIGH,then read
    {
             y=byte_read(data);
            DDRA=0xff;configure portA as output
            PORTA=0x00;//set the pin as high

}
9
  • I wonder what the reason is for the EEPROM ... because of temporarily storing data, or as a buffer (timing difference between the writer mcu and reader mcu? Or for other reasons (too)? Otherwise, remove the EEPROM, and send data directly from one MCU to the other (e.g. using UART/SPI/I2C). Commented Jul 17, 2019 at 16:46
  • @MichelKeijzers to prevent data from loss if the next frame from the sensor came and the microcontroller is still processing the last frame,so the frame will be dropped.
    – mohamed
    Commented Jul 17, 2019 at 16:51
  • If written correctly, receiving and processing are 2 different things. Also the Wire library does not support multi master. When both controllers try to access the EEPROM simultaneously, the bus will be blocked.
    – chrisl
    Commented Jul 17, 2019 at 17:07
  • @chrisl OK.that is true..so,.I have searched the internet for that,I have found that On way would be for the two microcontrollers to have an output line as an input to the other. A master that is "using" the EEPROM perhaps pulls his output low (or high - your choice) to say "I'm using it at the moment". The other reads his input first before going near the EEPROM if he finds the line active he backs off until it is set inactive by the other master.I tried this ,but I failed...could me give me pseudo code for this solution?
    – mohamed
    Commented Jul 17, 2019 at 17:14
  • With what did you fail? You should provide the code in question, so that we can help you with that. Though I'm still not sure, that using an external eeprom is a good idea
    – chrisl
    Commented Jul 17, 2019 at 17:20

1 Answer 1

2

You didn't show us a complete, minimal, compilable example, so my answer will only cover some important points.

  1. Your indention is way off. It is important to use the correct indention, since it help structure your code and will let you quickly see misplaced brackets. The Arduino IDE even has an autoformat function for this.

  2. You are configuring and checking always the whole PORT A, but you have only connected one of the pins. When you configure the whole port as input (without pullup), the other pins will be floating. Also, if both devices have the pin on input (no pullup), this pin will also be floating. The check cannot work this way. You should only look at the first bit in the port registers, since that is the pin, that you connected. You can set all other bits to zero when reading, by performing a bitwise AND operation: if(PINA & (1<<PA0)). This will execute, when the first bit of PINA is 1. To set a single bit you can use the bitwise OR: DDRA |= 1<<PA0; will set the first bit of DDRA. To erase only that bit from the register, you can use DDRA &= ~(1<<PA0);. The rest of the port will stay untoched with this.

  3. Your current protocol is, that the first MCU will check for LOW, do it' transmission, then drive the pin actively HIGH as a signal for the second MCU to start transmitting. The second MCU will do it's I2C stuff and then drive the pin actively LOW. So now we have an active LOW and active HIGH on the same pin, which in principle is a short. A rather big amount of current will flow from one MCU to the other, most likely destroying at least one of the pins (meaning the output hardware in the MCU, that serves that pin). To avoid this, you can use a principle like that, that the I2C port uses: Open Drain logic. You can start with the first MCU's pin configured as OUTPUT LOW, while the other is INPUT PULLUP. LOW means the first MCU can work. If the first MCU want's the second MCU to do a transmission, it will release the line by setting the PIN to INPUT PULLUP. The second MCU now sees a HIGH level on it's pin and starts it's transmission. When it is finished, it will drive the line actively LOW for a defined duration (enough for the first MCU to react) and then to INPUT PULLUP again. The first MCU will then see a LOW level on it's pin as a signal, that the second MCU is finished. It then itself drives the line actively LOW. Then the play starts again. The important thing is, that a HIGH state is only done by a pullup, not actively driven.


That said, I still don't see the necessity to share an external EEPROM for this use case. You are overthinking the problem. You wrote, that you don't want to miss a frame, if the second MCU is still processing the last frame. There are better ways to do that (especially when you consider the limited lifetime of EEPROM).

  • You didn't tell us, why you are using 2 MCU's, so maybe your goal can be reached with only 1 MCU, which will eliminate the whole need for transmission.

  • You could use another UART interface via SoftwareSerial or it's sibling libraries to let the MCU's communicate directly. "Not missing a frame" will still be the case, when you are not disabling interrupts. The library will read the data into a buffer in interrupts, while you are processing the previous frame. Depending on how much data you send, you might want to make the buffer bigger, but that is a simple change in the libraries definitions.

  • If you want to use I2C to communicate between both MCU's, you have 2 ways of doing it. You can either go the same way as described above for UART, by just letting it fill a big enough buffer, or you can do this through the bus transmissions. The first MCU would be the master, that tries to send the data to the second MCU (slave), when there is new data available. The slave will receive the data normally. When the frame is finished receiving, the slave can leave the bus, until it is finished processing. So, when the master tries to send more data in this time, the transmission will fail at the start, since no slave with that address is on the bus (the slave MCU left the bus for this period of time). You can check the return value of Wire.endTransmission(), which will reflect the corresponding error code. If this error code is returned, the master should wait a bit and try to send this frame again, until it is received successfully. That also means, that the master needs a big enough buffer for storing new data, while waiting for the slave to be ready. Or another way: The master can request 1 byte from the slave, that indicates, if the slave is ready for new data. If not, the master will wait a bit and ask again. If yes, it will transmit the data.

Note: Either way the frequency of data reception and processing must be equal for continuous operation. The whole chain will be as fast as the slowest part. If you receive data faster, than it get's processed, the buffer will fill up fast, until you really have to drop frames. The prinicples above are more about the case, when the processing and receiving may misalign or vary a bit, but at the average staying at the same speed. And for this simple communication buffers, that all communication libraries use, with enough space for maybe 2 to 4 transmissions (depending on the variation) are way enough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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