2

I'm very new to microcontrollers, and I'm using PIC18F4620 (master) to communicate with the TCS34725 color sensor (slave), and DS1307 real time clock (slave, on board) via I2C. Right now, I'm experiencing some sort of interference between those two. If I run any one of the them individually without the other connected to the port, then it works fine. If the other one is connected without even being initilized, then it hangs during the reading process. Their slave addresses are not the same, so I don't see why this happens. This is the code for the color sensor

 /* Initialize LCD. */
initLCD();

I2C_Master_Init(100000); //Initialize I2C Master with 100 kHz clock

while(1){
    /*read the id */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10010010);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    id = I2C_Master_Read(NACK);
    I2C_Master_Stop();   
    __delay_ms(200);

    /* Configure the RGBC Time register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10000001);
    I2C_Master_Write(0);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Configure the Control register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10001111);
    I2C_Master_Write(0);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Configure the Control register */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10000000);
    I2C_Master_Write(0b00001011);
    I2C_Master_Stop();
    __delay_ms(200);

    /* Read red data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10010110);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    rC = (tmp[0])|(tmp[1]<<8);

    /* Read green data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10011000);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    gC = (tmp[0])|(tmp[1]<<8);

    /* Read blue data */
    I2C_Master_Start();
    I2C_Master_Write(0b01010010);
    I2C_Master_Write(0b10011010);
    I2C_Master_RepeatedStart();
    I2C_Master_Write(0b01010011);
    tmp[0] = I2C_Master_Read(ACK);
    tmp[1]= I2C_Master_Read(NACK);
    I2C_Master_Stop();
    __delay_ms(1000);
    bC = (tmp[0])|(tmp[1]<<8);

    /* Display data on the LCD */
    __lcd_home();
    __lcd_clear();
    printf("id: %d", id);
    __delay_ms(500);


    __lcd_clear();
    printf("r:%u,b:%u", rC, bC);
    __lcd_newline();
    printf("g:%u", gC);
    __delay_ms(1000);

    id = 0;
    rC = 0;
    bC = 0;
    gC = 0;
}

This is the code for RTC

void main(void) {
   /* Write outputs to LATx, read inputs from PORTx. Here, all latche (LATx)
    * are being cleared (set low) to ensure a controlled start-up state. */  
    LATA = 0x00;
    LATB = 0x00; 
    LATC = 0x00;
    LATD = 0x00;
    LATE = 0x00;

    /* After the states of LATx are known, the data direction registers, TRISx
     * are configured. 0 --> output; 1 --> input. Default is  1. */
    TRISA = 0xFF; // All inputs (this is the default, but is explicated here for learning purposes)
    TRISB = 0xFF;
    TRISC = 0b10000000; /* RC3 is SCK/SCL (SPI/I2C),
                         * RC4 is SDA (I2C),
                         * RC5 is SDA (SPI),
                         * RC6 and RC7 are UART TX and RX, respectively. */
    TRISD = 0x00; // All output mode on port D for the LCD
    TRISE = 0x00;

    /************************** A/D Converter Module **************************/
    ADCON0 = 0x00;  // Disable ADC
    ADCON1 = 0b00001111; // Set all A/D ports to digital (pg. 222)

    /* Initialize LCD. */
    initLCD();

    I2C_Master_Init(100000); //Initialize I2C Master with 100 kHz clock
    /* Set the time in the RTC.
     * 
     * To see the RTC keep time, comment this line out after programming the PIC
     * directly before with this line included. */

    RTC_setTime();

    /* Declare local variables. */
    unsigned char time[7]; // Create a byte array to hold time read from RTC
    unsigned char i; // Loop counter

    /* Main loop. */
    while(1){
        /* Reset RTC memory pointer. */
        I2C_Master_Start(); // Start condition
        I2C_Master_Write(0b11010000); // 7 bit RTC address + Write
        I2C_Master_Write(0x00); // Set memory pointer to seconds
        I2C_Master_RepeatedStart(); // Start condition
        I2C_Master_Write(0b11010001); // 7 bit RTC address + Read
        for(i = 0; i < 6; i++){
            time[i] = I2C_Master_Read(ACK); // Read with ACK to continue reading
        }
        time[6] = I2C_Master_Read(NACK); // Final Read with NACK
        I2C_Master_Stop(); // Stop condition

        /* Print received data to LCD. */
        __lcd_home();
        printf("%02x/%02x/%02x", time[6],time[5],time[4]); // Print date in YY/MM/DD
        __lcd_newline();
        printf("%02x:%02x:%02x", time[2],time[1],time[0]); // HH:MM:SS
        __delay_ms(1000);
    }
}

void RTC_setTime(void){
    /* Writes the happynewyear array to the RTC memory.*/

    I2C_Master_Start();           // Start condition
    I2C_Master_Write(0b11010000); //7 bit RTC address + Write
    I2C_Master_Write(0x00);       // Set memory pointer to seconds

    /* Write array. */
    for(char i=0; i<7; i++){
        I2C_Master_Write(happynewyear[i]);
    }

    I2C_Master_Stop();            //Stop condition
}
sophattack
  • 21
  • 1
  • 1
    What value are your I2C pullup resistors? Do you have a scope or simple logic analyzer you can use to look at the bus? What if you don't even do any transactions, but simply measure the bus voltage with a meter? When you have a device connected but unused, you are still giving it power, right? – Chris Stratton Mar 11 '18 at 18:27
  • @ChrisStratton - the PIC18F range has internal pullups that I think are ~40k, which is presumably what's being used here given absence of mentioning external pullup. If this is the case, then this question is potentially a duplicate of https://electronics.stackexchange.com/questions/1849/is-there-a-correct-resistance-value-for-i2c-pull-up-resistors (the answer is: lower resistance) – Jules Mar 11 '18 at 18:34
  • @ChrisStratton The pull up resistors are prebuilt to the dev board I'm using, which is 10k. I don't have access to an oscilloscope rn, but I can use it on Monday. Yea, I still give the unused device power. – sophattack Mar 11 '18 at 18:50
  • @Jules Yes, there are internal pullups, but I think the value is 10k tho. – sophattack Mar 11 '18 at 18:56
  • 10K is a bit large. Try at least as an experiment adding 2.2K as well, or at least 4.7K. – Chris Stratton Mar 11 '18 at 19:05
  • Based on the formula at https://electronics.stackexchange.com/questions/1849/is-there-a-correct-resistance-value-for-i2c-pull-up-resistors, 10k would only be appropriate for capacitances up to about 100pF, which you could easily be hitting with a couple of devices, particularly if you're connecting separate modules with reasonably long wires. For a 5v system the minimum resistance is about 1.6k. Trying 2.2k would definitely be sensible. – Jules Mar 11 '18 at 19:14
  • 1
    Why do you say *"TCS34725 (slave), and DS1307 (slave, on board)"*? Does that mean the TCS34725 isn't on the same board, but connected through wires? How long are the wires, then? – dim Mar 11 '18 at 20:34
  • 1
    recommendation against using internal pull-ups for I2C: [What happens if I omit the pullup resistors on I2C lines?](https://electronics.stackexchange.com/a/102616/7036) – Nick Alexeev Mar 11 '18 at 21:14
  • 2
    Two pieces of information would shed light on your problem: (1) The schematic. If you don't have access to an EDA package, a pencil sketch will do. But a photo of the breadboard would not do. (2) Oscilloscope screenshot of the I2C transaction when the bus doesn't work. Another oscilloscope screenshot for the I2C transaction when the bus does work. – Nick Alexeev Mar 12 '18 at 07:37
  • @ChrisStratton Thank you so much, I solved the problem by adding 1k pull ups. – sophattack Mar 18 '18 at 04:05
  • Thanks everyone, I solved the problem by adding 1k pull ups. – sophattack Mar 18 '18 at 04:06
  • @sop: No, you just created another problem that apparently hasn't bitten you yet. Stop guessing and randomly poking at things. Stop and actually *understand* what is going on, what each part does, and what limits are in the spec. You've been asked a number of questions, most of which you haven't answered. This web site works both ways. The volunteers here will help, but we also want to eventually understand what the problem really was, how it was finally solved, etc. Once you actually answer the questions you were asked, I can explain what other problem you have now created. – Olin Lathrop Mar 18 '18 at 13:07

1 Answers1

1

I didn't look at the code because, for one thing, it's a bunch of high level calls without showing what really goes on at the bus level.

However, this is probably a electrical issue. Possibly the second slaves loads the bus lines so that something doesn't work. You haven't said anything about the bit rate or the pullups. Those matter. Perhaps the pullups are too high impedance and/or you are trying to use too fast of a bit rate. Look at the lines with a scope and see what is really happening. Make sure when each line goes high, that it gets there solidly within a bit time.

Olin Lathrop
  • 310,974
  • 36
  • 428
  • 915