PIC I2C using Colour sensor

Find out how to setup your programmer's software and how to solve many common problems.

Moderator: phalanx

PIC I2C using Colour sensor

Postby mreiter » Tue Feb 14, 2017 3:13 pm

Hello!

I have a colour sensor that I need to communicate with using I2C. I've written the following I2C code based off of this Arduino example (https://github.com/adafruit/Adafruit_TC ... S34725.cpp) but I am not having much luck getting data. If you code give my code a look over, that would be greatly appreciated. The color sensor that I am using is the model TCS34725 (https://cdn-shop.adafruit.com/datasheets/TCS34725.pdf)

Here is my I2C code:

Code: Select all
READ_COLOUR_I2C
    i2c_common_start

    movlw 0x29 ;TCS34725 address | WRITE bit (+0)
    i2c_common_write ;
    i2c_common_check_ack RD_ERR1

    ;Write data to I2C bus (Register Address in TCS34725)
    movlw regaddress
    iorlw 0x80
    i2c_common_write ;
    i2c_common_check_ack RD_ERR2

    ;Re-Select the TCS34725 on the bus, in READ mode
    i2c_common_repeatedstart
    movlw 0x2A ;TCS34725 address | READ bit (+1)
    i2c_common_write
    i2c_common_check_ack RD_ERR3

    ;Read data from I2C bus (Contents of Register in TCS34725)
    i2c_common_read
    movwf datachar
    i2c_common_nack ;Send acknowledgement of data reception

    goto RD_END

    RD_ERR1
 nop
 movlw b'00000011'
 movwf LATA
 goto RD_END
    RD_ERR2
 nop
 movlw b'00000101'
 movwf LATA
 goto RD_END
    RD_ERR3
 nop
 movlw b'00000111'
 movwf LATA
 goto RD_END
    RD_END
 i2c_common_stop
return

WRITE_COLOUR_I2C
    i2c_common_start

    movlw 0x29 ;TCS34725 address | WRITE bit
    i2c_common_write
    i2c_common_check_ack WR_ERR1

    ;Write data to I2C bus (Register Address in TCS34725)
    movlw regaddress
    iorlw 0x80
    i2c_common_write ;
    i2c_common_check_ack WR_ERR2

    ;Write data to I2C bus (Data to be placed in TCS34725 register)
    movlw databyte
    iorlw 0x80
    i2c_common_write
    i2c_common_check_ack WR_ERR3

    goto WR_END

    WR_ERR1
 nop
 movlw b'00001101'
 movwf LATA
 goto WR_END
   
    WR_ERR2
 nop
 movlw b'00001111'
 movwf LATA
 bsf LATE,0
 goto WR_END
 
    WR_ERR3
 nop
 movlw b'00001001'
 movwf LATA
 goto WR_END
    WR_END
 i2c_common_stop ;Release the I2C bus
 
return


Thanks a bunch

Matthew
mreiter
 
Posts: 11
Joined: Thu Feb 09, 2017 11:05 pm

Re: PIC I2C using Colour sensor

Postby phalanx » Thu Feb 16, 2017 8:48 pm

Your slave address is 0x29 (0b00101001) which occupies the 7 most significant bits of your first transmitted byte while your read/write bit is the least significant bit. This means you have to left shift 0x29 which gives you 0b01010010 or 0x52. Since the LSB is zero for a write, the byte you write to the I2C bus to address your sensor for a write is 0x52. Add one to this for a read operation and your byte to be written to address the sensor is 0x53.

Also keep in mind that you have to tell the sensor to do something before you can read anything useful back from it.

-Bill
User avatar
phalanx
Non-SFE Guru
 
Posts: 1924
Joined: Sun Nov 30, 2003 8:57 am
Location: Candia, NH

Re: PIC I2C using Colour sensor

Postby mreiter » Sat Feb 18, 2017 1:35 pm

Hello Bill,

Sorry for the delay in getting back to you, times have been crazy at school.

Thanks for the correction, I believe that Ive sorted out the addressing. I have having some issues however with reading the data from this sensor - when I look to get data from my colour sensors, I notice that my SDA/SCL pins both ride low, and my PIC hangs as a result. I am not sure what's causing this, nor have I been able to identify where the exact issue is. Mind if I get you to take a look at my updated I2C code, as well as the previous initializations?

Edit: just to confirm, all I need to do to connect the colour sensor to my PIC is connect the SDA/SCL pins on the sensor to RC4/RC3 respectively? I've not seen any prior literature telling me I need some special configuration, especially when using multiplier I2C devices, which in case as you know, includes a DS1307.

Updated I2C:
Code: Select all
READ_COLOUR_I2C   
    i2c_common_start
   
    movlw   0x52      ;TCS34725 address 0x29 << 1, WRITE bit (+0)
    i2c_common_write
    i2c_common_check_ack RD_ERR1_RTC
   
    ;Write command to I2C bus (Register Address in TCS34725)
    movlw   regaddress
    iorlw   0x80      ;command bit
    i2c_common_write
    i2c_common_check_ack RD_ERR2
   
    ;Re-Select the TCS34725 on the bus, in READ mode
    i2c_common_repeatedstart
    movlw   0x53      ;TCS34725 address 0x29 << 1, READ bit (+1)
    i2c_common_write
    i2c_common_check_ack RD_ERR3
   
    ;Read data from I2C bus (Contents of Register in TCS34725)
    i2c_common_read
    movwf data_colourL
    i2c_common_nack      ;Send acknowledgement of data reception

    i2c_common_read
    movwf data_colourH
    i2c_common_nack      ;Send acknowledgement of data reception

    goto RD_END

    RD_ERR1
   nop
   movlw   b'00000011'
   movwf   LATA
   goto   RD_END
    RD_ERR2
   nop
   movlw   b'00000101'
   movwf   LATA
   goto   RD_END
    RD_ERR3
   nop
   movlw   b'00000111'
   movwf   LATA
   goto   RD_END
    RD_END
   i2c_common_stop
return

WRITE_COLOUR_I2C
    i2c_common_start

    movlw   0x52 ;TCS34725 address | WRITE bit
    i2c_common_write
    i2c_common_check_ack WR_ERR1

    ;Write data to I2C bus (Register Address in TCS34725)
    movlw   regaddress
    iorlw   0x80
    i2c_common_write
    i2c_common_check_ack WR_ERR2

    ;Write data to I2C bus (Data to be placed in TCS34725 register)
    movlw   databyte
    i2c_common_write
    i2c_common_check_ack WR_ERR3

    goto    WR_END

    WR_ERR1
   nop
   movlw   b'00001101'
   movwf   LATA   
   goto   WR_END
   
    WR_ERR2
   nop
   movlw   b'00001111'
   movwf   LATA
   bsf   LATE,0
   goto    WR_END
   
    WR_ERR3
   nop
   movlw   b'00001001'
   movwf   LATA
   goto   WR_END
    WR_END
   i2c_common_stop ;Release the I2C bus
   
return


and here is the code I use to initialize/call the read commands for the colour sensor:
Code: Select all
    extern   i2c_common_setup, regaddress, databyte, datachar, READ_COLOUR_I2C, WRITE_COLOUR_I2C, d200us_C, d50ms_C, data_colourL, data_colourH

;    #define TCS34725_ADDRESS          (0x29)
;
;    #define TCS34725_COMMAND_BIT      (0x80)
;
;    #define TCS34725_ENABLE           (0x00)
;    #define TCS34725_ENABLE_AIEN      (0x10)    /* RGBC Interrupt Enable */
;    #define TCS34725_ENABLE_WEN       (0x08)    /* Wait enable - Writing 1 activates the wait timer */
;    #define TCS34725_ENABLE_AEN       (0x02)    /* RGBC Enable - Writing 1 actives the ADC, 0 disables it */
;    #define TCS34725_ENABLE_PON       (0x01)    /* Power on - Writing 1 activates the internal oscillator, 0 disables it */
;    #define TCS34725_ATIME            (0x01)    /* Integration time */
;    #define TCS34725_WTIME            (0x03)    /* Wait time (if TCS34725_ENABLE_WEN is asserted) */
;    #define TCS34725_WTIME_2_4MS      (0xFF)    /* WLONG0 = 2.4ms   WLONG1 = 0.029s */
;    #define TCS34725_WTIME_204MS      (0xAB)    /* WLONG0 = 204ms   WLONG1 = 2.45s  */
;    #define TCS34725_WTIME_614MS      (0x00)    /* WLONG0 = 614ms   WLONG1 = 7.4s   */
;    #define TCS34725_AILTL            (0x04)    /* Clear channel lower interrupt threshold */
;    #define TCS34725_AILTH            (0x05)
;    #define TCS34725_AIHTL            (0x06)    /* Clear channel upper interrupt threshold */
;    #define TCS34725_AIHTH            (0x07)
;    #define TCS34725_PERS             (0x0C)    /* Persistence register - basic SW filtering mechanism for interrupts */
;    #define TCS34725_PERS_NONE        (0b0000)  /* Every RGBC cycle generates an interrupt                                */
;    #define TCS34725_PERS_1_CYCLE     (0b0001)  /* 1 clean channel value outside threshold range generates an interrupt   */
;    #define TCS34725_PERS_2_CYCLE     (0b0010)  /* 2 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_3_CYCLE     (0b0011)  /* 3 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_5_CYCLE     (0b0100)  /* 5 clean channel values outside threshold range generates an interrupt  */
;    #define TCS34725_PERS_10_CYCLE    (0b0101)  /* 10 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_15_CYCLE    (0b0110)  /* 15 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_20_CYCLE    (0b0111)  /* 20 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_25_CYCLE    (0b1000)  /* 25 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_30_CYCLE    (0b1001)  /* 30 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_35_CYCLE    (0b1010)  /* 35 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_40_CYCLE    (0b1011)  /* 40 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_45_CYCLE    (0b1100)  /* 45 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_50_CYCLE    (0b1101)  /* 50 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_55_CYCLE    (0b1110)  /* 55 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_PERS_60_CYCLE    (0b1111)  /* 60 clean channel values outside threshold range generates an interrupt */
;    #define TCS34725_CONFIG           (0x0D)
;    #define TCS34725_CONFIG_WLONG     (0x02)    /* Choose between short and long (12x) wait times via TCS34725_WTIME */
;    #define TCS34725_CONTROL          (0x0F)    /* Set the gain level for the sensor */
;    #define TCS34725_ID               (0x12)    /* 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727 */
;    #define TCS34725_STATUS           (0x13)
;    #define TCS34725_STATUS_AINT      (0x10)    /* RGBC Clean channel interrupt */
;    #define TCS34725_STATUS_AVALID    (0x01)    /* Indicates that the RGBC channels have completed an integration cycle */
;    #define TCS34725_CDATAL           (0x14)    /* Clear channel data */
;    #define TCS34725_CDATAH           (0x15)
;    #define TCS34725_RDATAL           (0x16)    /* Red channel data */
;    #define TCS34725_RDATAH           (0x17)
;    #define TCS34725_GDATAL           (0x18)    /* Green channel data */
;    #define TCS34725_GDATAH           (0x19)
;    #define TCS34725_BDATAL           (0x1A)    /* Blue channel data */
;    #define TCS34725_BDATAH           (0x1B)


    COLOUR_INIT macro
   COLOUR_WRITE   0x00, 0x01 ; Enable Register (0x00), Power ON (0x01)
   COLOUR_WRITE   0x00, 0x02 ; Enable Register (0x00), RGBC enable (0x02)
   COLOUR_WRITE   0x01, 0xf6 ; Timing Register (0x01), 24ms rgbc cycle
   COLOUR_WRITE   0x0f, 0x03 ; Control Register (0x0f), 60x gain (0x03)
    endm
   
    COLOUR_READ    macro   address
   movlw   address
   movwf   regaddress
   call   READ_COLOUR_I2C
    endm
   
    COLOUR_WRITE macro address, datliteral
   movlw   address
   movwf   regaddress
   movlw   datliteral
   movwf   databyte
   call   WRITE_COLOUR_I2C
    endm
   
    COLOUR_GET_DATA macro clear, red, green, blue, temp_col
   COLOUR_READ 0x14    ; read clear colour address low, command bits set later
   DATA_TO_COLOUR   data_colourH, data_colourL, temp_col, clear
   
   COLOUR_READ 0x16    ; read red colour address low, command bits set later
   DATA_TO_COLOUR   data_colourH, data_colourL, temp_col, red
   
   COLOUR_READ 0x18    ; read green colour address low, command bits set later
   DATA_TO_COLOUR   data_colourH, data_colourL, temp_col, green
   
   COLOUR_READ 0x1A    ; read clear colour address low, command bits set later
   DATA_TO_COLOUR   data_colourH, data_colourL, temp_col, blue
    endm
   
    DATA_TO_COLOUR macro addrH, addrL, count, final
   movlw   0x08
   movwf   count
   movlw   addrH
   ROTATEL   count
   iorwf   addrL
   movwf   final
    endm
   
    ROTATEL  macro count
   rlncf   WREG
   decfsz   count
   bra   ROTATEL
    endm
   
;Delay200us macro
;   local loop200us
;   movlw   0xA4
;   movwf   d200us_C
;
;loop200us
;   decfsz   d200us
;   goto   loop200us
;   nop
;   endm
;   
;
;Delay50ms macro
;   local loop50ms
;   movlw   0xF9
;   movwf   d50ms_C
;
;loop50ms
;   Delay200us
;   decfsz   d50ms_C
;   endm
;;   


Thank you very much

Matthew
mreiter
 
Posts: 11
Joined: Thu Feb 09, 2017 11:05 pm


Return to PIC Microcontrollers - Software and Hardware

Who is online

Users browsing this forum: No registered users and 3 guests