Colorimetric reactions are very common in the biology and chemistry laboratories; these reactions form colored products, and by measuring the absorption/ transmission of different wavelengths incident on these products we can determine, for example, the concentration of a certain substance present in the solution investigated. To carry out these measurements, it is used colorimeters and spectrophotometers, equipment that has a high cost and can limit its access.
In this tutorial we will show you how to make a low cost portable colorimeter using Arduino. This equipment is a great solution for teaching, but can also be used in laboratories.
Materials
Circuit
Protoboard:
LED RGB Module:
TSL 2561 Sensor :
OLED Display :
Módulo SD:
Buttons:
One of the button legs must be powered by the 5V port; the other leg attached to one of the legs of the resistor and to port 7, 4 and 2 (each of the 3 buttons on one of these ports); the other leg of the resistor must be connected to GND.
Code
Below is the code for the Portable Colorimeter and the libraries required for its correct operation.
#include <SPI.h>
#include <RTClib.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include <SD.h>
#include <MicroLCD.h>
#define SD_CS_DIO 10
RTC_Millis RTC;
// SD Card Config
Sd2Card card;
SdVolume volume;
SdFile root;
// the logging file
File DataFile;
//CONFIGURACAO DO DISPLAY MICRO LCD
LCD_SH1106 lcd; /* para módulo controlado pelo CI SH1106 OLED */
//LCD_SSD1306 lcd; /* para módulo contralado pelo CI SSD1306 OLED */
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
void displaySensorDetails(void) {
sensor_t sensor;
tsl.getSensor(&sensor);
}
void configureSensor(void) {
tsl.enableAutoRange(true);
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);
}
// Define as conexões para cada cor do RGB
const int R = 6;
const int G = 5;
const int B = 3;
// Armazena os valores para cada cor entre (0-255)
int ValorR = 0;
int ValorG = 0;
int ValorB = 0;
int pinLed = 0;
// Define as conexões do botão seletor (push button)
int seletor;
int nm;
float Absorbancia;
float I0;
void setup() {
Serial.begin(9600);
Serial.println("Light Sensor Test");
Serial.println("");
RTC.begin(DateTime(__DATE__, __TIME__));
lcd.begin ();
lcd.clear();
lcd.setCursor(10, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("COLORIMETER");
// There was a problem detecting the TSL2561 ... check your connections
if (!tsl.begin()) {
Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
lcd.setCursor(1, 3);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print("No TSL2561 detected");
while (1);
} else {
lcd.setCursor(1, 3);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print("TSL2561 OK");
}
// Display some basic information on this sensor
displaySensorDetails();
// Setup the sensor gain and integration time
configureSensor();
/* We're ready to go! */
Serial.println("");
// Indica que os pinos dos botões são de SAÍDA do Arduino
pinMode(R, OUTPUT);
pinMode(G, OUTPUT);
pinMode(B, OUTPUT);
// Indica que os pinos dos botões são de ENTRADA no Arduino
pinMode(7, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
analogWrite(R, 255); //coloca valor inicial para vermeho (padrão inicial)
nm = 630;
// initialize the SD card
// Set the SD card CS pin to an output
pinMode(SD_CS_DIO, OUTPUT);
// Initialise the SD card
SD.begin(SD_CS_DIO);
if (!SD.begin(SD_CS_DIO)) {
/* If there was an error output this to the serial port and go no further */
Serial.println("ERROR: SD card failed to initialise");
lcd.setCursor(1, 5);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print("SD CARD ERROR");
while (1);
}
else {
lcd.setCursor(1, 5);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print("SD CARD OK");
Serial.println("SD Card OK");
delay (2000);
// Get a new sensor event
sensors_event_t event;
tsl.getEvent(&event);
I0 = event.light;
}
lcd.clear();
}
void loop()
{
// Get a new sensor event
sensors_event_t event;
tsl.getEvent(&event);
/* Display the results (light is measured in lux) */
if (event.light) {
lcd.setCursor(5, 2);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print(" ");
Serial.print(event.light);
Serial.println(" lux");
Serial.println (I0);
Absorbancia = log(I0 / event.light);
Serial.print(Absorbancia);
Serial.println(" Absorbância");
if (digitalRead(7) == LOW) {
nm = 420;
analogWrite(R, 0); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(G, 0); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(B, 255); //coloca valor inicial para vermeho (padrão inicial)
I0 = event.light;
}
if (digitalRead(4) == LOW) {
nm = 520;
analogWrite(R, 0); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(G, 255); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(B, 0); //coloca valor inicial para vermeho (padrão inicial)
I0 = event.light;
}
if (digitalRead(2) == LOW) {
nm = 630;
analogWrite(R, 255); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(G, 0); //coloca valor inicial para vermeho (padrão inicial)
analogWrite(B, 0); //coloca valor inicial para vermeho (padrão inicial)
I0 = event.light;
}
}
else {
Serial.println("Sensor overload");
lcd.clear();
lcd.setCursor(5, 2);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("SENSOR ERROR");
}
delay (100);
Serial.println(digitalRead(seletor));
//lcd.clear();
// lcd.setCursor(0, 2);
//lcd.setFontSize(FONT_SIZE_MEDIUM);
//lcd.print("Lux:");
//lcd.setCursor(35, 2);
//lcd.setFontSize(FONT_SIZE_MEDIUM);
//lcd.print(event.light);
lcd.setCursor(2, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("Abs:");
lcd.setCursor(40, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print(nm);
lcd.setCursor(70, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("nm");
lcd.setCursor(40, 12);
lcd.setFontSize(FONT_SIZE_LARGE);
lcd.print(" ");
lcd.setCursor(40, 12);
lcd.setFontSize(FONT_SIZE_XLARGE);
lcd.print(Absorbancia);
delay(100);
// Write the results to the SD Card
logging();
}
void logging()
{
DataFile = SD.open("data.csv", FILE_WRITE);
if (DataFile) {
DateTime now = RTC.now();
DataFile.print(now.day(), DEC);
DataFile.print('/');
DataFile.print(now.month(), DEC);
DataFile.print('/');
DataFile.print(now.year(), DEC);
DataFile.print(',');
DataFile.print(now.hour(), DEC);
DataFile.print(':');
DataFile.print(now.minute(), DEC);
DataFile.print(':');
DataFile.print(now.second(), DEC);
DataFile.print(",");
DataFile.print(Absorbancia);
DataFile.print(",");
if (nm == 630) {
DataFile.print("630nm");
}
else if (nm == 520) {
DataFile.print("520nm");
}
else if (nm == 420) {
DataFile.print("420nm");
}
DataFile.println();
DataFile.close();
}
delay(100);
}