LusoRobótica - Robótica em Português

Robótica => Iniciantes => Tópico iniciado por: tiagosilva510 em 29 de Maio de 2011, 12:38

Título: sfr05
Enviado por: tiagosilva510 em 29 de Maio de 2011, 12:38
preciso de ajuda com o sensor sfr05 e o atmega 88

Alguem tem algum tutorial sobre como por a funcionar?
Título: Re: sfr05
Enviado por: maurosmartins em 29 de Maio de 2011, 13:14
Viva Tiago, sobre os SRF05 posso ajudar no atmel nem por isso.

Coloca as tuas questões.

Cumprimentos, Mauro.
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Maio de 2011, 17:21
eu do sfr05 tambem percebo mais oh menos, o pior é mesmo o atmega :P

# Define ENABLE_INT # asm ("SEI")

# Define um TRUE
# Define FALSE 0
# Define PORTBDDR 0d11111110
# Define TRIGGER PORTD.1
# Define PIND.0 ECHO
# Define ILIMITADO 25000
# Define um WAIT_FOR_ECHO
# Define ECHO_MEASURE 2




MS10 int = 0;
mS int = 0;
int seg = 0;

echomeasure int = FALSE;
echotimer int;
distância = int LIMITLESS/29;

//-----
interrupção [TIM0_COMP] timer0_comp_isr (void)
{

if (echomeasure == WAIT_FOR_ECHO)
{
if (ECHO == 1)
{
echotimer = 0;
echomeasure = ECHO_MEASURE;
}
}

if (echomeasure == ECHO_MEASURE)
{
if (ECHO == 0)
{
= distância (* echotimer 100) / 29
echomeasure = FALSE;
}
mais
echotimer + +;
}



if (+ + MS10 == 10)
{
MS10 = 0;

if ((mS% 50) == 0) 
{
TRIGGER = 1;
echotimer = 0;
echomeasure = WAIT_FOR_ECHO;
delay_us (10);
TRIGGER = 0;
}


if (+ + MS == 1000)
{
mS = 0;
s + +;
}
}

}

Penso que seja algo deste genero, mas n tenho a certeza,

Cumprimentos
Título: Re: sfr05
Enviado por: senso em 29 de Maio de 2011, 22:27
Basta usares sei(); para ligar as interrupções, não é preciso andar a inventar com assembly.
Título: Re: sfr05
Enviado por: tiagosilva510 em 05 de Junho de 2011, 23:44
boas amigos,

estou a tentar programar um sfr05, com a ajuda de alguma pesquisa tambem claro, porque ainda estou a dar os primeiros passos :P , enviando os dados para um lcd 16x2

para ja fiz o codigo para o sfr05 mas n sei se estara correcto. gostaria que dessem uma vista de olhos se possivel.. compil direitinho, no entanto n sei como testar no sensor se funciona,
Código: [Seleccione]
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>


#define START_CLK 0x0A // Start clock with 1:8 prescaler CTC mode
#define START_CLK_N 0x02 // Start clock running 1:8 prescaler in normal mode
#define STOP_CLK 0x08 // Stop clock


void startRange(void);
unsigned int getEcho(void);
void setup(void); // General chip setup
void startTimer(unsigned int time); // Starts the timer running for a number of uS defined by value of time
void waitForTimer(void); // Waits for the timer to stop


int main(void)
{
setup();
waitForTimer();

unsigned int range;

while(1)
{
startRange(); // Send a high on the trigger pin to start a ranging
range = getEcho(); // Wait for the echo line to go high and then measure the length of this high

startTimer(0xFFFF); // Delay before taking another ranging
waitForTimer();
}
}

void setup(void)
{
DDRC = 0x01; // Port A pin 0 ouput all others input

TCCR1A = 0x00; // Set timer up in CTC mode
TCCR1B = 0x08;

TWBR = 0x20; // 100MHz I2C clock frequency
}

void startTimer(unsigned int time)
{
OCR1A = time; // Time set to count to
TIFR0 = 0x10; // Clear timer campare match flag
TCNT1 = 0x00; // Clear timer to zero
TCCR1B = START_CLK; // Start timer running 1:8 prescaler
}


void waitForTimer(void)
{
while(!(TIFR0&0x10)); // wait for timer to set compare match flag
TCCR1B = STOP_CLK; // Stop the timer
}

void startRange(void)
{
PORTC = ( 1<<PORTC0 ); // Send trigger pin high
startTimer(0x0001); // Wait around 10uS before sending it low again
waitForTimer();
PORTC = ( 0<<PORTC0 );
}

unsigned int getEcho(void)
{
unsigned int range;
 
while(!(PINC&0x02)); // Wait for echo pin to go high,  this indicates the start of the incoming pulse
TCNT1 = 0x00; // Clear timer to zero
TCCR1B = START_CLK_N; // Start timer running 1:8 prescaler in normal mode
while((PINC&0x02)); // Wait for echo pin to go low signaling that the pulse has ended
TCCR1B = STOP_CLK; // Stop the timer and set back to CTC mode
range = TCNT1/29; // Read back value in the timer counter register, this number divided by 29 will give us the range in CM

return(range);
}

Cumprimentos
Título: Re: sfr05
Enviado por: senso em 05 de Junho de 2011, 23:48
Testar é usar uma fita métrica meter algo a uma distancia conhecida e ver o que o sensor te dá.
Título: Re: sfr05
Enviado por: tiagosilva510 em 06 de Junho de 2011, 10:48
sim, mas este codigo é apenas para o sensor, ainda n fiz pro lcd.. como sei o q da assim?
Título: Re: sfr05
Enviado por: metRo_ em 06 de Junho de 2011, 11:14
sim, mas este codigo é apenas para o sensor, ainda n fiz pro lcd.. como sei o q da assim?

Algo deste género, tinha umas funções para imprimir strings etc etc mas não as encontrei aqui neste PC. Isto é para atmega8 por isso pode não funcionar à primeira, podes ter que alterar algumas coisas.

Código: [Seleccione]
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1

void USART_Init( unsigned int ubrr)
{
  /* Set baud rate */
  UBRRH = (unsigned char)(ubrr>>8);
  UBRRL = (unsigned char)ubrr;
  /* Enable receiver and transmitter */
  UCSRB = (1<<RXEN)|(1<<TXEN);
  /* Set frame format: 8data, 1stop bit */
  UCSRC = (1<<URSEL)|(3<<UCSZ0);
}

void USART_Transmit( unsigned char data )
{
  /* Wait for empty transmit buffer */
  while ( !( UCSRA & (1<<UDRE)) )
  ;
  /* Put data into buffer, sends the data */
  UDR = data;
}

void write_dec(uint16_t c)
{
  char temp[4] = {'0','0','0','0'};
  int f=0;
  while(c){
    temp[f++]=c%10+'0';
    c=c/10;
  }
  int flag=0;
  for(f=3;f>0;f--){
    if(flag || temp[f] != '0'){
      flag = 1;
      USART_Transmit(temp[f]);
     }else{
      //USART_Transmit(0x20);
     }
  }
  USART_Transmit(temp[0]);
}

int main(void) { 
  int teste=100;
  USART_Init(MYUBRR);
  USART_Transmit('T');
  USART_Transmit(':');
  USART_Transmit('\n');
  USART_Transmit('\r');
  write_dec(adcGravado);
}


Título: Re: sfr05
Enviado por: tiagosilva510 em 06 de Junho de 2011, 11:44
mas pra isso ja teria que implementar comunicaçao rs232 n existe outra maneira de testar?
Título: Re: sfr05
Enviado por: Tayeb em 06 de Junho de 2011, 12:08
Sugiro exemplos de código para diferentes microcontroladores vêr na página do fabricante em:

http://www.robot-electronics.co.uk/acatalog/examples.html (http://www.robot-electronics.co.uk/acatalog/examples.html)
Título: Re: sfr05
Enviado por: tiagosilva510 em 16 de Junho de 2011, 11:07
nng tem codigo pra este sensor?

Título: Re: sfr05
Enviado por: tiagosilva510 em 16 de Junho de 2011, 11:33
tenho um codigo pic, mas n consigo passar pra atmega 88


Código: [Seleccione]
int sonar()
{
   unsigned char z=0;
   unsigned int result_sonar=0;
   
    PORTAbits.RA1=1; -> envia impulso
TMR1L=0; -> demora cerca de 10 us
TMR1H=0; -> nao è esta instruço que faz demorar os 10 us. Apenas faz perder tempo.
PORTAbits.RA1=0; -> pára de enviar impulso

T1CONbits.TMR1ON=1;
while(PORTAbits.RA2==0) -> espera até receber o impulso
if(TMR1L>200)
inicio();
TMR1H=0;
TMR1L=0;
while(PORTAbits.RA2!=0) -> espera at? acabar de receber o impulso
if(TMR1H>77)
inicio();
T1CONbits.TMR1ON=0; -> grava o tempo que demorou a receber o impulso
result_sonar=(TMR1L);
result_sonar=result_sonar+TMR1H*256; -> PIC tem 16b bits. Apenas se refere aos 8 bits mais significativos.
result_sonar=result_sonar/58; -> converte para centimetros
TMR1L=0;
TMR1H=0;
TMR1L=0;
TMR1H=0;
return result_sonar;
}
Título: Re: sfr05
Enviado por: tiagosilva510 em 18 de Junho de 2011, 09:16
nng me pode ajudar?
Título: Re: sfr05
Enviado por: senso em 19 de Junho de 2011, 00:12
Sugiro exemplos de código para diferentes microcontroladores vêr na página do fabricante em:

http://www.robot-electronics.co.uk/acatalog/examples.html (http://www.robot-electronics.co.uk/acatalog/examples.html)


É que até lá diz Arduino...
Título: Re: sfr05
Enviado por: tiagosilva510 em 20 de Junho de 2011, 15:01
eu uso atmega88, n uso arduino, apenas o atmega mesmo
Título: Re: sfr05
Enviado por: Sérgio_Sena em 20 de Junho de 2011, 21:17
Esse sensor é bastante simples de usar, concerteza que consegues converter esse código PIC para o AVR, não ?

É que ficar à espera de alguém que te dê o trabalho feito, pode demorar tempo, se aparecer.

A internet é grande. De certeza que já alguém usou esse sensor com um AVR.
basta usar o Google.

;)
Título: Re: sfr05
Enviado por: senso em 20 de Junho de 2011, 21:25
Manda-me o sensor lá para meio de Julho que é quando tenho tempo livre que eu faço-te o código e depois mando o sensor para trás.
Título: Re: sfr05
Enviado por: tiagosilva510 em 27 de Junho de 2011, 18:24
Boas amigos, tentei fazer o codigo do zero, para tal comecei por:

Código: [Seleccione]
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <delay.h>

void startRange(void);
//unsigned int getEcho(void);
void setup(void);

int main(void)
{
setup();

// unsigned int range;

while(1)
{
startRange(); // Send a high on the trigger pin to start a ranging

}
}

void startRange(void)
{
PORTD = 0b00000001; // Send trigger pin high
_delay_us(10);     // Wait 10us...
PORTD = 0b00000000;
_delay_us(10);
}

void setup(void)
{
DDRD = 0x01; // Port D pin 0 ouput all others input
}

se usar um valor tipo 250ms este bocado de codigo funciona na perfeiçao, no entanto com 10 us obtenho no osciloscopio sempre cerca de 3.6ms, sei que deve ter haver com o temporizador interno do atmega, alguem me pode dar uma ajuda a configurar? estes 10 us servem para dar o impulso no trigger do srf05.

cumprimentos
Título: Re: sfr05
Enviado por: senso em 27 de Junho de 2011, 19:34
Onde é que está o #define F_CPU?
Tens de o definir antes de fazer include do delay.h para ele saber o que fazer, esse código de certeza que te está a dar warning quanto a isso e tu não estás a ligar ao warning..
Título: Re: sfr05
Enviado por: tiagosilva510 em 28 de Junho de 2011, 15:31
defenindo isso ja dara tal como pretendo?
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Junho de 2011, 21:35
defeni tal como sugeriste, no entanto ainda me deu mais warnings assim..

Código: [Seleccione]
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#define F_CPU 1000000
#include <delay.h>

void startRange(void);
//unsigned int getEcho(void);
void setup(void);

int main(void)
{
setup();

// unsigned int range;

while(1)
{
startRange(); // Send a high on the trigger pin to start a ranging

}
}

void startRange(void)
{
PORTD = 0b00000001; // Send trigger pin high
_delay_us(10);     // Wait 10us...
PORTD = 0b00000000;
_delay_us(10);
}

void setup(void)
{
DDRD = 0x01; // Port D pin 0 ouput all others input
}


tá aí os warnings :


../sonar.c:4:1: warning: "F_CPU" redefined
<command-line>: warning: this is the location of the previous definition
In file included from ../sonar.c:5:
C:\Users\Tiago Silva\Desktop\..\..\..\WinAVR-20090313\avr\include\avr/delay.h:36:2: warning: #warning "This file has been moved to <util/delay.h>."
In file included from C:\Users\Tiago Silva\Desktop\..\..\..\WinAVR-20090313\avr\include\avr/delay.h:37,
                 from ../sonar.c:5:
c:/winavr-20090313/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 21:40
Estás a compilar em -O0 porque o default é -Os ou -O2.
Título: Re: sfr05
Enviado por: CBX em 29 de Junho de 2011, 22:21
se o F_CPU estiver na 1º linha o warning desaparece

a localização do delay é <util/delay.h>

não sei se é relevante mas assim os warnings desaparecem
Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 22:27
Mas esta linha:
Código: [Seleccione]
c:/winavr-20090313/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"

Diz claramente que ele desligou as optimizações do compilador e está a compilar em -O0.
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Junho de 2011, 22:28
fiz tal como disseram.. defeni na 1ª linha, mudei o nome a livraria, udei para -os, deu 2 warnings


../sonar.c:1:1: warning: "F_CPU" redefined
<command-line>: warning: this is the location of the previous definition
Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 22:30
Não podes ter duas vezes o F_CPU, se for igual não tem mal, mas se forem diferentes vai dar barraca, pois ele vai assumir o ultimo que leu e esse pode não ser o que estás á espera..
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Junho de 2011, 22:37
ja esta sem warnings..

mas o que esta diferente do inicial é apenas a livraria que estava mal defenida, assim ja me vai dar o tempo que pretendo?
Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 22:40
Sim, mais ou menos meia duzia de clocks, mas isso é bastante fiavel.
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Junho de 2011, 22:43
ok, amanha ja testo, quanto aos fuses nao sei como resolver isto =/ n estou a conseguir enviar..


Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 22:57
Isso é porque de certeza que programas-te os fuses errados.
Título: Re: sfr05
Enviado por: tiagosilva510 em 29 de Junho de 2011, 23:01
e como faço agora pra programar os certos?
Título: Re: sfr05
Enviado por: senso em 29 de Junho de 2011, 23:03
Depende do que fizeste.
Não consegues nem ler os fuses?
Tens outro Atmega?
Se sim, faz um programa em que simplesmente toglas um pino, ligas esse pino ao pino Xtal1 do atmega bloqueado que tens, e ligas tambem a massa dos dois em conjunto, depois tentas ler a assinatura, se funcionar é porque tens os fuses errados no que toca a cristal/oscilador externo, se não ler, é porque desligas-te o ISP.
Título: Re: sfr05
Enviado por: tiagosilva510 em 30 de Junho de 2011, 14:59
ja esta a funcionar, obrigado senso
Título: Re: sfr05
Enviado por: tiagosilva510 em 30 de Junho de 2011, 17:04
agora passei ao passo seguinte.. ja coloquei o triger a funcionar.. estou a trabalhar no echo

Código: [Seleccione]
#define F_CPU 1000000
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>

void startRange(void);
unsigned int echo(void);
void setup(void);

int main(void)
{
setup();

//unsigned int range;

while(1)
{
startRange(); // Send a high on the trigger pin to start a ranging
echo();
}
}

void startRange(void)
{
PORTD = (1<<DDD0); // Send trigger pin high
_delay_us(10);     // Wait 10us...
PORTD = (0<<DDD0); // Send trigger pin low
//_delay_us(10);
}

void setup(void)
{
DDRD = 0b00000001; // Port D pin 0 ouput all others input

}


unsigned int echo(void)
{
unsigned int range;
while((PIND = (1<<DDD1))); // Wait for echo pin to go high,  this indicates the start of the incoming pulse
//TCNT0 = 0x00;
//TCCR0B =0b00000100;
while((PIND = (0<<DDD1))); // Wait for echo pin to go low signaling that the pulse has ended
//TCCR0B = 0x08;
range = TCNT1/29; // Read back value in the timer counter register, this number divided by 29 will give us the range in CM

return(range);
}

preciso de ajuda com esses contadores.. pk faz-me muita confusao a maneira de funcionar os contadores.. n percebo muito de como os por a funcionar..

Cumprimentos
Título: Re: sfr05
Enviado por: tiagosilva510 em 01 de Julho de 2011, 21:03
nng da uma ajuda?
Título: Re: sfr05
Enviado por: senso em 02 de Julho de 2011, 00:08
Dá uma leitura no meu tutorial sobre timers:
http://hekilledmywire.wordpress.com/2011/05/28/introduction-to-timers-tutorial-part-6/ (http://hekilledmywire.wordpress.com/2011/05/28/introduction-to-timers-tutorial-part-6/)

É que não configuras nada de nada dos timers e estás á espera que eles como que por milagre funcionem
Título: Re: sfr05
Enviado por: tiagosilva510 em 04 de Julho de 2011, 19:11
vou hoje mesmo ler o teu tutorial :)

agradeço desde ja a ajuda senso ;)
Título: Re: sfr05
Enviado por: tiagosilva510 em 20 de Julho de 2011, 20:38
nao estou a conseguir gerar uma interrupção com 1micro segundo.. alguem me ajuda? acho que estou a fazer as contas mal
Título: Re: sfr05
Enviado por: senso em 20 de Julho de 2011, 22:50
1us ou 1ms?
Título: Re: sfr05
Enviado por: tiagosilva510 em 20 de Julho de 2011, 23:38
1 us
Título: Re: sfr05
Enviado por: tcustodio em 21 de Julho de 2011, 00:20
segundo o código fonte das funções de delay um delay tão pequeno é impossível...

Citar
void delayMicroseconds(unsigned int us)
{
   // calling avrlib's delay_us() function with low values (e.g. 1 or
   // 2 microseconds) gives delays longer than desired.
   //delay_us(us);

#if F_CPU >= 16000000L
   // for the 16 MHz clock on most Arduino boards

   // for a one-microsecond delay, simply return.  the overhead
   // of the function call yields a delay of approximately 1 1/8 us.
   if (--us == 0)
      return;

   // the following loop takes a quarter of a microsecond (4 cycles)
   // per iteration, so execute it four times for each microsecond of
   // delay requested.
   us <<= 2;

   // account for the time taken in the preceeding commands.
   us -= 2;
#else
   // for the 8 MHz internal clock on the ATmega168

   // for a one- or two-microsecond delay, simply return.  the overhead of
   // the function calls takes more than two microseconds.  can't just
   // subtract two, since us is unsigned; we'd overflow.
   if (--us == 0)
      return;
   if (--us == 0)
      return;

   // the following loop takes half of a microsecond (4 cycles)
   // per iteration, so execute it twice for each microsecond of
   // delay requested.
   us <<= 1;
    
   // partially compensate for the time taken by the preceeding commands.
   // we can't subtract any more than this or we'd overflow w/ small delays.
   us--;
#endif

   // busy wait
   __asm__ __volatile__ (
      "1: sbiw %0,1" "\n\t" // 2 cycles
      "brne 1b" : "=w" (us) : "0" (us) // 2 cycles
   );
}


ali pouco depois do início:
Citar
// for a one-microsecond delay, simply return.  the overhead
   // of the function call yields a delay of approximately 1 1/8 us.
   if (--us == 0)
      return;

:/
Título: Re: sfr05
Enviado por: senso em 21 de Julho de 2011, 00:24
Basta usar um timer de 8 bits, com prescaler a 1 e meter count até 16, mas isso não te dá muito tempo para executar código é usar o modo CTC a fazer o toogle to pino.

Podes fazer delay de 4 instruções ou mais usando o _delay_loop2(unsigned int val)
Título: Re: sfr05
Enviado por: tiagosilva510 em 23 de Julho de 2011, 21:06
o varrimento de leds ja esta feito... agora queria por um buzzer a apitar com maior frequencia qunato menor for a distancia...

Código: [Seleccione]
#define F_CPU 1000000
#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include<interrupt.h>

unsigned int distancia=0,distancia_1=0;
unsigned char ler_pino=0,contador=800;

int cont=0;
void startRange(void);
unsigned int echo(void);
void setup(void);


/*ISR(TIMER0_COMPA_vect) {
contador--; //decrementa o contador até chegar a 0 (500ms)
if(contador==0) {
contador=800;
PORTD=~PORTD;// vai negar o estado do led, se estiver aceso apaga e vice versa
}
}*/



int main(void)
{
setup();



while(1)
{
startRange(); // Send a high on the trigger pin to start a ranging
distancia=echo();
distancia_1=((distancia*6)/58);

if(distancia_1>=650){
PORTB = 0b00000001;
// OCR0A=170;
}
if(distancia_1<550){
PORTB = 0b00000011;
// OCR0A=150;
}
if(distancia_1<450){
PORTB = 0b00000111;
// OCR0A=120;
}
if(distancia_1<350){
PORTB = 0b00001111;
// OCR0A=100;
}
if(distancia_1<250){
PORTB = 0b00011111;
// OCR0A=70;
}
if(distancia_1<150){
PORTB = 0b00111111;
// OCR0A=40;
}
if(distancia_1<70){
PORTB = 0b01111111;
// OCR0A=15;

}
_delay_ms(300);
}
}



void startRange(void)
{
PORTC =0b00000001 ; // Send trigger pin high
_delay_ms(15);     // Wait 10us...
PORTC = 0b00000000; // Send trigger pin low
}

unsigned int echo(){
unsigned int cont_sonar=0;
ler_pino=PINC&0b00000010;
while(ler_pino!=0b00000010)
ler_pino=PINC&0b00000010;
while(ler_pino!=0b00000000)
{
cont_sonar++;
ler_pino=PINC&0b00000010;
}

return cont_sonar;
}
void setup(void)
{
DDRC = 0b00000001; // Port D pin 0 ouput all others input
DDRB = 0b01111111;
PORTB = 0b00000000;
DDRD = 0b00000001;
TIMSK0=TIMSK0|2; //habilita a flag de interrupção do TC0
SREG=SREG|0X80; //HABILITA AS INTERRUPÇOES GLOBAIS
TCCR0A=0b10000011; //Timer0A
TCCR0B=0b00000100; //prescaler 256
}

tou a tentar fazer isso atravez do OCR0A mas n tou a conseguir.. alguem me ajuda?