TCS34725_TWI is a project aiming to implement TWI protocol to comunicate between an Arduino Nano and a TCS34725 RGB sensor.
I2C is a serial communication protocol used to communicate between masters and slaves using a two-wire interface. Two Wire Interface was created by Atmel to avoid any legal troubles using this communication protocol created by Philips.
Since this project uses a microcontroller from Atmel(atmega328p from an Arduino Nano), it should be implemented using TWI.
The two wire interface is defined by two wires: SDA (serial data) and SCL (serial clock) connected with a pull-up resistor to +Vdd. This allows to communicate between many devices, with their unique address, with only two wires.
In a normal state both lines are high. To start a communication, a master creates a start condition (SDA line low) and to end communication the master sends a stop condition (SDA line high). Between these conditions the data is sent.
After sending a start condition the master must send the 7-bit slave address he wants to establish connection followed by read/write bit (where read is 1 and write is 0). If the slave is on the bus, it answers with an ACK. If not, with NACK.
If the slave answers with ACK, the master should now become a master transmittter or a master receiver, depending on the read/write bit.
To transmit, a master transmitter should send the command, the desired data packets and then send a stop condition to end communication:
To receive, a master should after receiving the data send ACK or NACK: sends NACK when it is the last packed received before a stop condition.
In this example it is also notable that to change from master transmitter to master receiver, the master must send a repeated start condition and send the proper slave address + R/W bit:
A lib folder was created with the TWI protocol implemented in C.
To setup TWI it is necessary to set SCL frequency. Since the maximum rate is 400kHz and the TCS34725 works up to 400kHz, the SCL frequency is set a bit lower than the maximum values, 333kHz:
- Arduino Frequency: 16MHz
- Prescaler: 16
- TWEN set to 1 to enable TWI operation
A start condition is created by:
- Set TWSTA and TWINT to 1.
TWSTA is written to 1 to check if the bus is free and generates a start condition on the bus if it is free. TWINT is set by hardware when the TWI has finished its current task.
- Wait for TWINT to be set.
To write to the bus the TWI Data Register (TWDR) should be written with the data desired to send. Enable TWI operation and wait for it to end.
To read, the master waits reception, reads on TWDR and sends ACK to the slave by enable the TWI Enable Acknowledge Bit (TWEA).
In case of reception of the last packet before the stop condition, a NACK must be sent by set TWEA to 0.
A stop condition is created by setting TWI STOP Condition Bit (TWSTO) to 1.
The Sensor is divided into 4 states. The Sensor is on a Sleep state until it receives a TWI operation start and changes to Idle state (PON register set to 1).
It is not capable of reading colors before changing to RGBC state. To start reading RGB values, the sensor must enter the RGBC state by enable AEN.
Between the Idle state and the RGBC state the device needs a 2.4ms delay as stated on datasheet. And between each reading, the RGBC takes 2.4ms to 700ms.
The device is controlled by these intructions:
So to get, for example the device ID, it is necessary to:
- Send a Start Condition
- Send the Slave Address and the W bit, informing the slave the incoming data is an instruction
- Send the instruction: COMMAND (0x80) + ID (0x12)
- Send a repeated Start Condition in order to change to master receiver
- Send again the Slave Address, but now with the R bit
- Receive the ID
- Send a Stop Condition
The reception of the device ID guarantees that the slave is connected to master and the connection is well established.
Clear, red, green, and blue data is stored as 16-bit values. So, the master should read twice to get a proper color value:
- Send a Start Condition
- Send the Slave Address and the W bit, informing the slave the incoming data is an instruction
- Send the instruction: COMMAND (0x80) + COLOR (CDATA, RDATA, GDATA or BDATA)
- Send a repeated Start Condition in order to change to master receiver
- Send again the Slave Address, but now with the R bit
- Receive the first 8 bits
- Receive the last 8 bits
- Send a Stop Condition
The ADCs of the sensor is controlled by two variables: integration time and gain. The integration time controls the RGBC Timing Register and the number of the cycles. The gain controls the sensor light sensitivity.
Two set these two, the process is similar. For example, to set gain:
- Send a Start Condition
- Send the Slave Address and the W bit, informing the slave the incoming data is an instruction
- Send the instruction: COMMAND (0x80) + CONTROL_REGISTER (0x0F)
- Send the gain value: AGAIN (00x0 for 1x Gain)
- Send a Stop Condition
A GUI was created in Python (based on PyQt5) to simulate a RGB LED behavior. The program receives RGB values from serial port, prints it and converts it into a color.
To open the GUI, run:
python3 gui.py