Помогите с кодом для Сенсора цвета

Обсуждаем Arduino, Raspberry Pi и другие электронные компоненты и проекты DIY
Ответить
Лиза
Сообщения: 2
Зарегистрирован: 19 фев 2014, 11:06

Помогите с кодом для Сенсора цвета

Сообщение Лиза »

Добрый день! Мы - студенты с факультета пром. дизайна, и у нас возникли сложности с, в общем-то, несложной задачей. У нас есть 2 готовых кода для сенсора цвета, который мы не можем адаптировать под наш проект. в готовом коде сенсор считывает цвет и выдает словесное обозначение этого цвета (типа: это красный). Нам же надо, чтобы при чтении определенного цветового сигнала с помощью сенсора, ардуино преобразовывал его в нужный нам другой цветовой код и посылал новый цветовой сигнал на RGB- ленту. То есть: сенсор "увидел" ЖЕЛТЫЙ - лента загорелась ОРАНЖЕВЫМ; сенсор "увидел" СИНИЙ - лента загорелась ФИОЛЕТОВЫМ. Мы пытались написать свой кусок кода с функцией, но как-то совсем запутались. С ардуино мы знакомы вот уже 3 недели). Помогите, пожалуйста, а то завтра защита, а у нас ни одного рабочего прототипа. Спасибо.

Вариант кода 1:
#include <TimerOne.h>

#define OUT 2
#define S2 5
#define S3 6
#define S0 3
#define S1 4

volatile int g_count =0;
int g_flag = 0;
int g_array[3] = {0};
float g_SF[3] = {0};

void setup()
{
// Init TSC230 and setting Frequency.
pinMode(S0, OUTPUT);
pinMode(S1, OUTPUT);
pinMode(S2, OUTPUT);
pinMode(S3, OUTPUT);
pinMode(OUT, INPUT);

digitalWrite(S0, LOW); // OUTPUT FREQUENCY SCALING 2%
digitalWrite(S1, HIGH);

Serial.begin(115200);
Timer1.initialize(); // defaulte is 1s
Timer1.attachInterrupt(TSC_Callback);
attachInterrupt(0, TSC_Count, RISING);

delay(4000);

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

estabeleceContato(); // aguarda contato com o processing
}
void loop()
{
g_flag = 0;
for(int i=0; i<3; i++)
{
int val = int(g_array * g_SF);
val = constrain(val, 0, 255);
Serial.write(val);
}
delay(4000);

}

// seta o filtro
void TSC_FilterColor(int Level01, int Level02)
{
if(Level01 != 0)
Level01 = HIGH;

if(Level02 != 0)
Level02 = HIGH;

digitalWrite(S2, Level01);
digitalWrite(S3, Level02);
}
// incrementa g_cont cada vex que a sáida do sensor
// vai do nivel baixo ao alto
void TSC_Count()// finção chamada pela interrupção
{
g_count ++ ; // incrementa g_cont
}

void TSC_Callback()
{
switch(g_flag)
{
case 0:
TSC_WB(LOW, LOW); //Red
break;
case 1:
g_array[0] = g_count;
TSC_WB(HIGH, HIGH); //Green
break;
case 2:
g_array[1] = g_count;
TSC_WB(LOW, HIGH); //Blue
break;
case 3:
g_array[2] = g_count;
TSC_WB(HIGH, LOW); //Clear(no filter)
break;
default:
g_count = 0;
break;
}
}

void TSC_WB(int Level0, int Level1) //balanceamento de branco
{
g_count = 0;
g_flag ++;
TSC_FilterColor(Level0, Level1);
Timer1.setPeriod(1000000); // define periodo de 1 segundo
}

void estabeleceContato() {
while (Serial.available() <= 0) {
Serial.write('A'); // envia A ate estabelecer contato
delay(300);
}
}

int redPin = 11;
int greenPin = 10;
int bluePin = 9;

void setup()
{
pinMode (redPin,OUTPUT);
pinMode (greenPin,OUTPUT);
pinMode (bluePin,OUTPUT);
}

void loop()
{
if (TSC_WB(LOW, LOW))//if red
{
setColor(255,150,0);//orange
}
if else ( g_array[1] = g_count;
TSC_WB(LOW, HIGH))//blue
{
setColor(0,255,0);//green
}
void setColor(int red, int green, int blue)
{
analogWrite(redPin,red);
analogWrite(greenPin,green);
analogWrite(bluePin,blue);
}

/*
TCS230 sensor calibration and color matching

Input and output is via the Serial console.
Enable <newline> on the console.

How to use this:
1. Run the software in LEARN MODE and capture the calibration
constants and the output for an array of colors. Easiest is to
edit the table in the header file with the names of the colors
and use that as a prompt when scanning the color.
2. At the end of scanning all the colors, the text for the header
file is produced in the serial console. Cut and paste that into
the actual header file to capture the calibration and color
table data that has just been 'learnt'.
3. Compile and download the program.
4. Run the program in MATCH MODE to test the color recognition.
Each color will be matched to an entry in the color table and
t he name of the closest color will be displayed.
*/

#include <MD_TCS230.h>
#include <FreqCount.h>
#include "ColorMatch.h"

#define BLACK_CAL 0
#define WHITE_CAL 1
#define READ_VAL 2
#define LEARN_VAL 3

#define LEARN_MODE 'L'
#define MATCH_MODE 'M'

// Pin definitions
#define S2_OUT 12
#define S3_OUT 13
#define OE_OUT 8 // LOW = ENABLED

MD_TCS230 CS(S2_OUT, S3_OUT, OE_OUT);

// Global variables
uint8_t modeOp = 0; // mode of operation
uint8_t ctIndex;
colorData rgb;

void setup()
{
Serial.begin(9600);
Serial.print(F("\n[TCS230 Calibrator Example]"));

// input mode of operation
while (modeOp == 0)
{
Serial.print(F("\nOperate in Learn or Match mode?"));
modeOp = getChar();
if (modeOp != LEARN_MODE && modeOp != MATCH_MODE)
modeOp = 0;
else
clearInput();
}

// initialise color sensor
CS.begin();
if (modeOp == MATCH_MODE) // use calibration parameters from the header file
{
CS.setDarkCal(&sdBlack);
CS.setWhiteCal(&sdWhite);
}
}

char getChar()
// blocking wait for an input character from the input stream
{
while (Serial.available() == 0)
;
return(toupper(Serial.read()));
}

void clearInput()
// clear out serial input
{
while (Serial.read() != -1)
;
}

char *readASCII(uint8_t size)
// read up to size-1 characters from the serial input
// this is quick and dirty code
{
#define BUF_SIZE 12
static char s[BUF_SIZE];
uint8_t i = 0;
char c;

s[0] = '\0';
size--;
while ((i < size) && (size < BUF_SIZE-1))
{
c = getChar();
if (c == '\n')
break;
s[i++] = c;
s = '\0';
}

clearInput();

return(s);
#undef BUF_SIZE
}

void outputHeader(void)
// wite out the new header file with sensor values included
{
Serial.print(F("\n// Header file for the ColorMatch application"));
Serial.print(F("\n// This file is generated by the ColorMatch Application in Learn Mode"));

Serial.print(F("\n\n// Calibration data"));
Serial.print(F("\nsensorData sdBlack = { "));
Serial.print(sdBlack.value[0]); Serial.print(F(", "));
Serial.print(sdBlack.value[1]); Serial.print(F(", "));
Serial.print(sdBlack.value[2]); Serial.print(F(" };"));

Serial.print(F("\nsensorData sdWhite = { "));
Serial.print(sdWhite.value[0]); Serial.print(F(", "));
Serial.print(sdWhite.value[1]); Serial.print(F(", "));
Serial.print(sdWhite.value[2]); Serial.print(F(" };"));

Serial.print(F("\n\n// Color Table for matching"));
Serial.print(F("\ntypedef struct\n{\n char name[9]; // color name 8+nul\n colorData rgb; // RGB value\n} colorTable;"));

Serial.print(F("\n\ncolorTable ct[] = \n{"));
for (uint8_t i=0; i<ARRAY_SIZE(ct); i++)
{
Serial.print(F("\n {\""));
Serial.print(ct.name);
Serial.print(F("\", {"));
Serial.print(ct.rgb.value[0]);
Serial.print(F(", "));
Serial.print(ct.rgb.value[1]);
Serial.print(F(", "));
Serial.print(ct.rgb.value[2]);
Serial.print(F("} },"));
}
Serial.print(F("\n};\n"));
}

uint8_t fsmReadValue(uint8_t state, uint8_t valType)
// Finite State Machine for reading a value from the sensor
// Current FSM state is passed in and returned
// Type of value being read is passed in
// Current reading stored in a global rgb buffer
{
static uint8_t selChannel;
static uint8_t readCount;
static sensorData sd;

switch(state)
{
case 0: // Prompt for the user to start
Serial.print(F("\n\nReading value for "));
switch(valType)
{
case BLACK_CAL: Serial.print(F("BLACK calibration")); break;
case WHITE_CAL: Serial.print(F("WHITE calibration")); break;
case READ_VAL: Serial.print(F("color MATCH")); break;
case LEARN_VAL: Serial.print(ct[ctIndex].name); break;
default: Serial.print(F("??")); break;
}

clearInput();

if (valType == LEARN_VAL)
{
char *p;

Serial.print(F("\nNew name (<enter> for old) to start: "));
p = readASCII(ARRAY_SIZE(ct[0].name));
if (*p != '\0')
strcpy(ct[ctIndex].name, p);
Serial.print(ct[ctIndex].name);
}
else
{
Serial.print(F("\nPress any key to start ..."));
getChar();
clearInput();
}
state++;
break;

case 1: // start the reading process
CS.read();
state++;
break;

case 2: // wait for a read to complete
if (CS.available())
{
switch(valType)
{
case BLACK_CAL:
CS.getRaw(&sdBlack);
CS.setDarkCal(&sdBlack);
break;

case WHITE_CAL:
CS.getRaw(&sdWhite);
CS.setWhiteCal(&sdWhite);
break;

case READ_VAL:
case LEARN_VAL:
CS.getRGB(&rgb);
Serial.print(F("\nRGB is ["));
Serial.print(rgb.value[TCS230_RGB_R]);
Serial.print(F(","));
Serial.print(rgb.value[TCS230_RGB_G]);
Serial.print(F(","));
Serial.print(rgb.value[TCS230_RGB_B]);
Serial.print(F("]"));
break;
}
state++;
}
break;

default: // reset fsm
state = 0;
break;
}

return(state);
}

uint8_t colorMatch(colorData *rgb)
// Root mean square distance between the color and colors in the table.
// FOr a limited range of colors this method works ok using RGB
// We don't work out the square root or the mean as it has no effect on the
// comparison for minimum. Square of the distance is used to ensure that
// negative distances do not subtract from the total.
{
int32_t d;
uint32_t v, minV = 999999L;
uint8_t minI;

for (uint8_t i=0; i<ARRAY_SIZE(ct); i++)
{
v = 0;
for (uint8_t j=0; j<RGB_SIZE; j++)
{
d = ct.rgb.value[j] - rgb->value[j];
v += (d * d);
}
if (v < minV) // new best
{
minV = v;
minI = i;
}
if (v == 0) // perfect match, no need to search more
break;
}

return(minI);
}

void loop()
{
static uint8_t runState = 0;
static uint8_t readState = 0;

if (modeOp == LEARN_MODE) // Learning mode
{
switch(runState)
{
case 0: // calibrate black
readState = fsmReadValue(readState, BLACK_CAL);
if (readState == 0) runState++;
break;

case 1: // calibrate white
readState = fsmReadValue(readState, WHITE_CAL);
if (readState == 0) runState++;
break;

case 2: // prep for learning mode
Serial.println(F("\n\nFor each color, enter name and sense color"));
ctIndex = 0;
runState++;
break;

case 3: // learn color values
readState = fsmReadValue(readState, LEARN_VAL);
if (readState == 0)
{
for (uint8_t j=0; j<RGB_SIZE; j++)
{
ct[ctIndex].rgb.value[j] = rgb.value[j];
}
ctIndex++;
if (ctIndex >= ARRAY_SIZE(ct)) runState++;
}
break;

case 4: // output the text data
outputHeader();
runState++;
break;

default:
runState = 0; // start again if we get here as something is wrong
}
}
else // Matching mode
{
switch(runState)
{
case 0: // read a value
readState = fsmReadValue(readState, READ_VAL);
if (readState == 0) runState++;
break;

case 1: // find the matching color
{
uint8_t i = colorMatch(&rgb);

Serial.print(F("\nClosest color is "));
Serial.print(ct.name);
runState++;
}
break;

default:
runState = 0; // start again if we get here as something is wrong
}
}
}

КАЛИБРОВКА ЦВЕТА КО ВТОРОМУ СКЕТЧУ:

// Header file for the ColorMatch application
// This file is generated by the ColorMatch Application in Learn Mode

// Calibration data
sensorData sdBlack = { 7770, 6720, 8840 };
sensorData sdWhite = { 54390, 51740, 69490 };

// Color Table for matching
typedef struct
{
char name[9]; // color name 8+nul
colorData rgb; // RGB value
} colorTable;

colorTable ct[] =
{
{"WHITE", {255, 255, 255} },
{"BLACK", {0, 0, 0} },
{"YELLOW", {255, 255, 80} },
{"ORANGE", {46, 8, 3} },
{"RED", {255, 177, 255} },
{"GREEN", {17, 26, 7} },
{"BLUE", {125, 255, 255} },
{"BROWN", {8, 0, 0} },
};
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1018
Зарегистрирован: 22 окт 2010, 23:57

Re: Помогите с кодом для Сенсора цвета

Сообщение Mr.Kubikus »

Привет! Сейчас попробуем разобраться с этим кодом.
С уважением, Григорий
GitHub FB ВК
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1018
Зарегистрирован: 22 окт 2010, 23:57

Re: Помогите с кодом для Сенсора цвета

Сообщение Mr.Kubikus »

Скажите, а управлять светодиодной лентой без датчика цвета вы уже научились? Например, по очереди мигать всеми цветами.
С уважением, Григорий
GitHub FB ВК
Лиза
Сообщения: 2
Зарегистрирован: 19 фев 2014, 11:06

Re: Помогите с кодом для Сенсора цвета

Сообщение Лиза »

Ленту мы пока не подключали, экспериментируем просто с 2-мя ардуино, 4-6 LEDами, горящих одним цветом, и одним RGB. Группку LEDов, поключенных к одному ардуино, подносим к сенсору, который, как и RGB, подключен ко второму ардуино. RGB, в идеале, после распознавания сенсором цвета с наших LEDов, должен загореться нужным нам оттенком. Сегодня в течении дня, наши поиски кода зарулили вот сюда (в итоге RGB хаотично мигает):

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;
int redPin = 11;
int greenPin = 10;
int bluePin = 9;
void setup()
{
Serial.begin(115200);
pinMode(s0,OUTPUT);
pinMode(s1,OUTPUT);
pinMode(s2,OUTPUT);
pinMode(s3,OUTPUT);
pinMode(redPin,OUTPUT);
pinMode(greenPin,OUTPUT);
pinMode(bluePin,OUTPUT);

}
void TCS()
{
flag=0;
digitalWrite(s1,HIGH);
digitalWrite(s0,HIGH);
digitalWrite(s2,LOW);
digitalWrite(s3,LOW);
attachInterrupt(0, ISR_INTO, LOW);
timer0_init();

}
void ISR_INTO()
{
counter++;
}
void timer0_init(void)
{
TCCR2A=0x00;
TCCR2B=0x07; //the clock frequency source 1024 points
TCNT2= 1000; //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("red=");
Serial.println(countR,DEC);
digitalWrite(s2,HIGH);
digitalWrite(s3,HIGH);
setColor(255,125,0);
}
else if(flag==2)
{
countG=counter;
Serial.print("green=");
Serial.println(countG,DEC);
digitalWrite(s2,LOW);
digitalWrite(s3,HIGH);
setColor(255,255,0);
}
else if(flag==3)
{
countB=counter;
Serial.print("blue=");
Serial.println(countB,DEC);
Serial.println("\n");
digitalWrite(s2,LOW);
digitalWrite(s3,LOW);
setColor(0,255,255);

}
else if(flag==4)
{
flag=0;
}
counter=0;
}
void loop()
{
TCS();
while(1);


}
void setColor(int red, int green, int blue)
{
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}


Вот как-то так пока)...
Ответить