Color Sensor question

roineust:
No text shows up, when i open the serial monitor, with the above code you posted. I tried to press the reset button and it wrote ‘da’ and then ‘dada’ is that the beginning of the word ‘data’ or has the Homer Simpson worm overtaken my computer? :lol:

Hmmmm ... I loaded it into my Arduino Micro and I get what I expect. See the attached .txt file.

What version of Arduino IDE are you using ? Was the serial monitor baud rate set to 9600 ?

roineust:
Any way, as you asked me to do, here is the log of the serial monitor results, from the previous code, just to remind you, s2 and s3 wires are totally disconnected, so do we need them at all in the new code?

Yup, you should connect them if only to get all the colors instead of just 1 color over and over (green being my guess).

roineust:
The attached images are a print screen samples of the results, when the sensor is above the white color and then, again, over the dark color.

The white color sampling outputs numbers of around 2700-2800 and the dark color sample outputs numbers of around 2500-2600.

Were those the same as your yellow-white and dark brown ? You can mouse select text in the serial monitor and then Control-c copy it to be pasted into a text file using just the Notepad editor. It's easier than screenshots and can show more data.

Just to eliminate any copy’n’paste errors, here’s a copy of the .ino file I used … renamed as a .txt so I could attach it here. Just change the extension back to .ino and put it in a subfolder of the same name (TCS230Copy) in your Arduino folder. Then see if it’ll upload and run.

FWIW- can you understand what this last version of code does ?

Houston, we have a problem.

But I’ve found and fixed it. I put a right brace, }, in the wrong place. Here’s a snippet of the existing erroneous code with comments added to point out the error.

    default:
      //code should never get here
      Serial.println("Error");
      //reset the state machine
      count = 0;
      state = 0;
      //set next color to red
      digitalWrite(S2, LOW);
      digitalWrite(S3, LOW);
      break;
      <----- The } below should be here --------------------------------------
    //wait 1 sample period to collect counts from TCS230
    delay(smpl_period);
    //state machine end
  } <-------- This } should be 4 lines up --------------------------------------
}

And here’s what it should be. Fix it and give it a try.

    default:
      //code should never get here
      Serial.println("Error");
      //reset the state machine
      count = 0;
      state = 0;
      //set next color to red
      digitalWrite(S2, LOW);
      digitalWrite(S3, LOW);
      break;
  }
  //wait 1 sample period to collect counts from TCS230
  delay(smpl_period);
  //state machine end
}

This is why code has to be tested and proven to work before believing it’s resultts. And why I dislike posting code I can’t test.

On that note I figure out a way to semi-test the fixed code above. It’s not giving as accurate a count as I expected. I put a pulse-train of 990 Hz into the Arduino. I increased the sample period back to 1 sec. The counts should all have been 990 +/- 2 counts. I’m seeing 977s. I’m not sure if this really matters for your usage but it bothers me, so I’m investigating it.

Is the new version any more understandable than the original you posted ?

In the meantime, i decided to go for just duplicating parts in the code, so duplicate=2 sensors, triplicate=3 sensors. And also, changing the first instance of the command attachInterrupt(0, TSC_Count, RISING); to attachInterrupt(1, TSC_Count, RISING); in the second instance of the duplicated line.

Yet, The code still does not work for both the sensors at the same time, but only for one. :doh:

Is it possible for you to explain to me, why this duplication method, did not work?

Here is the code i am referring to:

#include <TimerOne.h>

#define S0     6
#define S1     5
#define OUT    2

#define S01     8
#define S11     7
#define OUT1    3

int   g_count = 0;    // count the frequecy
int   g_array[3];     // store the RGB value
int   g_flag = 0;     // filter of RGB queue
float g_SF[3];        // save the RGB Scale factor

int   g_count1 = 0;    // count the frequecy
int   g_array1[3];     // store the RGB value
int   g_flag1 = 0;     // filter of RGB queue
float g_SF1[3];        // save the RGB Scale factor
 
 
// Init TSC230 and setting Frequency.
void TSC_Init()
{
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(OUT, INPUT);
 
  digitalWrite(S0, LOW);  // OUTPUT FREQUENCY SCALING 2%
  digitalWrite(S1, HIGH); 
}

void TSC_Init1()
{
  pinMode(S01, OUTPUT);
   pinMode(S11, OUTPUT);
   pinMode(OUT1, INPUT);
 
  digitalWrite(S01, LOW);  // OUTPUT FREQUENCY SCALING 2%
  digitalWrite(S11, HIGH); 
}
 
// Select the filter color 
void TSC_FilterColor(int Level01, int Level02)
{
  if(Level01 != 0)
    Level01 = HIGH;
 
  if(Level02 != 0)
    Level02 = HIGH;
 
 // digitalWrite(S2, Level01); 
  //digitalWrite(S3, Level02); 
}

// Select the filter color 
void TSC_FilterColor1(int Level011, int Level021)
{
  if(Level011 != 0)
    Level011 = HIGH;
 
  if(Level021 != 0)
    Level021 = HIGH;
 
  //digitalWrite(S2, Level01); 
  //digitalWrite(S3, Level02); 
}
 
void TSC_Count()
{
  g_count ++ ;
}

void TSC_Count1()
{
  g_count1 ++ ;
}
 
void TSC_Callback()
{
  switch(g_flag)
  {
    case 0: 
         Serial.println("->WB Start");
         TSC_WB(LOW, LOW);              //Filter without Red
         break;
    case 1:
         Serial.print("->Frequency R=");
         Serial.println(g_count);
         g_array[0] = g_count;
         TSC_WB(HIGH, HIGH);            //Filter without Green
         break;
    case 2:
         Serial.print("->Frequency G=");
         Serial.println(g_count);
         g_array[1] = g_count;
         TSC_WB(LOW, HIGH);             //Filter without Blue
         break;
 
    case 3:
         Serial.print("->Frequency B=");
         Serial.println(g_count);
         Serial.println("->WB End");
         g_array[2] = g_count;
         TSC_WB(HIGH, LOW);             //Clear(no filter)   
         break;
   default:
         g_count = 0;
         break;
  }
}

void TSC_Callback1()
{
  switch(g_flag1)
  {
    case 0: 
         Serial.println("->WB Start*1*");
         TSC_WB1(LOW, LOW);              //Filter without Red
         break;
    case 1:
         Serial.print("->Frequency R*1*=");
         Serial.println(g_count1);
         g_array1[0] = g_count1;
         TSC_WB1(HIGH, HIGH);            //Filter without Green
         break;
    case 2:
         Serial.print("->Frequency G*1*=");
         Serial.println(g_count1);
         g_array1[1] = g_count1;
         TSC_WB1(LOW, HIGH);             //Filter without Blue
         break;
 
    case 3:
         Serial.print("->Frequency B1*1=");
         Serial.println(g_count1);
         Serial.println("->WB End*1*");
         g_array1[2] = g_count1;
         TSC_WB1(HIGH, LOW);             //Clear(no filter)   
         break;
   default:
         g_count1 = 0;
         break;
  }
}
 
void TSC_WB(int Level0, int Level1)      //White Balance
{
  g_count = 0;
  g_flag ++;
  TSC_FilterColor(Level0, Level1);
  Timer1.setPeriod(100000);             // set 1s period
}

void TSC_WB1(int Level01, int Level11)      //White Balance
{
  g_count1 = 0;
  g_flag1 ++;
  TSC_FilterColor1(Level01, Level11);
  Timer1.setPeriod(100000);             // set 1s period
}
 
void setup()
{
  TSC_Init();
  TSC_Init1();
 
  Serial.begin(9600);
   Timer1.initialize();             // defaulte is 1s
   //Timer3.initialize();             // defaulte is 1s
  
  Timer1.attachInterrupt(TSC_Callback);  
  attachInterrupt(0, TSC_Count, RISING);  

  Timer1.attachInterrupt(TSC_Callback1);  
   attachInterrupt(1, TSC_Count1, RISING);  
 
  delay(400);
 
  for(int i=0; i<3; i++){
    Serial.println(g_array[i]);
     Serial.println(g_array1[i]);
  }
 
  g_SF[0] = 255.0/ g_array[0];     //R Scale factor
  g_SF[1] = 255.0/ g_array[1] ;    //G Scale factor
  g_SF[2] = 255.0/ g_array[2] ;    //B Scale factor
  
  g_SF1[0] = 255.0/ g_array1[0];     //R Scale factor
  g_SF1[1] = 255.0/ g_array1[1] ;    //G Scale factor
  g_SF1[2] = 255.0/ g_array1[2] ;    //B Scale factor
 
  Serial.println(g_SF[0]);
  Serial.println(g_SF[1]);
  Serial.println(g_SF[2]);
  
  Serial.println(g_SF1[0]);
  Serial.println(g_SF1[1]);
  Serial.println(g_SF1[2]);
 
}
 
void loop()
{
   g_flag = 0;
    g_flag1 = 0;
   for(int i=0; i<3; i++){
    Serial.println(int(g_array[i] * g_SF[i]));
     Serial.println(int(g_array1[i] * g_SF1[i]));
   }
   delay(1000);
 
}

roineust:
I am not able to hold on to the pace, neither of the content you are referring to, nor to the pace of changes, you are making on that undecipherable content itself.

Think of yourself as a 12th grader, who is supposed to explain stuff to a 3rd grader. That’s more or less the differences here…

Your instructions and code look to me, closer to the UFO’s of an intelligent species, who came to earth at some Paleolithic age and were surprised to discover, that the ape like creature residing there, needs a whole day to light a tiny fire.

Not knowing what, if any, background you have let me recommend that you should read the following pages to "learn how to swim". While jumping into the deep end, as you have here, is often touted as a quick way to learn, more often you end up just gasping for air before giving up and drowning.

http://arduino.cc/en/Tutorial/Foundations

Read the pages on the basics of a sketch (gack, I loathe that term). Then the pages on digital pins, variables and functions.

http://arduino.cc/en/Tutorial/HomePage

Look at the 1’st pages on Basics and then those under Control structures for - if, for loops and the switch case.

If you can grok the above then you should be able to look at, and decipher how, most sketches work. Look at the sketches in the lessons on this page.

http://arduino.cc/en/Tutorial/Links

Above all else bookmark this page and have it open when reading or writing a sketch.

http://arduino.cc/en/Reference/HomePage

It’s your Rosetta Stone.

I’ll address where your attempt to add another TCS230 went so [Bill_Murray_voice] wrong, horribly wrong [/Bill_Murray_voice] in another post.

Thanks and sorry for being unmethodical, in my journeys through this wonderful world of DIY electronics&software.

roineust:
In the meantime, i decided to go for just duplicating parts in the code, so duplicate=2 sensors, triplicate=3 sensors. And also, changing the first instance of the command c to attachInterrupt(1, TSC_Count, RISING); in the second instance of the duplicated line.

Yet, The code still does not work for both the sensors at the same time, but only for one. :doh:

You were close but since coding is neither horseshoes nor hand-grenade tossing, your attempt falls short. What would be needed ? It would seem that you've figured out that each TCS230 output needs it's own, separate Arduino input pin. And if your memory serves you well you will recall that it must be a special pin, an external interrupt pin. A review of this page is in order.

http://arduino.cc/en/Reference/AttachInterrupt

It shows what pins can be used on which Arduino and what interrupt #, which is all the code “knows”, goes with each pin.

So if you wired your 2 devices to pins 2 and 3, your code statements above would be almost correct. Let’s look at that page a bit more, especially that 1’st line.

Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs.

How does that line do that ? Let’s look down a few lines to the syntax.

attachInterrupt(interrupt, ISR, mode)

Yup, the ISR named TSC_Count is what will run when interrupt 0 or 1 occurs, per your statements. Hmmmm, that’s not right is it ?

Analogy time - you’re assigned to watch 2 kids, Dennis and Menace, but you also want to watch the Big Game. Since the kids are mostly good, needing minimal attention, you plan to tie a string from each to you arms, Dennis to the left and Menace to the right. When you feel a tug on the string you’ll pause the cable box and tend to the kid. When done you’ll go back and un-pause the game, having missed nothing due to the interruption. And while you’re at it you’ll keep a count of each kids total # of pulls so when asked you can say “Yes dear, I checked on the kids, X and Y times as a matter of fact”.

Alas you’ve tied (by analogy) Menace’s string, by mistake, to your left arm too. Since all you know is which arm has been tugged on, will Menace ever get any attention ?

So you need a separate ISR for each device. Let’s look at the existing ISR.

//this is the external interrupt / counter ISR
void TSC_Count()
{
  count ++ ;
}

http://arduino.cc/en/Reference/Increment

All it does “keep count of the tugs”. It increments by 1 a variable (0, 1, 2, …) every time it runs. If you don’t use a different variable in that 2’nd ISR you’ll be looking at Menace when he pulls but mistakenly adding 1 to Dennis’s count.

So at this point you might have 2 ISRs, TSC1_Count() and TSC2_Count() using 2 variables, count1 and count2. You got this part right.

Is there more … yes. Look at this.

//declare the constants
#define S0     6
#define S1     5
#define S2     4
#define S3     3
#define OUT    2

You need a new, differently named OUT for the added device and a new pin assigned to S3 since pin3 is needed for that other “OUT”. FWIW all S0 pins can be wired together as can the S1s, S2s and S3s. Only 4 Arduino pins are, at most, needed to control all the TSC230s. You got this part right too.

And then there’s setting the pins up.

  //set the pins to be I or O
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(OUT, INPUT);

And declaring the variables.

//declare the variables
volatile int   count = 0; //a count of pulses from TSC230

What’s missing ? You got these parts right above.

At this point your Arduino will collect the data but you’ve yet to print it out. Yup, more changes in all of the “cases”. Look at just one, what needs changing/adding ?

      Serial.print("Counts R = ");
      Serial.println(count);
      //reset the counter
      count = 0;

You may have notice I’m using the fixed version of my code. It’s so much easier to read and devoid of unneeded code, you should too. You over did this part in your attempt, due to the original code being obtuse and your skill level.

fixed code:

//version 0.11 of TCS230 code

//declare the constants
#define S0     6
#define S1     5
#define S2     4
#define S3     3
#define OUT    2

const unsigned long smpl_period = 100; //sample period in msec

//declare the variables
volatile int count = 0; //a count of pulses from TCS230
int state = 0;          //state machine control variable
int set = 0;            //a count of the RGBW sets processed

void setup() {
  //set the baud rate
  Serial.begin(9600);
  //set the pins to be I or O
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(OUT, INPUT);
  //set the max freq of the TCS230 output
  digitalWrite(S0, LOW);  // OUTPUT FREQUENCY SCALING 2%
  digitalWrite(S1, HIGH); // OUTPUT FREQUENCY SCALING 2%
  //set the 1st color to be analyzed
  //this color is red
  digitalWrite(S2, LOW);
  digitalWrite(S3, LOW);
  //attach and enable the external interrupt(s)
  attachInterrupt(0, TSC_Count, RISING);
  //wait 1 sample period to collect counts from TCS230
  delay(smpl_period);
  //go to state machine ready to process 1st color
}

void loop() {
  //run state machine to collect and process data
  switch (state)
  {
    case 0:
      //process the collected red count data
      //freeze the counter(s)
      noInterrupts();
      //send the data
      Serial.print("Data set number = ");
      Serial.println(set);
      Serial.print("Counts R = ");
      Serial.println(count);
      //reset the counter
      count = 0;
      //set next state
      state ++;
      //set next color to green
      digitalWrite(S2, HIGH);
      digitalWrite(S3, HIGH);
      //re-enable the counter(s)
      interrupts();
      break;
    case 1:
      //process the collected green count data
      //freeze the counter(s)
      noInterrupts();
      //send the data
      Serial.print("Counts G = ");
      Serial.println(count);
      //reset the counter
      count = 0;
      //set next state
      state ++;
      //set next color to blue
      digitalWrite(S2, LOW);
      digitalWrite(S3, HIGH);
      //re-enable the counter(s)
      interrupts();
      break;
    case 2:
      //process the collected blue count data
      //freeze the counter(s)
      noInterrupts();
      //send the data
      Serial.print("Counts B = ");
      Serial.println(count);
      //reset the counter
      count = 0;
      //set next state
      state ++;
      //set next color to white
      digitalWrite(S2, HIGH);
      digitalWrite(S3, LOW);
      //re-enable the counter(s)
      interrupts();
      break;
    case 3:
      //process the collected "white" count data
      //freeze the counter(s)
      noInterrupts();
      //send the data
      Serial.print("Counts W = ");
      Serial.println(count);
      Serial.println(" ");
      //reset the counter
      count = 0;
      //set next state
      state = 0;
      //increment the data set counter
      set ++;
      //set next color to red
      digitalWrite(S2, LOW);
      digitalWrite(S3, LOW);
      //re-enable the counter(s)
      interrupts();
      break;
    default:
      //code should never get here
      Serial.println("Error");
      //reset the state machine
      count = 0;
      state = 0;
      //set next color to red
      digitalWrite(S2, LOW);
      digitalWrite(S3, LOW);
      break;
  }
  //wait 1 sample period to collect counts from TCS230
  delay(smpl_period);
  //state machine end
}

//this is the external interrupt / counter ISR
void TSC_Count()
{
  count ++ ;
}

I reiterate that getting the code working in it’s final form for a single sensor will save you a lot of typing.