Projects
Basic Sensors
Color

Overview

This project reads the red, green, and blue values measured by the color sensor and displays the readings on a 20x4 LCD screen with an I2C backpack.

Components

Component NamePurpose
Arduino NanoThis will be the microcontroller
TCS2300This will be the colour sensor
I2C LCD 20X4This will be the LCD display

Circuit Diagram

nano_color_lcd_fritzing

Assembly

TCS3200 Pin Connections

Nano PinTCS3200 Pin
D4S0
D5S1
D6S2
D7S3
D8Out
5VVCC
GndGnd

I2C LCD Pin Connections

Nano PinI2C LCD Pin
A4SDA
A5SCL
5VVCC
GNDGND

Code

/*
  Project: Color Sensor value reading with output on LCD with I2C Backpack
  Project Description:
  This sketch writes readings read from a color sensor to an LCD display module.
  This sketch is for a 20x4 screen.
 
  Author: STEMVentor Educonsulting
  
  This code is copyrighted. Please do not reuse or share for any purpose other than for learning with subscribed STEMVentor programs.
  This code is for educational purposes only and is not for production use.
*/
 
// LIBRARIES
 
// Used for communicating with I2C devices
#include <Wire.h> 
 
// https://www.arduino.cc/reference/en/libraries/liquidcrystal-i2c/
// Install the LiquidCrystal I2C by Frank de Brabander from the IDE library manager. 
#include <LiquidCrystal_I2C.h>
 
// PIN DEFINITIONS
// Define the pin to which the S pins of the color sensor are connected
// S pins of the sensor module connected to the corresponding D pins on the board
// For Arduino Nano, comment if using ESP32
#define S0 4
#define S1 5
#define S2 6
#define S3 7
#define sensorOut 8
 
// For ESP32, uncomment if using ESP32
// #define S0 4
// #define S1 5
// #define S2 16
// #define S3 17
// #define sensorOut 18
 
// GLOBAL VARIABLES
// Define the display size
const byte rows = 4;
const byte cols = 20;
 
// Used for reading a string.
String redValue;
String greenValue;
String blueValue;
 
/* INITIALIZE OBJECTS
 * Libraries usually follow an object-oriented approach that requires
 * an instance of the class to call its methods.
 */
/* 
 * All I2C components have an address, the default is usually 0x27
 * If that doesn't work, see this: https://playground.arduino.cc/Main/I2cScanner/
 * The init statement accepts the address and the number of columns and rows.
 */
LiquidCrystal_I2C lcd(0x27, cols, rows);
 
/* LOCAL FUNCTIONS */
 
// Read the sensor readings
void readColour()
{
  int frequency = 0;
 
  // Setting red filtered photodiodes to be read by making respective pins LOW
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  // Reading the output frequency using pulseIn function via the sensor out pin of sensor module
  frequency = pulseIn(sensorOut, LOW);
  // Mapping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 25, 72, 255, 0);
  // Printing the value on the serial monitor
  Serial.print("R= ");
  Serial.print(frequency);
  Serial.print("  ");
  redValue = "R = " + String(frequency); 
  delay(100);
 
  // Setting Green filtered photodiodes to be read
  digitalWrite(S2, HIGH);
  digitalWrite(S3, HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Remapping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 30, 90, 255, 0);
  // Printing the value on the serial monitor
  Serial.print("G= ");
  Serial.print(frequency);
  Serial.print("  ");
  greenValue = "G = " + String(frequency); 
  delay(100);
 
  // Setting Blue filtered photodiodes to be read
  digitalWrite(S2, LOW);
  digitalWrite(S3, HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Remapping the value of the frequency to the RGB Model of 0 to 255
  frequency = map(frequency, 25, 70, 255, 0);
  // Printing the value on the serial monitor
  Serial.print("B= ");
  Serial.print(frequency);
  Serial.println("  ");
  blueValue = "B = " + String(frequency); 
  delay(100);
}
 
/*
  Function to print to LCD on a single row.
  Takes the row number and the text to display on that row (max 20 chars, rest will be truncated).
  The entire display is cleared if the clear_all flag is true, else only the row is cleared (the default).
 */
void printToLCDByRow(int row, String text, bool clear_all = false)
{
  const char* twenty_spaces = "                    ";
 
  if (clear_all) { 
    lcd.clear(); // Clears the entire display
  } 
 
  lcd.setCursor(0, row-1);
  lcd.print(twenty_spaces); // Clears the row
  lcd.setCursor(0, row-1); // Cursor has to be set again after printing spaces
  lcd.print(text);
}
 
/*
 Function to print to LCD across rows with each row having 20 chars.
 Messages can be a maximum of 20x4 chars, rest will be truncated.
 The entire display is cleared before printing the text.
 */
void printToLCD(String text)
{
  lcd.clear(); // Clears the entire display
 
  byte chars_remaining = text.length();
  byte char_from = 0;
  byte char_to = chars_remaining < cols ? text.length() : char_from + cols;
  byte row = 1;
 
  while (chars_remaining > 0) {
    String line = text.substring(char_from, char_to);
    printToLCDByRow(row, line);
 
    chars_remaining = text.length() - char_to;
    char_from = char_to;
    char_to = chars_remaining < cols ? text.length() : char_from + cols;
    row++;
  }
 
  Serial.println("Data string has been displayed on LCD");
}
 
void LCD_setup()
{
  // Initializing wire
  Wire.begin();
  // Initialize the LCD.
  lcd.init();
  // Turn on the backlight and print a message.
  lcd.backlight();
  // Use the function to display text on each line individually.
  printToLCDByRow(1, "I2C LCD Ready!", true);
  printToLCDByRow(2, "Enter some text.", false);
  printToLCDByRow(3, "Max 80 characters.", false);
  printToLCDByRow(4, "For a 20x4 LCD.", false);
}
 
void colourSensor_setup()
{
  // Define the pin mode
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  // Setting frequency-scaling to 20%
  digitalWrite(S0, HIGH);
  digitalWrite(S1, LOW);
}
 
/* SETUP CODE: runs once when the board starts up or resets */ 
void setup() 
{
  // Start the serial communication with baud rate suitable for your components.
  Serial.begin(9600);
  LCD_setup();
  colourSensor_setup();
  Serial.println("The board is ready!");
}
 
/* MAIN LOOP: runs repeatedly at a very high frequency (1000s of times a second) */
void loop() 
{
  delay(1000); 
  readColour();
  printToLCDByRow(1, redValue, true);
  printToLCDByRow(2, greenValue, false);
  printToLCDByRow(3, blueValue, false);
}