Este proyecto esta basado en un sensor de dfrobot tcs3200, el cual mediante 4 entradas digitales seleccionamos unos filtros. El sensor produce una salida de onda cuadrada cuya frecuencia es proporcional a la intensidad del filtro elegido.
Mas información: http://www.dfrobot.com/wiki/index.php?title=TCS3200_Color_Sensor_%28SKU:SEN0101%29
Para esto es importante, la iluminación. Por defecto el sensor tiene leds blancos, pero hay que recordar que la luz blanca tiene color rojo, verde y azul, por lo que contamina los datos, además el tipo de material también afectará al resultado.
Importante la luz no debe incidir directamente en el sensor, también contamina el resultado.
Además en VB al intentar reconstruir el color, siempre habrá un error. En la mayoría de los casos el color será muy diferente al color reconstruido y será mejor guiarse por un canal (por ejemplo el rojo) que por la suma de los tres.
El programa que hecho servir es el mismo programa que hay en la web del fabricante, pero le hecho unos pequeños cambios para poder comunicarme con VB.
Código Arduino modificado:
int s0=3,s1=4,s2=5,s3=6;
int out=2;
int flag=0;
byte counter=0;
byte countR=0,countG=0,countB=0;
void setup()
{
Serial.begin(9600);
pinMode(s0,OUTPUT);
pinMode(s1,OUTPUT);
pinMode(s2,OUTPUT);
pinMode(s3,OUTPUT);
}
void TCS()
{
flag=0;
digitalWrite(s1,HIGH);
digitalWrite(s0,HIGH);
digitalWrite(s2,LOW);
digitalWrite(s3,LOW);
attachInterrupt(0, ISR_INTO, CHANGE);
timer0_init();
}
void ISR_INTO()
{
counter++;
}
void timer0_init(void)
{
TCCR2A=0x00;
TCCR2B=0x07; //the clock frequency source 1024 points
TCNT2= 100; //10 ms overflow again
TIMSK2 = 0x01; //allow interrupt
}
int i=0;
ISR(TIMER2_OVF_vect)//the timer 2, 10ms interrupt overflow again. Internal overflow interrupt executive function
{
TCNT2=100;
flag++;
if(flag==1)
{
countR=counter;
Serial.print("R");
if (counter < 100) { Serial.print (0); }
if (counter < 10) {Serial.print (0); }
Serial.print(countR,DEC);
digitalWrite(s2,HIGH);
digitalWrite(s3,HIGH);
}
else if(flag==2)
{
countG=counter;
Serial.print("G");
if (counter < 100) { Serial.print (0); }
if (counter < 10) {Serial.print (0); }
Serial.print(countG,DEC);
digitalWrite(s2,LOW);
digitalWrite(s3,HIGH);
}
else if(flag==3)
{
countB=counter;
Serial.print("B");
if (counter < 100) { Serial.print (0); }
if (counter < 10) {Serial.print (0); }
Serial.print(countB,DEC);
digitalWrite(s2,LOW);
digitalWrite(s3,LOW);
}
else if(flag==4)
{
Serial.print("\n");
flag=0;
}
counter=0;
}
void loop()
{
TCS();
while(1);
}
En el visual basic leo los datos recibidos, un ejemplo:
R122G131B107
R121G130B106
R121G130B106
R120G131B107
R121G130B106
R121G ----Trama incompleta
Mediante las letras R, G y B identifico los valores de cada canal. Para evitar que los valores cambien para cada trama hago servir un timer de 500ms donde cada vez muestro la media de las tramas de cada canal. Para eso hago servir 3 arrays, en este caso la array del canal R tendría 6 valores, mientras que el array del canal G y B 5 valores.
Rojo=(122+121+121+120+121+121)/6= 121
Verde=(131+130+130+131+130)/5= 130
Azul=(107+106+106+107+106)/5= 106
Código del Timer1 de visual basic:
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Dim cuenta As Integer
Dim textin As String
Dim max_muestras As Integer = 100
Dim roig(max_muestras) As Integer 'Red
Dim cnt_r As Integer = 0
Dim verd(max_muestras) As Integer 'Green
Dim cnt_g As Integer = 0
Dim blau(max_muestras) As Integer 'blue
Dim cnt_b As Integer = 0
textin = SerialPort1.ReadExisting() 'guardo todos los datos del puerto
cuenta = textin.Length
TextBox1.Text = TextBox1.Text + textin
'ejemplo puedo recibir:
' R005G200B255
' R006G199B255
' R006G201
'Tengo 3 datos del canal rojo, 3 del verde y dos del azul
For i As Integer = 0 To (cuenta - 1) 'leo los datos
If (textin(i) = "R") And ((i + 3) <= (cuenta - 1)) Then
roig(cnt_r) = CInt(textin(i + 1) + textin(i + 2) + textin(i + 3))
'guardo en un array los datos del canal rojo
cnt_r = cnt_r + 1 'cuento los datos que tengo en el canal rojo
End If
If (textin(i) = "B") And ((i + 3) <= (cuenta - 1)) Then
verd(cnt_g) = CInt(textin(i + 1) + textin(i + 2) + textin(i + 3))
cnt_g = cnt_g + 1
End If
If (textin(i) = "G") And ((i + 3) <= (cuenta - 1)) Then
blau(cnt_b) = CInt(textin(i + 1) + textin(i + 2) + textin(i + 3))
cnt_b = cnt_b + 1
End If
Next
If (cnt_r > 0) Then
For i As Integer = 0 To cnt_r - 1
Red = Red + roig(i) ' 5+5+6 =16
Next
Red = Red / cnt_r 'Hago una media 16/3= 5
If Red >= 0 And Red <= 255 Then 'Compruebo qu el resultado es coherente
lRed.Text = Red
ProgressBarRed.Value = Red '5
End If
cnt_r = 0
End If
If (cnt_g > 0) Then
For i As Integer = 0 To cnt_g - 1
Green = Green + verd(i)
Next
Green = Green / cnt_g 'Hago una media
If Green >= 0 And Green <= 255 Then
lGreen.Text = Green
ProgressBarGreen.Value = Green
End If
cnt_g = 0
End If
If (cnt_b > 0) Then
For i As Integer = 0 To cnt_b - 1
Blue = Blue + blau(i)
Next
Blue = Blue / cnt_b 'Hago una media
If Blue >= 0 And Blue <= 255 Then
lBlue.Text = Blue
ProgressBarBlue.Value = Blue
End If
cnt_b = 0
End If
If Red >= 0 And Red <= 255 And Green >= 0 And Green <= 255 And Blue >= 0 And Blue <= 255 Then
colormuestra.BackColor = Color.FromArgb(Red, Green, Blue)
End If
End Sub
Descargar proyecto: http://www.4shared.com/zip/ucIrUOIm/Control_LedRGB.html
No hay comentarios:
Publicar un comentario