BASIC4MCU | 질문게시판 | 아두이노 프로그램 수정 도움 부탁드립니다
페이지 정보
작성자 아야어여 작성일2018-09-27 21:26 조회7,889회 댓글0건본문
여름 때 아두이노 음성 관련해서 질문드렸는데 센서를 하나 추가하는 방식으로 해서 되었습니다.
이것을 가지고 수정해서 또 다른 것을 만들어 보고자 하는데
현재는 시리얼 모니터로 학습모드와 동작모드 선택 후 동작모드 시에는 엔터를 이용해서
음성출력와 색인식이 되었습니다.
그리고 수정하고 싶은 것은 시리얼모니터에서 학습모드와 동작모드 선택 없이 바로 색 인식 후
음성출력을 해주려고 하고 있습니다. 시리얼모니터에서 학습모드와 동작모드 선택없이
바로 들어가는 것 까지는 했는데 색인식이 되질 않습니다.
시리얼모니터를 누르면 바로 음성출력과 색인식이 되는데 색이 맞질 않습니다.
어떻게 해결해야 하나요?
--------------------수정파일-----------------------------------------
#include <MD_TCS230.h>
#include <FreqCount.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.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'
#define S2_OUT 7
#define S3_OUT 6
MD_TCS230 CS(S2_OUT, S3_OUT);
uint8_t modeOp;
uint8_t ctIndex;
colorData rgb;
unsigned long time = 0;
SoftwareSerial mySerial(10, 11);
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
mp3_set_serial (mySerial); //set Serial for DFPlayer-mini mp3 module
delay(1); //wait 1ms for mp3 module to set volume
mp3_set_volume (15);
}
void clearInput()
// 시리얼 포트에 들어온 데이터들을 모두 읽어 없앱니다:
{
while (Serial.read() != -1)
;
}
void outputHeader(void)
// 영점 조정한 값들과 컬러를 RGB로 감지한 값들을 헤더 파일에 사용할 수
// 있게 시리얼 모니터로 출력합니다:
{
Serial.print(("\n// ColorMatch.h 파일에 사용되는 영점 조정과 컬러 값들입니다"));
Serial.print(("\n// 이 파일은 ColorMatch 스케치 학습 모드에서 만들어졌습니다"));
Serial.print(("\n\n// 영점 조정 데이터:"));
Serial.print(("\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(("\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(("\n\n// 색 찾기를 위한 컬러 테이블:"));
Serial.print(("\ntypedef struct\n{\n char name[10]"));
Serial.print(("\n\ncolorTable ct[] = \n{}"));
for (uint8_t i = 0; i < ARRAY_SIZE(ct); i++) {
Serial.print(("\n {\""));
Serial.print(ct[i].name);
Serial.print(("\", {"));
Serial.print(ct[i].rgb.value[0]);
Serial.print((", "));
Serial.print(ct[i].rgb.value[1]);
Serial.print((", "));
Serial.print(ct[i].rgb.value[2]);
Serial.print(("} },"));
}
Serial.print(("\n};\n"));
}
uint8_t fsmReadValue(uint8_t state, uint8_t valType)
{
static uint8_t selChannel;
static uint8_t readCount;
static sensorData sd;
switch (state) {
case 0: // 시작하기 위한 안내문을 보여줍니다:
Serial.print(F("\n\n값을 읽는 중: "));
switch (valType) {
case BLACK_CAL: Serial.print(("검정색 영점 조정")); break;
case WHITE_CAL: Serial.print(("하얀색 영점 조정")); break;
case READ_VAL: Serial.print(("색 맞추기")); break;
case LEARN_VAL: Serial.print(ct[ctIndex].name); break;
default: Serial.print(F("??")); break;
}
clearInput();
if (valType == LEARN_VAL) {
}
else {
Serial.print(("\n시작하려면 어떤 키든 눌러주세요 ..."));
clearInput();
}
state++;
break;
case 1: // 센서 값을 읽기 시작합니다
CS.read();
state++;
break;
case 2: // 값을 읽어 들일 때까지 기다립니다
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(("\nRGB["));
Serial.print(rgb.value[TCS230_RGB_R]);
Serial.print((","));
Serial.print(rgb.value[TCS230_RGB_G]);
Serial.print((","));
Serial.print(rgb.value[TCS230_RGB_B]);
Serial.print(("]"));
break;
}
state++;
}
break;
default: // reset fsm
state = 0;
break;
}
return (state);
}
uint8_t colorMatch(colorData *rgb)
{
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[i].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) { // 학습 모드
switch (runState) {
case 0: // 검정색 영점 조정
readState = fsmReadValue(readState, BLACK_CAL);
if (readState == 0) runState++;
break;
case 1: // 하얀색 영점 조정
readState = fsmReadValue(readState, WHITE_CAL);
if (readState == 0) runState++;
break;
case 2: // 학습 모드를 위한 준비
Serial.println(F("\n\n모든 컬러에 대하여, 이름을 넣고 색을 감지합니다"));
ctIndex = 0;
runState++;
break;
case 3: // 색을 학습합니다. RGB 값을 읽어들여 이를 보관합니다
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: // 헤더 파일로 사용키 위하여 시리얼 모니터로 출력합니다
outputHeader();
runState++;
break;
default:
runState = 0; // 잘못되었다면 다시 시작합니다
}
}
else { // 색 맞추기 모드
switch (runState) {
case 0: // 색의 RGB 값을 읽어들입니다
readState = fsmReadValue(readState, READ_VAL);
if (readState == 0) runState++;
break;
case 1: // 가까운 색을 찾아냅니다:
{
uint8_t i = colorMatch(&rgb);
Serial.print(("\n가장 가까운 색은 "));
Serial.print(ct[i].name);
Serial.print(("입니다"));
if(!strcmp(ct[i].name, "빨간색")){mp3_play (1); delay(100);}
else if(!strcmp(ct[i].name, "주황색")){mp3_play (2);delay(100);}
else if(!strcmp(ct[i].name, "노란색")){mp3_play (3);delay(100);}
else if(!strcmp(ct[i].name, "초록색")){mp3_play (4); delay(100);}
else if(!strcmp(ct[i].name, "파란색")){mp3_play (5);delay(100);}
else if(!strcmp(ct[i].name, "남색")){mp3_play (6);delay(100);}
else if(!strcmp(ct[i].name, "보라색")){mp3_play (7);delay(100);}
else if(!strcmp(ct[i].name, "검정색")){mp3_play (8);delay(100); }
else if(!strcmp(ct[i].name, "하얀색")){mp3_play (9); delay(100);}
else if(!strcmp(ct[i].name, "분홍색")){mp3_play (10); delay(100);}
runState++;
delay(3000);
}
break;
default:
runState = 0; // 잘못되었다면 다시 시작합니다
}
}
}
------------------------------------원본파일---------------------------------------------------
#include <MD_TCS230.h>
#include <FreqCount.h>
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.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'
#define S2_OUT 7
#define S3_OUT 6
MD_TCS230 CS(S2_OUT, S3_OUT);
uint8_t modeOp = 0; // 동작 모드
uint8_t ctIndex;
colorData rgb;
unsigned long time = 0;
SoftwareSerial mySerial(10, 11);
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
// 동작 모드를 선택하기 위하여 입력받기
while (modeOp == 0) {
Serial.println(("학습모드(L) OR 동작모드(M)"));
modeOp = getChar();
if (modeOp != LEARN_MODE && modeOp != MATCH_MODE)
modeOp = 0;
else
clearInput();
}
CS.begin();
if (modeOp == MATCH_MODE) { // 헤더 파일로부터 영점 조정 데이터를 사용합니다
CS.setDarkCal(&sdBlack);
CS.setWhiteCal(&sdWhite);
}
mp3_set_serial (mySerial); //set Serial for DFPlayer-mini mp3 module
delay(1); //wait 1ms for mp3 module to set volume
mp3_set_volume (15);
}
char getChar()
// 소문자가 들어 올 경우 대비
{
while (Serial.available() == 0)
;
return (toupper(Serial.read()));
}
void clearInput()
// 시리얼 포트에 들어온 데이터들을 모두 읽어 없앱니다:
{
while (Serial.read() != -1)
;
}
char *readASCII(uint8_t size)
{
#define BUF_SIZE (9 + 1)
static char s[BUF_SIZE];
uint8_t i = 0;
char c;
s[0] = '\0';
size--;
while ((i < size) && (size < BUF_SIZE)) {
c = getChar();
if (c == '\n')
break;
s[i++] = c;
s[i] = '\0';
}
clearInput();
return (s);
#undef BUF_SIZE
}
void outputHeader(void)
// 영점 조정한 값들과 컬러를 RGB로 감지한 값들을 헤더 파일에 사용할 수
// 있게 시리얼 모니터로 출력합니다:
{
Serial.print(("\n// ColorMatch.h 파일에 사용되는 영점 조정과 컬러 값들입니다"));
Serial.print(("\n// 이 파일은 ColorMatch 스케치 학습 모드에서 만들어졌습니다"));
Serial.print(("\n\n// 영점 조정 데이터:"));
Serial.print(("\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(("\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(("\n\n// 색 찾기를 위한 컬러 테이블:"));
Serial.print(("\ntypedef struct\n{\n char name[10]"));
Serial.print(("\n\ncolorTable ct[] = \n{}"));
for (uint8_t i = 0; i < ARRAY_SIZE(ct); i++) {
Serial.print(("\n {\""));
Serial.print(ct[i].name);
Serial.print(("\", {"));
Serial.print(ct[i].rgb.value[0]);
Serial.print((", "));
Serial.print(ct[i].rgb.value[1]);
Serial.print((", "));
Serial.print(ct[i].rgb.value[2]);
Serial.print(("} },"));
}
Serial.print(("\n};\n"));
}
uint8_t fsmReadValue(uint8_t state, uint8_t valType)
{
static uint8_t selChannel;
static uint8_t readCount;
static sensorData sd;
switch (state) {
case 0: // 시작하기 위한 안내문을 보여줍니다:
Serial.print(F("\n\n값을 읽는 중: "));
switch (valType) {
case BLACK_CAL: Serial.print(("검정색 영점 조정")); break;
case WHITE_CAL: Serial.print(("하얀색 영점 조정")); break;
case READ_VAL: Serial.print(("색 맞추기")); break;
case LEARN_VAL: Serial.print(ct[ctIndex].name); break;
default: Serial.print(F("??")); break;
}
clearInput();
if (valType == LEARN_VAL) {
char *p;
Serial.print(("\n새로운 이름(<엔터>옛 이름 사용) : "));
p = readASCII(ARRAY_SIZE(ct[0].name));
if (*p != '\0')
strcpy(ct[ctIndex].name, p);
Serial.print(ct[ctIndex].name);
}
else {
Serial.print(("\n시작하려면 어떤 키든 눌러주세요 ..."));
getChar();
clearInput();
}
state++;
break;
case 1: // 센서 값을 읽기 시작합니다
CS.read();
state++;
break;
case 2: // 값을 읽어 들일 때까지 기다립니다
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(("\nRGB["));
Serial.print(rgb.value[TCS230_RGB_R]);
Serial.print((","));
Serial.print(rgb.value[TCS230_RGB_G]);
Serial.print((","));
Serial.print(rgb.value[TCS230_RGB_B]);
Serial.print(("]"));
break;
}
state++;
}
break;
default: // reset fsm
state = 0;
break;
}
return (state);
}
uint8_t colorMatch(colorData *rgb)
{
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[i].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) { // 학습 모드
switch (runState) {
case 0: // 검정색 영점 조정
readState = fsmReadValue(readState, BLACK_CAL);
if (readState == 0) runState++;
break;
case 1: // 하얀색 영점 조정
readState = fsmReadValue(readState, WHITE_CAL);
if (readState == 0) runState++;
break;
case 2: // 학습 모드를 위한 준비
Serial.println(F("\n\n모든 컬러에 대하여, 이름을 넣고 색을 감지합니다"));
ctIndex = 0;
runState++;
break;
case 3: // 색을 학습합니다. RGB 값을 읽어들여 이를 보관합니다
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: // 헤더 파일로 사용키 위하여 시리얼 모니터로 출력합니다
outputHeader();
runState++;
break;
default:
runState = 0; // 잘못되었다면 다시 시작합니다
}
}
else { // 색 맞추기 모드
switch (runState) {
case 0: // 색의 RGB 값을 읽어들입니다
readState = fsmReadValue(readState, READ_VAL);
if (readState == 0) runState++;
break;
case 1: // 가까운 색을 찾아냅니다:
{
uint8_t i = colorMatch(&rgb);
Serial.print(("\n가장 가까운 색은 "));
Serial.print(ct[i].name);
Serial.print(("입니다"));
if(!strcmp(ct[i].name, "빨간색")){mp3_play (1); delay(100);}
else if(!strcmp(ct[i].name, "주황색")){mp3_play (2);delay(100);}
else if(!strcmp(ct[i].name, "노란색")){mp3_play (3);delay(100);}
else if(!strcmp(ct[i].name, "초록색")){mp3_play (4); delay(100);}
else if(!strcmp(ct[i].name, "파란색")){mp3_play (5);delay(100);}
else if(!strcmp(ct[i].name, "남색")){mp3_play (6);delay(100);}
else if(!strcmp(ct[i].name, "보라색")){mp3_play (7);delay(100);}
else if(!strcmp(ct[i].name, "검정색")){mp3_play (8);delay(100); }
else if(!strcmp(ct[i].name, "하얀색")){mp3_play (9); delay(100);}
else if(!strcmp(ct[i].name, "분홍색")){mp3_play (10); delay(100);}
runState++;
}
break;
default:
runState = 0; // 잘못되었다면 다시 시작합니다
}
}
}
댓글 0
조회수 7,889등록된 댓글이 없습니다.