Portable Colorimeter

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

  • 1 Protoboard
  • 1 OLED Display
  • 1 LED RGB Module
  • 1 TSL 2561 Sensor
  • 1 SD Module
  • 1 Arduino UNO
  • 3 Buttons
  • Jumper

Circuit

Protoboard:

  • 5V and GND

LED RGB Module:

  • R = 6
  • G = 5
  • B = 3
  • Negative = GND

TSL 2561 Sensor :

  • VCC = 3V
  • GND
  • SDA = 4
  • SCL = 5

OLED Display :

  • VCC = 5V
  • GND
  • CS = 10
  • MOSI = 11
  • SCK = 13
  • MISO = 12

Módulo SD:

  • VCC = 5V
  • GND
  • SDA = 4
  • SCK = 5

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);
}

Files

LTE 2019 - Educational Technology Lab - IB - UNICAMP