Trabalho Pratico 2
Objetivo
- Maior Familiarização com a HandyBoard e com o ambiente de programção IC.
- Adquirir noções sobre o funcionamento de sensores e a melhor utilização destes com a HandyBoard.
- Noções basicas sobre processamento dos sinais adquiridos atraves dos sensores.
Montagem do robô
As unicas modificações no robô foram as intalações dos sensores e a adição de um pequeno compartimento para a realização da identificação dos blocos, cujo objetivo é manter as condições de luminosidade constanstes.
Dificuldades encontradas
- Lidar com os sensores
Os sensores se mostraram um pouco ineficientes quando a superficie do objeto a ser identificado nao era liso (exemplo:Blocos fornecidos, eram muito porosos o que dificulta a reflexão da luz proveniente do emissor). Tambem apresentaram resultados ruins quando havia muito reflexão na superfie (exemplo: plista sobre a qual foi montada a trajetoria com a linha preta quando esta estava sujeita a forte iluminação artificial).
- Resolução dos problemas
A solução é tratar os sinais dos sensores por meio de algoritimos adequados a cada aplicação.
Resultados Obtidos dos testes
Apos a realização dos testes propostos obtivemos os seguintes resultados:
Iluminação constante, distância 3mm
Sem Iluminação constante, distância 3mm
Podemos observar que a variação da luminosidade causou tambem uma flutuação do sinal em torno da média e um deslocamento para baixo da média.
Curva Sinal x Distância
O comportamento é não linear, mas para distâncias menores que 10mm e maiores que 3mm podemos fazer uma aproximação linear razuavel.
Fizemos entao uma regressão de quarta ordem que abrange os 4 pontos.
Efeito dos motores na leitura do sensor
Validação
Para distâncias diferentes das anteriores obtivemos 4 medidas e 4 valores calculados apartir da equação da regressão de 4 ordem mostrada em figura anterior e os respectivos erros:
* Para Dist = 4,5mm
Medido = 11 Calculado = -7,48 Erro = 18,48
* Para Dist = 7,5mm
Medido = 92,98 Calculado = 69,94 Erro = 23,04
* Para Dist = 10,5mm
Medido = 171,84 Calculado = 162,65 Erro = 9,19
* Para Dist = 13,5mm
Medido = 212,92 Calculado = 206,49 Erro = 6,43
Influência da superfície na identificação dos blocos
Vemos pelo gráfico que a melhor distancia é 3mm, pois propicia a maior distancia entre os sinais. Além disso vimos que penas variações na distancia podem provocar troca entre as cores. O algoritimo que utilizamos é baseado na media do sinal obtido atraves do sensor.
LISTA DE EXERCICIOS
Normalização:
1-Para os valores medidos do sensor temos:
Máximo de Luz Refletida = 6 Mínimo de Luz Refletida = 252
/*normal.c*/ int normalize (int light) { int MAX_LIGHT = 6; int MIN_LIGHT = 252;
int output = 100 - ( (light – MAX_LIGHT)*100 / (MIN_LIGHT – MAX_LIGHT) );
if (output < 0) output = 0; if (output > 100) output = 100;
return output; }
2-Utilizando a função normalize para o sensor fotoelétrico QRB1113 obtivemos os valores esperado, uma vez que foram normalizados. A faixa de valores que a função retorna é de zero a cem.
3-Quando o sensor estiver em contato com uma superfície mais refletora do que a utilizada na calibração (superfícies brancas) ou quando a superfície for menos refletora que a utilizada na calibração (superfícies pretas) o valor encontrado estará fora do range; ou seja, MAX_LITHG > valor medido ou MIN_LIGHT < valor medido.
Valores Históricos:
1-Para um array de 50 posições e uma frequência de aquisição de dados de 7,8125Hz temos:
Tempo = 50/7,8125 e Tempo = 6,4 segundos
3-/* stuck.c*/
void STUCKROBOT() { int valores[50]; int i = 0; float x; while(1)
{
If(i!=0)
{
x = analog(2);
if( x != valores( i – 1 ) ) { i = 0; }
valores( i ) = x;
if( i == 49) { printf(“stucked”); }
}
else{ valores( i ) = analog(2); }
i++;
sleep(0.1);
}
}
O programa compara o valor lido com o último valor do buffer, caso seja igual armazena na posição corrente do buffer, caso seja diferente armazena na primeira posição do buffer. Se o buffer encher indica que todos os valores são iguais e que o robô está parado.
Codigo Fonte
funcoes.ic
/*Variavel global*/ int vetCont; int vetCont2;
/* * * Funcionalidades * * */
int calibraCor(int cor) {
float media, desvio; calculaDados(); media = calculaMedia(); MEDIA_COR[cor] = media; return 1;
}
int calibraPretoBranco() {
float sensorLocomocao[2][2];
printf("Calibrar preto nos sensores.\n");
while(!start_button());
while(start_button());
calculaDadosPretoBranco(PRETO, sensorLocomocao);
printf("Calibrar branco nos sensores.\n");
while(!start_button());
while(start_button());
calculaDadosPretoBranco(BRANCO, sensorLocomocao);
calculaMediaPretoBranco(sensorLocomocao);
FUNCAO_ATIVA = 0;
}
int identificaCor() {
int melhor_cont, i;
float media, melhor, temp;
calculaDados();
media = calculaMedia();
melhor = 256.0;
for(i = 0; i < 4; i++)
{
temp = (media - MEDIA_COR[i]);
if(temp < 0.0) {
temp = temp*-1.0;
}
if (temp < melhor)
{
melhor = temp;
melhor_cont = i;
}
}
if (melhor_cont == VERDE)
printf("Verde.\n");
else if (melhor_cont == VERMELHO)
printf("Vermelho.\n");
else if (melhor_cont == AZUL)
printf("Azul.\n");
else if (melhor_cont == AMARELO)
printf("Amarelo.\n");
sleep(5.0);
beep();
return 1;
}
/* * * Locomocao * * */
int locomocao() {
int tarefa_caminhar; int tarefa_matar; FUNCAO_ATIVA = 1; andarReto(); tarefa_caminhar = start_process(caminhar()); tarefa_matar = start_process(parar()); while(FUNCAO_ATIVA); kill_process(tarefa_caminhar); kill_process(tarefa_matar); ao(); return 1;
}
void caminhar() {
while(1) {
//Se sensor esquerdo entrar numa faixa branca vira pra esquerda
if(((float)analog(PORTA_SENSOR_ESQ)) < MEDIA_PRETO_BRANCO[SENSOR_ESQ] &&
((float)analog(PORTA_SENSOR_DIR)) < MEDIA_PRETO_BRANCO[SENSOR_DIR]) {
virarEsquerda();
}
//Se sensor direito entrar numa faixa preto vira pra direita
if(((float)analog(PORTA_SENSOR_DIR)) > MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
((float)analog(PORTA_SENSOR_ESQ)) > MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
virarDireita();
}
//Se sensor direito entrar numa faixa preto vira pra direita
/*if(((float)analog(PORTA_SENSOR_DIR)) > MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
((float)analog(PORTA_SENSOR_ESQ)) < MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
virarDireita();
}*/
//Se sensor direito entrar numa faixa preto vira pra direita
if(((float)analog(PORTA_SENSOR_DIR)) < MEDIA_PRETO_BRANCO[SENSOR_DIR] &&
((float)analog(PORTA_SENSOR_ESQ)) > MEDIA_PRETO_BRANCO[SENSOR_ESQ]) {
andarReto();
}
}
}
void virarEsquerda() {
motor(MOTOR_ESQ, (int)(-1*POTENCIA_MOTOR_ESQ)); motor(MOTOR_DIR, POTENCIA_MOTOR_DIR);
}
void virarDireita() {
motor(MOTOR_ESQ, POTENCIA_MOTOR_ESQ); motor(MOTOR_DIR, (int)(-1*POTENCIA_MOTOR_DIR));
}
void andarReto() {
motor(MOTOR_ESQ, POTENCIA_MOTOR_ESQ); motor(MOTOR_DIR, POTENCIA_MOTOR_DIR);
}
/* * * * Funcoes auxiliares * */
float calculaMedia() {
int i;
int m = 0;
for(i = 0; i < vetCont; i++) {
m += VET_DADOS[i];
}
return ((float) m / (float) vetCont);
}
float calculaMediaPretoBranco(float sensorLocomocao[][]) {
MEDIA_PRETO_BRANCO[SENSOR_ESQ] = (sensorLocomocao[SENSOR_ESQ][PRETO] + sensorLocomocao[SENSOR_ESQ][BRANCO])/2.0; MEDIA_PRETO_BRANCO[SENSOR_DIR] = (sensorLocomocao[SENSOR_DIR][PRETO] + sensorLocomocao[SENSOR_DIR][BRANCO])/2.0;
}
int calculaDados() {
int tarefa_dados; tarefa_dados = start_process(adquirirDadosCor()); sleep(5.0); beep(); kill_process(tarefa_dados); return 1;
}
void adquirirDadosCor() {
vetCont = 0;
printf("Aguarde...\n");
while(1)
{
VET_DADOS[vetCont++] = analog(PORTA_SENSOR_COR);
sleep(0.1);
}
}
void calculaDadosPretoBranco(int cor, float sensorLocomocao[][]) {
int i;
int m = 0;
int tarefa_dados;
tarefa_dados = start_process(adquirirDadosPretoBranco());
sleep(5.0);
beep();
kill_process(tarefa_dados);
m = 0;
for(i = 0; i < vetCont; i++) {
m += VET_DADOS[i];
}
sensorLocomocao[SENSOR_ESQ][cor] = ((float) m / (float) vetCont);
m = 0;
for(i = 0; i < vetCont2; i++) {
m += VET_DADOS2[i];
}
sensorLocomocao[SENSOR_DIR][cor] = ((float) m / (float) vetCont2);
}
void adquirirDadosPretoBranco() {
vetCont = 0;
vetCont2 = 0;
printf("Aguarde...\n");
while(1)
{
VET_DADOS[vetCont++] = analog(PORTA_SENSOR_ESQ);
VET_DADOS2[vetCont2++] = analog(PORTA_SENSOR_DIR);
sleep(0.1);
}
}
void parar() {
while(!stop_button()); while(stop_button()); FUNCAO_ATIVA = 0;
}
menu.ic
#define MOTOR_ESQ 1 #define MOTOR_DIR 3 #define TEMPO_30_CM 2.0 #define TEMPO_90_GRAUS 1.15 #define VERDE 0 #define VERMELHO 1 #define AZUL 2 #define AMARELO 3 #define PRETO 0 #define BRANCO 1 #define PORTA_SENSOR_COR 4 #define PORTA_SENSOR_ESQ 2 #define PORTA_SENSOR_DIR 6 #define SENSOR_ESQ 0 #define SENSOR_DIR 1
/*Variavel global responsavel pelo armazenamento da potencia dos motores*/
int POTENCIA_MOTOR_ESQ, POTENCIA_MOTOR_DIR; int FUNCAO_ATIVA; int VET_DADOS[100]; int VET_DADOS2[100]; float MEDIA_COR[4]; float MEDIA_PRETO_BRANCO[2];
void menu() { char menuPrincipal[5][30] = {“1- Seguir linha preta”, “2- Identificar blocos”, “3- Calibrar cores”, “4- Calibrar preto e branco”, “5- Pegar Dados”};
int item, contador, retorno = 1;
POTENCIA_MOTOR_ESQ = 50;
POTENCIA_MOTOR_DIR = 50;
while(1) {
#ifdef DEBUG
printf("Opcao escolhida: %d\n", contador);
#endif
if(start_button()) { //Caso alguma opcao tenha sido marcada
while(start_button()); //Aguarda que tire-se o dedo do butao start
if (contador == 1) {
retorno = locomocao();
} else if (contador == 2) {
retorno = identificaCor();
} else if (contador == 3) {
retorno = menuCalibracaoCor();
} else if (contador == 4) {
retorno = menuCalibracaoPretoBranco();
} else if (contador == 5) {
retorno = calculaDados();
}
} else {
if(retorno == 1) {
imprimeMenu2(&contador, 4, menuPrincipal);
retorno = 0;
} else {
imprimeMenu(&contador, 4, menuPrincipal);
}
}
}
}
int menuCalibracaoCor() {
int item;
int retorno;
char menu[4][20] = {"1- Verde", "2- Vermelho", "3- Azul", "4- Amarelo"};
while(1) {
#ifdef DEBUG
printf("loop motoresMenu\n");
#endif
if(stop_button()) {
while(stop_button());
return 1;
} else if(start_button()) {
while(start_button());
retorno = calibraCor(item - 1);
#ifdef DEBUG
printf("Retornou de calibrar angulos\n");
#endif
} else {
if(retorno == 1) {
imprimeMenu2(&item, 4, menu);
retorno = 0;
} else {
imprimeMenu(&item, 4, menu);
}
}
}
}
int menuCalibracaoPretoBranco() {
int tarefa_calibra; int tarefa_matar_calibra; FUNCAO_ATIVA = 1; tarefa_calibra = start_process(calibraPretoBranco()); tarefa_matar_calibra = start_process(parar()); while(FUNCAO_ATIVA); kill_process(tarefa_calibra); kill_process(tarefa_matar_calibra); return 1;
}
/*Funcao chamada para imprimir a opcao do menu possibilitando a livre movimentacao entre as mesmas.*/
void imprimeMenu(int *contador, int tam, char arranjo[][]) {
int resultado, item;
item = (255 / tam) + 1;
resultado = (*contador) * item;
if (knob() > resultado) {
//(*contador)++;
(*contador) = (knob() / item) +1;
printf("%s\n",arranjo[knob() / item]);
//printf("%s\n",arranjo[((*contador)-1) % tam]);
} else if (knob() < ((*contador)-1) * item) {
(*contador) = (knob() / item) +1;
printf("%s\n",arranjo[knob() / item]);
// (*contador)--;
// printf("%s\n",arranjo[((*contador)-1) % tam]);
}
}
void imprimeMenu2(int *contador, int tam, char arranjo[][]) {
int item;
item = (255/tam) + 1;
printf("%s\n",arranjo[knob() / item]);
(*contador) = (knob() / item) +1;
}
main.ic
main apenas chama a função menu





