LusoRobótica - Robótica em Português
Robótica => Iniciantes => Tópico iniciado 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?
-
Viva Tiago, sobre os SRF05 posso ajudar no atmel nem por isso.
Coloca as tuas questões.
Cumprimentos, Mauro.
-
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
-
Basta usares sei(); para ligar as interrupções, não é preciso andar a inventar com assembly.
-
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,
#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
-
Testar é usar uma fita métrica meter algo a uma distancia conhecida e ver o que o sensor te dá.
-
sim, mas este codigo é apenas para o sensor, ainda n fiz pro lcd.. como sei o q da assim?
-
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.
#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);
}
-
mas pra isso ja teria que implementar comunicaçao rs232 n existe outra maneira de testar?
-
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)
-
nng tem codigo pra este sensor?
-
tenho um codigo pic, mas n consigo passar pra atmega 88
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;
}
-
nng me pode ajudar?
-
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...
-
eu uso atmega88, n uso arduino, apenas o atmega mesmo
-
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.
;)
-
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.
-
Boas amigos, tentei fazer o codigo do zero, para tal comecei por:
#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
-
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..
-
defenindo isso ja dara tal como pretendo?
-
defeni tal como sugeriste, no entanto ainda me deu mais warnings assim..
#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"
-
Estás a compilar em -O0 porque o default é -Os ou -O2.
-
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
-
Mas esta linha:
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.
-
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
-
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..
-
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?
-
Sim, mais ou menos meia duzia de clocks, mas isso é bastante fiavel.
-
ok, amanha ja testo, quanto aos fuses nao sei como resolver isto =/ n estou a conseguir enviar..
-
Isso é porque de certeza que programas-te os fuses errados.
-
e como faço agora pra programar os certos?
-
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.
-
ja esta a funcionar, obrigado senso
-
agora passei ao passo seguinte.. ja coloquei o triger a funcionar.. estou a trabalhar no echo
#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
-
nng da uma ajuda?
-
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
-
vou hoje mesmo ler o teu tutorial :)
agradeço desde ja a ajuda senso ;)
-
nao estou a conseguir gerar uma interrupção com 1micro segundo.. alguem me ajuda? acho que estou a fazer as contas mal
-
1us ou 1ms?
-
1 us
-
segundo o código fonte das funções de delay um delay tão pequeno é impossível...
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:
// 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;
:/
-
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)
-
o varrimento de leds ja esta feito... agora queria por um buzzer a apitar com maior frequencia qunato menor for a distancia...
#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?