Stuck with the tcs34725 color sensor with Arduino and processing

Hey Guys!

I need help. I am doing school project with the tcs34725 color sensor and Arduino. I want to use the color rgb and temperature to visualize rain on my screen. I managed with Arduino to control the color of the rain on my computer screen, but i want to use the color temperature to control the amount of rain. The last part i can’t get to work. I am a little bit desperate. I attached my processing and Arduino code. I hope someone can help me with this!

Arduino code

#include <Wire.h>
#include "Adafruit_TCS34725.h"

Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);

int R = 0;
int G = 0;
int B = 0;

int c = 0;

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  uint16_t red, green, blue, clear, colorTemp;

  tcs.getRawData(&red, &green, &blue, &clear);
  colorTemp = tcs.calculateColorTemperature(red, green, blue);

  uint32_t sum = clear;
  float r,g,b;
  float c;

  r= red;
  r /= sum;

  g= green;
  g /= sum;

  b= blue;
  b /= sum;

  r *=256;
  g *=256;
  b *=256;

  R = r;
  G = g;
  B = b;

  Serial.print("Color Temp");
  Serial.print(":");
  Serial.println(colorTemp, DEC); 
  Serial.flush();

  Serial.print("R");
  Serial.print(":");
  Serial.println(R);
 
  Serial.print("G");
  Serial.print(":");
  Serial.println(G);
 
  Serial.print("B");
  Serial.print(":");
  Serial.println(B);
  Serial.flush();
  }

Processing code

import processing.serial.*;

Serial port;

//color sensor
int lf = 10;    // Linefeed in ASCII.  
String myString = null; //all data from arduino 
float colorTemp; 
float R;
float G;
float B;
color fillColor;

// falling rain
ArrayList <Drop> Drops = new ArrayList<Drop>();

Drop myDrop;

void setup(){
 size(1200,700);
 
 //color sensor
 port = new Serial(this, "/dev/cu.usbmodem144101", 9600);
 port.clear();
 
 // falling rain
 background(255);
  for (int i=0; i <100; i++){
       Drops.add(new Drop (random(width),random (-300,0),random(1,4)+2,color(random (255), random (255),random (255)),0,0,height+100-(random(300))));
  }
}

void draw(){ 
 // color sensor
 while (port.available() > 0) {
   myString = port.readStringUntil(lf); //read it until you hit the end of the line. 
   
      if (myString != null) { //if we did that successfully 
      print(myString);  // Prints String 
      int valueStart = myString.indexOf(":");
      if (valueStart > 0) {
        String mySensor = myString.substring(0, valueStart); // substring from 1st to 2nd character
        String myData = myString.substring(valueStart+1, myString.length()-1); 

        // println(mySensor + " I am the sensor"); 
        // println(myData + " I am the data"); 
        // println(mySensor + ":" + myData);

        myData = myData.trim(); 
        
        if (mySensor.equals("colorTemp")) 
        { 
          colorTemp = float(myData);
          println("colorTemp:" + myData);
        }
        
         if (mySensor.equals("R")) 
        { 
          R = float(myData);
          println("r:" + myData);
          }
          
         if (mySensor.equals("G")) 
        { 
          G = float(myData);
          println("g:" + myData);
          }
          
         if (mySensor.equals("B")) 
        { 
          B = float(myData);
          println("b:" + myData);
          }
          
          fillColor = color(R,G,B);
      }
    }
  }
  
  // falling rain
  fill(0,70);
  rect(0,0,width,height);
  
  for (int i=0; i <100; i++){
  Drop b = Drops.get(i);
  
  b.c = fillColor;
  
    if(b.y> b.endPos){
      b.splash();
      }
    else{
     b.rain(); 
    }
 }
 
  port.clear(); // clean up the port so it's ready for new data  
   
 }
 
 void stop() {
  port.stop(); 
  super.stop();
}

Second tablat

class Drop {
  float x;
  float y;
  float speed;
  color c;
  float ellipseX;
  float ellipseY;
  float endPos;
  
  Drop(float rainX, float rainY, float rainSpeed, color rainColor, float rainEllipseX, float rainEllipseY, float rainEndPos){
    x = rainX;
    y = rainY;
    speed = rainSpeed;
    c = rainColor;
    ellipseX = rainEllipseX;
    ellipseY = rainEllipseY;
    endPos = rainEndPos;
  }
  
 void init(){
    x = random(width);
    y = random (-300,0);
    speed = random(1,4)+2;
    c = color(random (255), random (255),random (255));
    ellipseX =0;
    ellipseY =0;
    endPos =height+100-(random(300));
  }
  
 void update(){
  y = y + speed;
}

void rain(){
  fill (c);
  noStroke();
  rect(x,y,5,10,20);
  update();
  }
  
 void splash(){
  stroke(c);
  noFill();
  ellipse(x,y,ellipseX,ellipseY);
  
  ellipseY += speed * 0.2;
  ellipseX += speed * 0.5;
  
  if(ellipseX>50){
      init();
  }  
 }
}
1 Like

Hello,

I have a sensor with that IC from AdaFruit. :slight_smile:

Please format your code and I may have a look at it:
https://discourse.processing.org/faq#format-your-code

You can go back and edit this.

:)

1 Like

Hey!

Did i do the formatting right now? This is the first time i am doing this haha

It is readable and cut and paste-able.
There is always a first time.

I will took a look at this later in the day.

:)

Okay great! Thanks :smiley:

Hello,

Can you show sample output to the serial monitor of Arduino?
I want to get a sense of the data you are sending; I can easily simulate this for testing

My sensor is somewhere; it may still be at work and I don’t have access to that.

:)

This is the output i see!

Hello,

Which part?

Suggestion:
Send the data all at once with only one println() at the end; this represents your data set.
And remove the R:, B: and G: You know where the data starts and ends and do not need to send these.

This is messy but I have sample data in it for testing:

Summary
import processing.serial.*;

Serial port;

//color sensor
int lf = 10;    // Linefeed in ASCII.  
String myString = null; //all data from arduino 
float colorTemp; 
float R;
float G;
float B;
color fillColor;

// falling rain
ArrayList <Drop> Drops = new ArrayList<Drop>();

Drop myDrop;

void setup() {
  size(1200, 700);

  //color sensor
  printArray(Serial.list()); //glv
  //port = new Serial(this, "/dev/cu.usbmodem144101", 9600);
  port = new Serial(this, "COM16", 9600); //glv
  port.clear();


  // falling rain
  background(255);
  for (int i=0; i <100; i++) {
    Drops.add(new Drop (random(width), random (-300, 0), random(1, 4)+2, color(random (255), random (255), random (255)), 0, 0, height+100-(random(300))));
  }
}

void draw() 
  { 
  // color sensor
  //while (port.available() > 0) 
    {
    //myString = port.readStringUntil(lf); //read it until you hit the end of the line. 

    String myString = "Color Temp:6822,R:126,G:101,B:102,"; //Sample data

    if (myString != null) 
      { //if we did that successfully 
      println("myString:  " + myString);  // Prints String 
      int valueStart = myString.indexOf(":");
      if (valueStart > 0) 
        {
        String mySensor = myString.substring(0, valueStart); // substring from 1st to 2nd character
        String myData = myString.substring(valueStart+1, myString.length()-1); 

        println("mySensor:  " + mySensor); 
        println("myData:    " + myData); 
        println(mySensor + ":" + myData);
        //println();

        myData = myData.trim(); 

        // Split into an array and use elements of array
        String [] myData2 = split(myData, ',');
        printArray (myData2);
        
        
        //if (mySensor.equals("Color Temp")) 
        //  { 
        //  colorTemp = float(myData);
        //  println("colorTemp:" + myData);
        //  }

        //if (mySensor.equals("R")) 
        //  { 
        //  R = float(myData);
        //  println("r:" + myData);
        //  }

        //if (mySensor.equals("G")) 
        //  { 
        //  G = float(myData);
        //  println("g:" + myData);
        //  }

        //if (mySensor.equals("B")) 
        //  { 
        //  B = float(myData);
        //  println("b:" + myData);
        //  }
          println();
        fillColor = color(R, G, B);
        }
      }
    }

  // falling rain
  fill(0, 70);
  rect(0, 0, width, height);

  for (int i=0; i <100; i++) 
    {
    Drop b = Drops.get(i);

    b.c = fillColor;

    if (b.y> b.endPos) 
      {
      b.splash();
      } 
    else 
      {
      b.rain();
      }
    }

  port.clear(); // clean up the port so it's ready for new data
  }

void stop() 
  {
  port.stop(); 
  super.stop();
  }

I left some work for you.
Once you have clean strings in the array you can convert that data to an int to use.

You can see why you should remove the R:, G: and B: at source (Arduino) or you have to clean it up at destination (Processing):

I did not have all the the line feeds from println()s when I wrote above; I got ahead of myself and wrote some sample data without them.
Your code may have been working as is.

:)

1 Like

Ok thanks but your solution with the serial string does not work with my version of arduino/processing. I have no problem getting the data in RGB en colortemp the only issue I have is linking the colortemp to control the number of raindrops.

I took a lot of effort to get sofar and since this is part of a schoolassignment I have to stick to certain rules.

So I cannot change the input code,hope that you still can help me otherwise thank you for the effort.

You are receiving:
float colorTemp = 6000;
convert colorTemp to an int for use later.

use int(colorTemp) in your for() loop as the upper limit; you have 100 in there now.

So now your loop will fail because you are trying to create 6000 raindrops but you only created 100 in setup() ready for use.

Increase raindrops to 10000 (it may be a bright and rainy day) in for() loop in setup.

That should give you something to work with.

In the above, the color temp is directly proportional to a number of raindrops.
So on a bright sunny day (6000K) it is really raining hard( 6000 raindrops).

You may want to use map() to change that a bit; lower K and it is raining. I leave that with you.
https://processing.org/reference/map_.html
https://processing.org/examples/map.html

:)

1 Like

Hey i changed the code based on your advice, but it stil does not work, i don’t see any raindrops anymore. Can you check if i did it right?:slight_smile:

I already tried to use the map() function, but do i need to put the map() inside the for loop in the draw function?

import processing.serial.*;

Serial port;

//color sensor
int lf = 10;    // Linefeed in ASCII.  
String myString = null; //all data from arduino 
int colorTemp; 
float R;
float G;
float B;
color fillColor;

// falling rain
ArrayList <Drop> Drops = new ArrayList<Drop>();

Drop myDrop;

void setup(){
 size(1200,700);
 
 //color sensor
 port = new Serial(this, "/dev/cu.usbmodem144101", 9600);
 port.clear();
 
  // falling rain
 background(255);
  for (int i=0; i <10000; i++){
       Drops.add(new Drop (random(width),random (-300,0),random(1,4)+2,color(random (255), random (255),random (255)),0,0,height+100-(random(300))));
  }
}

void draw(){ 
 //color sensor
 while (port.available() > 0) {
   myString = port.readStringUntil(lf); //read it until you hit the end of the line. 
   
      if (myString != null) { //if we did that successfully 
      print(myString);  // Prints String 
      int valueStart = myString.indexOf(":");
      if (valueStart > 0) {
        String mySensor = myString.substring(0, valueStart); // substring from 1st to 2nd character
        String myData = myString.substring(valueStart+1, myString.length()-1); 

        // println(mySensor + " I am the sensor"); 
        // println(myData + " I am the data"); 
        // println(mySensor + ":" + myData);

        myData = myData.trim(); 
        
        if (mySensor.equals("colorTemp")) 
        { 
          colorTemp = int(myData);
          println("colorTemp:" + myData);
        }
        
        
         if (mySensor.equals("R")) 
        { 
          R = float(myData);
          println("r:" + myData);
          }
          
         if (mySensor.equals("G")) 
        { 
          G = float(myData);
          println("g:" + myData);
          }
          
         if (mySensor.equals("B")) 
        { 
          B = float(myData);
          println("b:" + myData);
          }
          
          fillColor = color(R,G,B);
      }
    }
  }
  
  // falling rain
  fill(0,70);
  rect(0,0,width,height);
  
  for (int i=0; i <int(colorTemp); i++){
  Drop b = Drops.get(i);
  
  b.c = fillColor;
  
    if(b.y> b.endPos){
      b.splash();
      }
    else{
     b.rain(); 
    }
 }
 
  port.clear(); // clean up the port so it's ready for new data  
   
 }
 
 void stop() {
  port.stop(); 
  super.stop();
} 
1 Like

I was having issues with converting the string to an int an not sure why at this point.

I did correct it by changing this to only parse for color temp (assuming 4 digits).

String myData = myString.substring(valueStart+1, valueStart+5);
but it is not getting R, G and B now but does help to get at the root of it… hopefully.

So far:

Summary
import processing.serial.*;

Serial port;

//color sensor
int lf = 10;    // Linefeed in ASCII.  
String myString = null; //all data from arduino 
int colorTemp; 
float R;
float G;
float B;
color fillColor;
int test;

// falling rain
ArrayList <Drop> Drops = new ArrayList<Drop>();

//Drop myDrop;

void setup() {
  size(1200, 700);

  //color sensor
  printArray(Serial.list()); //glv
  //port = new Serial(this, "/dev/cu.usbmodem144101", 9600);
  port = new Serial(this, "COM16", 9600); //glv
  port.clear();


  // falling rain
  background(255);
  for (int i=0; i <10000; i++) {
    Drops.add(new Drop (random(width), random (-300, 0), random(1, 4)+2, color(random (255), random (255), random (255)), 0, 0, height+100-(random(300))));
  }
  //noLoop();
}

void draw() 
  {
  background(0);  
  // color sensor
  //while (port.available() > 0) 
    {
    //myString = port.readStringUntil(lf); //read it until you hit the end of the line. 

    String myString = "Color Temp:6822\nR:126\nG:101\nB:102\n"; //Sample data

    if (myString != null) 
      { //if we did that successfully 
      println("myString:  " + myString);  // Prints String 
      int valueStart = myString.indexOf(":");
      if (valueStart > 0) 
        {
        String mySensor = myString.substring(0, valueStart); // substring from 1st to 2nd character
        String myData = myString.substring(valueStart+1, valueStart+5); 

        println("mySensor:   " + mySensor); 
        println("myData1:" + myData); 
        //println(mySensor + ":" + myData);
        //println();

        String myData2 = myData.trim();
        println("myData2:    " + myData2); 

        // Split into an array and use elements of array
        //String [] myData2 = split(myData, ',');
        //printArray (myData2);
        
        if (mySensor.equals("Color Temp")) 
          { 
          test = int(trim(myData));
          println("test "+  test);
          println();
          println("colorTemp2: " + int(myData));
          }

        if (mySensor.equals("R")) 
          { 
          R = float(myData);
          println("r: " + myData);
          }

        if (mySensor.equals("G")) 
          { 
          G = float(myData);
          println("g: " + myData);
          }

        if (mySensor.equals("B")) 
          { 
          B = float(myData);
          println("b: " + myData);
          }
          println();
        fillColor = color(R, G, B);
        }
  }
    }

  //float colorTemp = 6000;
  
  int numDrops = test;
  
  fillColor = color(255, 255, 0);
  // falling rain
  fill(0, 70);
  rect(0, 0, width, height);

  for (int i=0; i <numDrops; i++) 
    {
    Drop b = Drops.get(i);

    b.c = fillColor;

    if (b.y> b.endPos) 
      {
      b.splash();
      } 
    else 
      {
      b.rain();
      }
    }

  port.clear(); // clean up the port so it's ready for new data
  }

void stop() 
  {
  port.stop(); 
  super.stop();
  }

Try it and see if you can glean any insight from the messy code I shared.

:)

1 Like

Yes i get more raindrops now! But how do i need to use the map function to change the number?

Yay!
My sample data did not work because it was not a serial stream! I must be tired.
I was going to write some Arduino code or change the Processing code to stagger input but not now.

See what you can glean from here:
https://processing.org/reference/map_.html
https://processing.org/examples/map.html

First, decide what you want to map.

If you map 32F to 212F to 0C to 100C:

void setup() 
	{
  size(640, 360);
  noLoop();
	}

void draw() 
  {
  for (int F = 32; F<=212; F++)
    {
    float C = map(F, 32, 212, 0, 100);
    println("map:  ", F, C);
    
    //Sames as:
    C = 5.0/9.0*(F-32);
    println("math: ", F, C);
    }
}

map() is really just an equation to a straight line.

Now decide how you want to map() your color K to raindrops; if that is what you want to do.

:)

1 Like

Okay! Thank you i will try if that works!

Hello again,

May I borrow that Drop class for future use?
I will use it as an example only.
Who do I credit?

I will revamp the whole serial receive code to my liking.

My preference is to use:
https://processing.org/reference/libraries/serial/serialEvent_.html

Stay well!

That was a fun distraction for the day.
And the raindrops are still falling!

:)

Hey!

Ofcourse you can use the code! Credits to: Marit. I have one last question for you :smiley:. I tried the map function to change the amount of rain. But i can’t get it to work, processing even crashed :grimacing: I would like to have rain drops between 0 and 500. How do i need to fix this?

Good morning!

Please show your map function and the error.

The map function returns a float and you may have to make that an int before passing to raindrops.

Sometimes Processing crashes… make sure you are saving backups of each working version.

:)

 
  // falling rain
  fill(0,70);
  rect(0,0,width,height);
  int numDrops = test;
  
  for (int i=0; i <numDrops; i++){
    float C = map(i, 0, 10000, 0, 500);
    println("map:  ", i, C);
    
    //Sames as:
    C = 5.0/9.0*(i-0);
    println("math: ", i, C);
  
    Drop b = Drops.get(i);
    
    b.c = fillColor;
    
      if(b.y> b.endPos){
        b.splash();
        }
      else{
       b.rain(); 
      }
 }
 
  port.clear(); // clean up the port so it's ready for new data  
   
 }
```