Using the TCS3200 with Arduino or Parallax Propeller.

Image of the TCS3200 chip - from emartee

Working on a project which requires color detection, but you don’t want to bother with making your own color sensor? The TCS3200 is a great sensor offering sampling rates much higher than one made with a photoresistor. The main downfall to it is that the TCS3200-DB package from Parallax is very expensive ~ 80$ and more complicated to calculate spectral response compensation. If you’re up for some fun, make your own color sensor!

How it works:

As you can see there is an array of photodiodes with color filters on top. There are four types of filters – red, blue, green, and a clear filter. You may have noticed that there are multiple photodiodes of each color, and this helps reduce bad readings due to non-uniformity of incoming light.

TCS3200-DB package from parallax

Excluding power, TCS3200 only has 1 output and the rest of the wires are all inputs. The output is a 50% duty cycle square wave with a frequency proportional to the light intensity (irradiance) on the selected filter. There are two pins to divide the frequency of the square wave S0 and S1, and two pins to select the color filter S2 and S3. The chip works from 2.7V to 5.5V, so it’ll work fine with 3.3V or 5V micro controllers.

Wiring:

When using the TCS3200-DB with Arduino: Connect Vdd, V, and +5v to the Arduino’s 5V line, Gnd connects to the Arduino’s Ground. All other wires are on the example program.

TCS3200 Wiring

Program functionality for Arduino:

The program will need to determine if there an object in front of the sensor. If there is an object present, then figure out what color it is. I will be looking at the TCS3200 output’s rising edge to the falling edge, so the less time elapsed means that there is more light. There will be some redundant readings, but this is to help ensure correct detection if anything is moving.

Take a measurement with the LED off, then compare that to a measurement with the LED on (line 53), both using the clear filter. If there was a significant difference then that means that there is an object in front of the sensor. If there wasn’t a significant difference then just return a zero (line 61-64).

Image from TCS3200 datasheet

Take a clear filter reading and compare it with readings of each color filter, both with the LED on (line 67-72). Then do somewhat of a reverse ratio, since smaller means more light, and pick the largest reading (lines 70 – 96).

Now there will be a serial output of all the ratios and this program simply selects the largest. If you need more accurate readings instead of just the primaries, then I suggest divide the ratio with the spectral response found in the datasheet.

Spectral and pinout from datasheet. Note: if you're using the product from Parallax, use the spectral response from their TCS3200_doc.pdf.

There are plenty of comments in the programs below to help the user get started. there is a detectColor(TCS3200’s output square wave pin) that will return a 0 if nothing is in front of the sensor, 1 for red, 2 for blue, and 3 for green. After each reading it will power off the TCS3200 chip and LED.

I don’t fully support the Parallax Propeller, but I did write a simple program to do basic readings.

TCS3200 for Arduino with line numbers

TCS32000 for Arduino without line numbers

TCS3200 with Parallax Propeller (main.spin)

TCS3200 with Parallax Propeller (taosCountLib.spin)

Or download everything from RapidShare

Color detection with Arduino for under 5$

Let’s say that you’re working on a project and it needs color detection. This guide will help you make a basic red, blue, green color detector that will decide if an object is present – and the color of the object. A range of up to 6cm is possible with proper guidance tubes! Let’s look at some of the options of completed sensors on the market:

The TCS3200 is a great sensor that I’ve used on Propeller and Arduino based projects, but its 80$ per sensor once shipping is paid! For the ASEE robot we needed two of these and our total budget was 450$! Since we purchased a TCS3200,  I decided to reverse engineer it and create my own! It’s a great sensor, but do we really need an adjustable lens with anti reflective coatings? It’s a bit large too…

There are two white LEDs and an array of photodiodes inside. Some of those photodiodes have color filters on them. Pulling certain pins high/low will determine which diode groups are selected — no filter, red, blue, green. The color sensor outputs a square wave and it’s frequency is proportional to the light intensity. There are also frequency multiplication pins which change the proportional constant.

Design:

There are a few different ways to do this, but I’ll cut to the chase and give you what I found to be the best. Let’s use a sensor to measure ambient light, and compare that measurement to measurements with only a powered red LED, blue LED, and finally a green LED. I say ‘sensor’ because there are many different light sensors that will fit the job.

Some of the major pros of this method is that it only needs 3 digital pins and 1 analog pin on the micro controller when using a photoresistor. If you want to use a photoresistor but don’t have analog pins, then use my “Measuring resistance or voltage with 1 I/O” post! This sensor can be built into a very small form factor with decent sampling rates less than 20ms!

Choosing a light sensor – this guide is for a photoresistor:

Choosing the LED:

  • ‘Piranha’ RGB LED – what I used because we had some sitting around looking for a nibble.
  • RGB LED – another LED that would be great.
  • Just use 3 separate bright LEDs

    Schematic: Click to enlarge

The build:

The Piranha RGB LED is a bit different than we might expect. In order to turn on the red LED we’ll need to pull the blue and green pins HIGH, then pull red LOW. Only one LED at a time may be lit, otherwise the LED with the lowest threshold voltage will probably be the only one to light.

This design will use 19mA per sensor. Two sensors may have their LED lines tied together since the Arduino is capable of sourcing/sinking 40mA. Each color sensor’s photoresistor (output) will need a dedicated ADC pin on the micro controller.

Important:

Photoresistor tube is shorter.

Isolate the LED and photoresistor by using white paper tubes wrapped in a layer of electrical tape. Cut the tubes so that they’re

Black tape behind photoresistor

about 2-3cm long and fit one on the LED and put the other on the photoresistor with a black piece of tape stuck to the back of the resistor. You want to block as much light as possible on the back end of the photoresistor.

Improving results:

Here’s a way to get a rough calibration: The wavelength for the Piranha is Red: 630nm, Green: 525nm, Blue: 470nm. Now look at the spectral response for your sensor. We can make software corrections to the measurements at the LED’s wavelength. I would suggest doing a constant multiplication to the reading to get all readings to 100%. The color detection ran well enough that I didn’t need to do this for my project.

In the schematic above a 10k Ohm resistor was picked mostly because that size worked well for me. The resistor value depends on the light levels and the tube length you’re going to be working with on your robot. A longer tube increase range, but decrease overall light values. This will require a resistor around 20k.  Mainly you’ll want to put one of the photodiodes in the tube prior to the build and put it in the environment you’ll be using it in. Here’s a graph that will explain why.

My photoresistors to up to 200k in pitch dark! Graph made with WolframAlpha

Let’s say that we want the sensor to be very directional and view a far ways away. Since the photoresistor is deep inside a tube, it won’t be exposed to much light. Since it’s probably operating past 100k ohms, if the resistance changes to 150k ohms, then the voltage will hardly change at all when using a 10k grounding resistor. Don’t forget that there are only 1024 segments with the on board 10bit ADC! You’ll want to use a part of the graph which has a large negative slope (left side). The right side of the graph will be difficult for the microcontroller to interpret when using small resistor values. A 100k resistor will have a small negative slope, but it’s distributed all over the graph. If you want to adjust the resistance after the project is already done: just add resistance to the ground pin of the sensor. The ground pin connects directly to the 10k resistor, and nothing else uses it. Remember that resistors in series is just the sum of the individual values.

You could also think of this in terms of curvyness, so curvature will be small, then large, then small. Don’t go past the large value for curvyness. Methods exist to calculate curvyness but not necessary. If you’re interested it’s on page 833 of James Steward – fundamentals of calculus 6th ed.

Alternative designs:

You could use four possibly three photoresistors and have colored filters in front of them. Then a white LED to look for reflectivity. This method is more difficult to calibrate, and would require three to four analog pins with one digital pin for the LED.

Code for Arduino:

Color Detection code (pdf)

Measuring resistance or voltage with 1 digital I/O

Let’s say that you’re trying to measure some resistance, but running low on analog pins. Maybe you’re using a microcontroller (aka micro) that’s purely digital, such as the parallax propeller. Well my friends this post is for you! Let’s consider the fact that nearly all micro’s digital pins trigger at 1/2 of the voltage they micro is being driven at. If we slowly increase the voltage of a micro’s digital input, the micro will consider it HIGH at 2.5+ volts for a 5v micro.

If we use a simple charging RC circuit, we can think of the final voltage as 2.5 volts. What if we have the micro discharge the circuit, so we start at about 0v. After the circuit is discharged the micro will turn the pin to input and time how long the circuit takes to charge to 2.5v. Resistance is easily calculated knowing initial and final voltage, capacitance, and time elapsed.

Math:

At the top is the classical, time domain, voltage of a charging capacitor. Vcap is the capacitor voltage, Eemf is the electromotive force (charging voltage), C is the capacitor’s capacitance, t is the time in seconds, and R is the resistance being solved for.

Vcap will be 2.5v when micro triggers, C is .1uF, t is in micro seconds, Eemf is 5v. For arduino, which runs at 5v and digital I/O triggers at about 2.5v. Notice that the 10E-6 cancels out. This is good since Arduino doesn’t have alot of sigfigs to work with during calculations.

Make sure that the time that this circuit takes is reasonable. The time below is in Seconds. Everything else is same as before, R is approximately what resistance is being measured.

variables are same values as above.

Vcap was switched to Vc

Schematic:

As you can see the circuit is fairly simple. The 270Ohm resistor is to limit current the current as the micro discharges the capacitor. The R is the resistance we’re trying to measure.

This circuit is not meant for extremely high sampling rates. If you absolutely need a high sample, then I suggest that you get an ADC chip to do it all for you. Note that if the resistance is high, then you might want to decrease capacitance. If Resistance is very low, then increase capacitance. Only do this if you’re having problems though.

Sometimes the ADC chip is worth it, but if you don’t happen to have one lying around, or if you don’t want to mess around with spi or I2C, then this is a quick work around.

So in this screenshot I had channel 1 (yellow) connected to the capacitor. Channel 2 (blue) connected to a signal pin on the micro. The capacitor’s voltage suddenly drops down when the micro discharges it. When the blue line’s rising edge occurs, that signals the I/O measurement has begun and the pin is set to input. We can then see the blue line’s falling edge occurs when the capacitor’s voltage is at 2.5 volts. As soon as the 2.5 mark is it, the circuit is ready for another sampling. I just had the sampling set to some arbitrary length of time.

Here’s a video of it in action!

Original forum posts

http://arduino.cc/forum/index.php/topic,50642.msg361179.html#msg361179

http://adafruit.com/forums/viewtopic.php?f=25&t=19476

Code for the Arduino:

Any analog references are solely for debugging. Remove them when you are confident everything’s working.

Click to download resistor measurement program (pdf)

Measuring Voltage using this method: I do like the thought of using 1 i/o to measure nearly any range of voltage, but basically if you’re measuring up to 100 volts, then this method will only be able to measure 50-100 volts. This is because the voltage divider will make the 0-100v into 0-5v, and the pin won’t trigger below about 2.5v. This equation was calculated using Thevenin’s theory. It could also easily be solved using nodal analysis, but then we’d have some calculus to do! I feel as though this is impressive to do very accurate voltage calculations, but it’s a bit complicated and doesn’t work over the full range. An op amp could be added to give a wider voltage measurement range, but this is would require additional pins… and the op amp output won’t like charging capacitors!

Well the voltage calculation was off, but fitting the calculated versus real output results in a linear function with slope almost 1. Interestingly it’s off by a constant.

I decided not to investigate why, but it is probably a result of component 10% manufacturing tolerance.

If you decide to give this a shot, then use the top middle schematic with the equation on the very bottom “a” is 2.5 (on the mid left). I suggest you do a function fit of calculated versus real voltage output like I did. Code is extremely similar to the example above. Of course you could just do a function fit for the entire thing since the picture shows the form of the equation.

code for voltage measurement: voltage_measuring_rc

Sharp proximity sensor Function Fitting

Ultrasonic distance sensors, such as the Ping))), are great, but they aren’t cheap and often have very low refresh rates around 50ms. The sharp sensor becomes an attractive alternative since it updates about 1-2 milliseconds, outputs a fairly consistent distance measurement, and it’s about 15$!

Long range Sharp Sensor

Long range Sharp Sensor (Image by sparkfun.com)

What an awesome looking little guy! The only problem with him is that it’s difficult to calculate an accurate distance from his analog output, but with a little bit of some curve fitting we’ll have the problem solved.

The graph that the data sheet provided gives a good bird’s-eye view of how to solve the problem. For this fit, It will be accurate about 15-150cm. I just simply plugged in a voltage meter and started taking measurements of the output voltage. I then used logger pro to plot and fit the points.

sharp Fitting (click to enlarge)

For this example, I was using the Arduino. One thing to keep in mind is that the arduino only has a 10bit ADC. The voltage of interest for the sharp sensor ranges from about .5-2.7 volts. In this range we only have about 450 points of measurement by the ADC. In order to improve this I set the analog reference to internal which maxes out at 1.1volts. Then used a voltage divider on the sharp sensor’s output so that 2.7+.1 scaled to 1.1 volts.

For the voltage divider, I just used a 20k potentiometer, so R1+R2 = 20k. Vin is 2.8, Vout is 1.1, so R2 needs to be 7857ohms (measure this with your voltmeter.). So the center tab of the pot will be Vout, And the sides will be R1 and R2. It doesn’t matter on your polarity, but make sure that the 7857ohms is what’s connected to ground. Once you’ve wired everything check Vout to ensure the 2.7v output is a little below 1.1v.

I will mention that when the sharp sensor updates, it will make a little ‘bloop’ in the analog voltage output. The signal to noise ratio tends to drop right before and after it updates. You can put a capacitor connected to the micro controller’s analog input pin and connect the other wire of the capacitor to ground. If you need to filter some of the readings, as I did, then I suggest don’t use the capacitor, filter, then do a running average. The method of read ->filter -> running average seemed to work best.

Below is example code for Arduino, and I simplified the equation a bit! I was using a 2.64v to 1.1 voltage divider, but you can just key in your values.

Note: All analogs are on 1.1v! Don’t go above this or you’ll probably fry your chip!

Code for Arduino: (ver ~ 0022)

Click to download Sharp Interpretation program (pdf)