A ideia é de um robô que estabeleça uma relação com o ambiente e com as pessoas mostrando que ele consegue extrair desse contexto uma experiência sensorial e a partir disso gerar uma resposta visual. Na prática, o robô tem quatro áreas luminosas na sua estrutura de cérebro, cada área corresponde a um sentido diferente (no caso: visão, audição, tato e olfato). A partir do momento que cada sentido é estimulado, uma luz uniforme ou dispersada acende na região correspondente (cada uma com sua respectiva cor). Quão maior a intensidade do estímulo, mais luminosa será a resposta.
PROJETO ORIGINAL -
Requisitos funcionais:
- Sensor de proximidade: Corresponde ao sentido do tato. Serão dois sensores de ultrassom.
- Sensor de intensidade luminosa: Corresponde ao sentido da visão. Serão vários LDRs (resistor que depende de luz, funcionando também como um sensor).
- Sensor de frequência sonora: Corresponde ao sentido da audição. Falta definir como será exatamente.
- Sensor de gás analógico: Corresponde ao sentido do olfato. Será um único sensor de gás.
- LEDs: Serão LEDs RGB, cada cor correspondendo a um sentido.
Requisitos não funcionais:
- Estrutura interna: provavelmente produzida em náilon ou acrílico, servirá de apoio aos sensores e LEDs.
- Estrutura externa: servirá de revestimento protetor do robô e definirá o formato de cérebro planejado. Os possíveis matérias para a estrutura externa ainda serão testados.
Processamento:
Conteúdo criado na rede antiga por Alexandre Andrade, Raquel Pontes, Victor Uchôa, Lucas Sampaio e Juan Henrique.
"DIÁRIO DE BORDO" -
03 de Outubro de 2012
VISÃO
Na parte da visão nós testamos o LDR em função do fade, neste caso quanto mais luz captada, maior o brilho. Nós programamos de forma que, dos cinco utilizados, apenas o LDR que captasse a maior luminosidade controlasse o fade do LED.
Código Utilizado
// Iniciamos declarando as variáveis do código
int ldr0=A0, ldr1=A1, ldr2=A2, ldr3=A3, ldr4=A4, ldrVal;
int LDRled = 11;
void setup(){
// Em setup declaramos que o LDRled é OUTPUT, o arduino está enviando o sinal a ele, Serial.begin inicia a comunicação do sensor com arduino
Serial.begin(9600);
pinMode(LDRled, OUTPUT);
}
void loop(){
// A função Serial.print vai imprimir os valores dos LDRs
Serial.println(analogRead(ldr0));
Serial.println(analogRead(ldr1));
Serial.println(analogRead(ldr2));
Serial.println(analogRead(ldr3));
Serial.println(analogRead(ldr4));
// A função max compara dois valores e retorna apenas o maior, desta forma apenas o maior LDR vai controlar o fade do LED
ldrVal = max(analogRead(ldr0), analogRead(ldr1));
ldrVal = max(ldrVal, analogRead(ldr2));
ldrVal = max(ldrVal, analogRead(ldr3));
ldrVal = max(ldrVal, analogRead(ldr4));
Serial.println(ldrVal);
// Em constrain reestabelecemos o valor mínimo e máximo de LdrVAL, agora é de 200 a 900
ldrVal = constrain(ldrVal, 200, 900);
// Map cria uma proporção entre os limites iniciais(200, 900) e os limites futuros(0, 255), logo o resultado desta função será um valor entre 0 e 255 em relação aos limites iniciais 200 e 900.
ldrVal = map (ldrVal, 200, 900, 0, 255);
// Escreve o valor de ldrVal em LDRled e imprime na tela
analogWrite(LDRled, ldrVal);
Serial.print(ldrVal);
Serial.println("modified");
analogWrite(LDRled, ldrVal);
delay(100);
}
TATO
Na parte do tato realizamos o fade em função do sensor ultrassom. Neste caso, quanto menor a distância medida (maior a proximidade), maior o brilho. Utilizamos dois ultrassons e um LED, o fade foi controlado a partir de uma média aritmética entre os valores captados pelos dois sensores. Na programação criamos uma relação inversamente proporcional entre a distância e a luminosidade.
Código Utilizado
//Iniciamos declarando as variáveis do programa int ledultra = 9;
const int ultra1 = 7, ultra2 = 8;
void setup() {
// Serial.begin inicia a comunicação do sensor com o arduino e em pinMode declaramos que ledultra é OUTPUT, ele irá receber informação do arduino
Serial.begin(9600);
pinMode(ledultra, OUTPUT);
}
void loop(){
long duration1, duration2, media, cm;
//Calcula a distância captada de ultra1
pinMode(ultra1, OUTPUT);
digitalWrite(ultra1, LOW);
delayMicroseconds(2);
digitalWrite(ultra1, HIGH);
delayMicroseconds(5);
digitalWrite(ultra1, LOW);
pinMode(ultra1, INPUT);
duration1 = pulseIn(ultra1, HIGH);
// Calcula a distância captada de ultra2
pinMode(ultra2, OUTPUT);
digitalWrite(ultra2, LOW);
delayMicroseconds(2);
digitalWrite(ultra2, HIGH);
delayMicroseconds(5);
digitalWrite(ultra2, LOW);
pinMode(ultra2, INPUT);
duration2 = pulseIn(ultra2, HIGH);
// Declara o valor de media
media = (duration1+duration2)/2;
cm = microsecondsToCentimeters(media); // Converte tempo em distância
Serial.print(cm); // Imprime o valor de cm
Serial.print("cm");
Serial.println();
cm = constrain(cm, 0, 200);
// Em constrain restabelecemos os limites de cm agora de 0 a 200
cm = map(cm, 0, 200, 255, 0);
//Em map criamos uma proporção entres os limites iniciais de cm(0, 200) e os novos limites(255, 0)
// Isto é feito em função do fade do LED que varia entre 0 e 255 desta forma quando um objeto estiver a dois metros do ultrassom o LED se manterá apagado, e quando a distância entre um objeto e o ultrassomfor de 0 cm o LED brilhará o máximo.
analogWrite(ledultra, cm);
Serial.print(cm);
Serial.print("modified");
Serial.println();
delay(100); // Imprime os valores calculados em cm
}
long microsecondsToCentimeters(long microseconds) // 29 microssegundos equivale a 1 cm, dividindo o valor captado pelo ultrassom por 29 estaremos convertendo em centímetros
{
return microseconds / 29 / 2; //dividimos por 2 porque queremos apenas a distância captada pelo sensor
}
10 de Outubro de 2012
CÓDIGOS : síntese
Para aprimorar o Cérebro, nós buscamos juntar os códigos (que acabou não sendo possível) e testar os LDRs, ligados apenas na fonte. Ao final do projeto, pretendemos que o arduino sirva somente de receptor/transmissor de informações.
Durante o processo houveram poucos problemas e foram apenas de mal contato.
Para ligar todos os LDRs e transmitir o sinal ao LEDs, decidimos usar o comando max, que consiste em pegar o maior valor entre dois números. Como foram utilizados 5 LDRs, fizemos em forma de série, Ex: max entre LDR1/ LDR2 = valor1; max entre valor1/LDR3 = valor2; etc.
Para os ultrassons foi usada a média, que nada mais é que somar o valor de ULTRA1 com o de ULTRA2 e dividir por 2.
Por falta de material para começar a usar o microfone, apenas melhoramos o que foi feito no encontro anterior.
24 de Outubro de 2012
AUDIÇÃO
Nesse encontro finalmente passamos à audição. Tivemos diversos problemas nessa etapa. Primeiramente, para conectar o sensor [modelo SEN12945P] precisamos soldar fios às suas saídas a fim de ligá-lo ao arduino.
O sensor tem 4 pinos: Ground, Vcc, Signal e NC.
Os dois primeiros são para alimentação enquanto que o signal serve para mandar o sinal ao controlador, porém não identificamos a função do NC.
Em seguida, problemas de circuito e mal contato na protoboard, solucionados com alguns testes. Por fim, uma má regulação do sensor e uma sala bastante ruidosa atrapalharam testar definitivamente a programação e o fading do LED.
31 de Outubro de 2012
AUDIÇÃO
Continuamos trabalhando no microfone. Dessa vez conseguimos escrever um programa que controlasse o brilho do LED a partir da leitura do sensor. Contudo esbarramos em dois problemas:
-
Ao emitir um som de intensidade constante, o LED deveria se manter aceso. O que realmente aconteceu era um piscar aleatório. Quando observamos os valores lidos pelo sensor no serial monitor, vimos que mesmo com um som constante, alguns zeros (aparentemente sem padrão) surgiam. Nossa solução foi eliminar esses zeros na programação, impedindo que eles fossem passados para o LED. Não funcionou totalmente, entretanto o LED passou a piscar menos.
Código Utilizado
//Iniciamos declarando as variáveis do programa const int ledPin = 11;
int quantz=0, limitez=5;
void setup() { // Serial.begin inicia a comunicação do sensor com o arduino e em pinMode declaramos que ledPin é OUTPUT, ele irá receber informação do arduino
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
int sensorValue = analogRead(A0);
//A leitura do Sensor é feita.
Serial.println(sensorValue);
//Para efeito de controle, o valor lido é impresso no serial monitor.
sensorValue = constrain(sensorValue, 350, 700);
//A função constrain modifica os limites dos valores lidos. Todos os valores abaixo de 350 viram 350 e os acima de 700 viram 700.
sensorValue = map(sensorValue, 350, 700, 0, 255);
//A função map modifica proporcionalmente o intervalo de 350 a 700 para 0 a 255, para imprimir os valores no LED.
Serial.print(sensorValue);
Serial.println("mod");
if(sensorValue > 0) {
//Essa condicional impede que os zeros aleatórios passem pro LED, eliminando parte das piscadas do LED.
analogWrite(ledPin, sensorValue);
quantz=0;
} else {
quantz++;
//Essa variável vai armazenando quantos zeros seguidos aparecem
}
if(quantz>=limitez) {
//Se o número de zeros seguidos supera 5, o LED é apagado. Sem essa condicional o LED não apagaria quando houvesse silêncio, já que todos os zeros seriam eliminados.
quantz = 0;
analogWrite(ledPin, 0);
}
}
- O segundo problema está relacionado ao efeito fading. Nos sensores relativos à visão e tato, conseguimos um fading bem interessante, porém com o microfone esse efeito não funcionou tão bem. É notável que o LED brilha de acordo com sons mais fortes ou mais fracos, mas a transição de uma intensidade de brilho para outra é tão rápida que não obtivemos o efeito que queríamos. Portanto, no próximo encontro tentaremos algumas ideias para melhorar o efeito a partir da programação.
7 e 14 de Novembro de 2012
AUDIÇÃO
Nos dois últimos encontros continuamos trabalhando no microfone. Após testar várias ideias, conseguimos chegar a um código bem simples que conseguisse realizar o fading. Decidimos fazer um código que só fizesse o fading pra apagar os LEDs, ou seja, quando algum som chegar no microfone os LEDs se acenderão de uma vez e apagarão gradualmente. O único problema que o novo código não resolve é o de um som contínuo. Como dito antes, o ideal seria que os LEDs ficassem acesos enquanto algum som contínuo estivesse chegando ao microfone, mas ainda não encontramos uma forma adequada de fazer isso.
Código Utilizado
const int ledMicrofone = 11; //Iniciamos declarando as variáveis do programa
void setup() { // Serial.begin inicia a comunicação do sensor com o arduino e em pinMode declaramos que ledMicrofone é OUTPUT, ele irá receber informaçã do arduino
pinMode(ledMicrofone, OUTPUT);
Serial.begin(9600);
}
void loop() {
int sinalMicrofone;
sinalMicrofone = analogRead(A0);
//A leitura do Sensor é feita.
sinalMicrofone = constrain(sinalMicrofone, 400, 1000);
//A função constrain modifica os limites dos valores lidos. Todos os valores abaixo de 400 viram 400 e os acima de 1000 viram 100.
sinalMicrofone = map(sinalMicrofone, 400, 1000, 0, 255);
//A função map modifica proporcionalmente o intervalo de 400 a 1000 para 0 a 255, para imprimir os valores no LED.
analogWrite(ledMicrofone, sinalMicrofone);
//O Led é aceso de acordo com a intensidade do som que chegou no microfone.
for(int i = 0; i < sinalMicrofone; ++i) {
analogWrite(ledMicrofone, sinalMicrofone-i);
delay(20);
//Esse laço faz com o Led vá apagando gradualmente.
}
}
No próximo encontro vamos começar a pensar em como juntar todos os sentidos em um único código utilizando uma máquina de estados.
ESTRUTURA
Nesses mesmos dois encontros dos dias 7 e 14, parte do grupo começou a planejar o shield para o arduino que conterá todas as saídas de Signal, Vcc e Ground dos sensores e dos quatro drivers de LEDs. Listamos todo o material que será necessário comprar:
- placa de ilha 10cmX10cm dupla face,
- barras de pino fêmea de 3 e 4 entradas,
- mais o material de experimentação do revestimento do robô.
Posteriormente, foi analisado o tamanho adequado da placa, bem como a melhor disposição de todos os componentes, de forma a adequá-los aos "caminhos" na placa e a origem deles na própria estrutura do robô.
O shield já está planejado com um esquema desenhado para nos orientar na hora de montá-lo. *foto: enviar
21 de Novembro de 2012
OLFATO
Nesse encontro as atividades foram realizadas no Museu de Arte Contemporânea de Pernambuco (MAC-PE). Começamos a trabalhar no sentido do olfato com o sensor de gás mas avançamos pouco visto que ainda não entendemos perfeitamente o seu funcionamento.
Código Utilizado
void setup() {
Serial.begin(9600); //inicia a comunicação do sensor com o arduino
}
void loop() {
int val;
val=analogRead(A0);
//Faz a leitura do sensor.
Serial.println(val);
//Imprime no serial monitor o valor lido.
delay(100);
}
28 de Novembro de 2012
Nesse encontro não conseguimos avançar no trabalho com o sensor de gás, devido a falta de um cabo usb para ligar o arduino no computador. Portanto, nos limitamos a discutir possíveis métodos de unir os códigos de todos os sentidos em um único código sem prejudicar o efeito visual do fading.
No próximo encontro esperamos avançar com o trabalho do sensor de gás e também começar a montar o shield que une os sensores e os drivers ao arduino.
05 de Dezembro de 2012
OLFATO
Nesse encontro conseguimos escrever e testar alguns códigos para o sensor de gás. No final, chegamos a um código similar ao do microfone. A única diferença está no tratamento dos valores do leitor, já que quando assopramos no sensor de gás, a leitura é "atrapalhada" fazendo o valor diminuir. Isso só acontece porque nosso modelo de sensor detecta gases do tipo GLP (ou Gases Liquefeitos de Petróleo) e não gás carbônico, o produto de nossa respiração. Tendo em vista isso, quanto menor o valor lido pelo sensor, mais forte a pessoa está soprando e, portanto, maior o brilho dos LEDs.
Código Utilizado
//Iniciamos declarando as variáveis do programa int sensorGas;
int ledGas = 11;
void setup(){ // Serial.begin inicia a comunicação do sensor com o arduino e em pinMode declaramos que ledGas é OUTPUT, receptor de informações
pinMode(ledGas, OUTPUT);
Serial.begin(9600);
}
void loop(){
sensorGas = analogRead(A0);
//A leitura do Sensor é feita.
Serial.println(sensorGas);
sensorGas = constrain(sensorGas, 30, 80);
//A função constrain modifica os limites dos valores lidos. Todos os valores abaixo de 30 viram 30 e os acima de 80 viram 80.
sensorGas = map(sensorGas, 30, 80, 255, 0);
//A função map modifica proporcionalmente o intervalo de 30 a 80 para 255 a 0, para imprimir os valores no LED.
analogWrite(ledGas, sensorGas);
for(int i = 0; i < sensorGas; ++i)
{
analogWrite(ledGas, sensorGas-i);
delay(20);
//Esse laço faz com o Led apague gradualmente.
}
}
ESTRUTURA
Também avançamos na construção do shield e testamos algodão como um possível material para a estrutura externa do cérebro. Considerando que os códigos de todos os sentidos estão prontos, na próxima semana vamos trabalhar na união deles.
12 de Dezembro de 2012
CÓDIGO: problemas
Nesse encontro começamos a juntar os sentidos em um único código e esbarramos em alguns problemas.
Esses problemas estão relacionados ao fato de que faz parte do conceito do cérebro mostrar que os sentidos funcionam simultaneamente independentes. Para obter essa simultaneidade é necessário que o código final seja sequencial, sem delays e loops dentro da função principal.
Daí vem nosso problema: o efeito fading que nós fizemos depende diretamente do uso das funções delay e for. Portanto, na parte da programação, a prioridade é reescrever todos os códigos dos sentidos sem utilizar delay e for.
ESTRUTURA
No âmbito da parte externa, testamos o polímero PU (Poliuretano) como possível material. Esse material tem dezenas de aplicações e é rígido o suficiente para se sustentar, é fácil de moldar e também dispersar a luz da maneira que queríamos.
* Durante o período de 19/Dezembro/2012 a 15/Janeiro/2013 não houve encontros presenciais pois foi o recesso do Projeto Robuca. Desta forma, também não houve avanços físicos na estrutura nem virtuais na programação, somente uma maturação de idéias. *
16, 23 e 30 de Janeiro de 2013
CÓDIGO: solução
Com o prazo apertado pra finalizar o projeto tivemos que encontrar uma solução rápida para os problemas de programação. A melhor encontrada foi escrever dois códigos e consequentemente utilizar dois arduinos. Também foi necessário utilizar quatro LDRs ao invés dos cinco originais. O 1º código une visão/tato e o 2º une audição/olfato.
Código 1
//Iniciamos declarando as variáveis do programa const int ultra = 7;
long duration;
long cm;
const int ledultra= 6;
const int LDRled = 5;
const int ldr0=A0, ldr1=A1, ldr2=A2, ldr3=A3;
int ldrVal;
void setup() { // Serial.begin inicia a comunicação dos sensores com o arduino e em pinMode declaramos que ledGas e LDRled são OUTPUT, receptores de informações
Serial.begin(9600);
pinMode(ledultra, OUTPUT);
pinMode(LDRled, OUTPUT);
}
void loop()
{
duration = funcUltra(duration);
//funcUltra é a função que faz a leitura do ultrassom.
cm = microsecondsToCentimeters(duration);
//O tempo lido no ultrassom é convertido para centímetros.
cm = constrain(cm, 0, 30);
cm = map(cm, 0, 30, 255, 0); //constrain e map modificam os limites dos valores lidos para transmitir os valores aos LEDs. ldrVal = compara();
//compara é a função que lê os LDRs e retorna o maior valor lido.
ldrVal = constrain(ldrVal, 500, 900);
ldrVal = map (ldrVal, 500, 900, 0, 255); //constrain e map modificam os limites dos valores lidos para transmitir os valores aos LEDs.
analogWrite(LDRled, ldrVal);
//O valor modificado dos LDRs é inscrito nos leds da visão.
analogWrite(ledultra, cm);
//O valor modificado do ultrassom é inscrito nos leds do tato.
delay(30);
}
long funcUltra(long duration)
//funcUltra é a função que faz a leitura do ultrassom.
{
pinMode(ultra, OUTPUT);
digitalWrite(ultra, LOW);
delayMicroseconds(2);
digitalWrite(ultra, HIGH);
delayMicroseconds(5);
digitalWrite(ultra, LOW);
pinMode(ultra, INPUT);
duration = pulseIn(ultra, HIGH);
return duration;
}
long microsecondsToCentimeters(long microseconds)
{
return microseconds / 29 / 2;
}
int compara()
//compara é a função que lê os LDRs e retorna o maior valor lido.
{
ldrVal = max(analogRead(ldr0), analogRead(ldr1));
//max retorna o maior entre dois valores.
ldrVal = max(ldrVal, analogRead(ldr2));
ldrVal = max(ldrVal, analogRead(ldr3));
return ldrVal;
}
Código 2
/*
Esse código foi escrito como uma máquina de estadosfinitos.
Nele existem dois estados LEITURA e FADING.
Em LEITURA os valores dos sensores são lidos e modificados.
Em FADING esses valores são inscritos nos leds e um fade out é realizado.
*/
#define LEITURA 0
#define FADING 1
//Iniciamos declarando as variáveis do programa
int sensorGas;
int sinalMicrofone;
int tempoAtual;
int tempoAnterior = 0;
int intervalo = 10;
int i = 0;
int j = 0;
const int ledGas = 9;
const int ledMicrofone = 10;
boolean estado = LEITURA;
void setup() //inicia a comunicação do sensor com o arduino e declaramos que ledGas e ledMicrofone são OUTPUT.
{
pinMode(ledGas, OUTPUT);
pinMode(ledMicrofone, OUTPUT);
Serial.begin(9600);
}
void loop(){
tempoAtual = millis();
if(estado == LEITURA){
sensorGas = analogRead(A4);
//O valor do sensor de gás é lido.
sensorGas = constrain(sensorGas, 30, 50);
sensorGas = map(sensorGas, 30, 50, 255, 0);
//constrain e map modificam os limites dos valores lidos.
analogWrite(ledGas, sensorGas);
//Esse valor é inscrito inicialmente nos leds.
sinalMicrofone = analogRead(A5);
//O valor do microfone é lido.
sinalMicrofone = constrain(sinalMicrofone, 200, 800);
sinalMicrofone = map(sinalMicrofone, 200, 800, 0, 255);
//constrain e map modificam os limites dos valores lidos.
analogWrite(ledMicrofone, sinalMicrofone);
//Esse valor é inscrito inicialmente nos leds.
estado = FADING;
//Fim do estado LEITURA.
}
else if (estado==FADING && (i if(i //Essa estrutura substitui o for e o delay.
{
if(tempoAtual - tempoAnterior > intervalo)
//Esse if substitui a utilização da função delay.
{
analogWrite(ledGas, sensorGas-i);
tempoAnterior = tempoAtual;
++i;
}
}
if(j //Essa estrutura substitui o for e o delay.
{
if(tempoAtual - tempoAnterior > intervalo)
//Esse if substitui a utilização da função delay.
{
analogWrite(ledMicrofone, sinalMicrofone-j);
tempoAnterior = tempoAtual;
++j;
}
}
}
else
{
estado = LEITURA;
i=0;
//Fim do estado FADING.
}
}
ESTRUTURA - interna.
A parte da montagem dos LEDs e sensores na estrutura do robô era a mais atrasada, portanto foi onde concentramos o trabalho.
Novamente por causa do prazo apertado, tivemos que abandonar a montagem do shield, por dificuldade em encontrar os materiais necessários a tempo. Utilizamos em seu lugar uma protoboard.
Para montar a caixa encontramos grandes dificuldades em lidar com a quantidade de fios necessária para ligar os leds em paralelo e os sensores na protoboard. A imagem abaixo é da fase final da montagem e mostra a quantidade de fios utilizada:
Depois de montada a estrutura, fizemos os testes de funcionamento e todos os leds e sensores funcionaram da forma esperada. Nos próximos encontros só precisamos finalizar o robô com a parte externa que vai ser de arame e poliéster.
Ou