Ir ao conteúdo
  • Cadastre-se

Duvida projeto


Posts recomendados

eu e uns amigos do curso estamos tentando montar um carrinho com arduino e l298 mais não ta funcionando, tipo ele só anda para a frente vou postar o codigo que estou usando e como fiz a ligação:

OBS:tipo se eu ligar o enable no 5 e 6 como está no codigo ele nem anda só o sensor que se move.

Se alguem puder me dar uma luz eu agradeço.... desculpem o incomodo a programação não é muito o meu forte..





 

 

#include <Servo.h>
#include <Ultrasonic.h>
Servo myservo;
int pos = 90;  //posição inicial do servo
int echopin = 9; // a saido echo do SRF05 liga no pin 9
int trigerpin = 8; // a saida triger do SRFo5 liga no pin 8
int in1 = 2; // pino 1 do motor 1
int in2 = 3; // pino 2 do motor 1
int in3 = 4; // pino 1 do motor 2
int in4 = 7; // pino 2 do motor 2
int enable1 = 5; // define a velociadade do motor 1
int enable2 = 6; // define a velocidade do motor 2
unsigned long pulsetime = 0; // Variavel que faz a leitura do pulso
unsigned long distancia = 0; //Variavel que que armazena a distancia
void stopMotor() {
  //para os motores
  analogWrite(enable1, 0);
  analogWrite(enable2, 0);
}
void setup()
{
  myservo.attach(10); // anexa o servo lógico ao fisico no pino 10
  pinMode(enable1, OUTPUT); // define todos os pinos como saída
  pinMode(enable2, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(trigerpin, OUTPUT); // define o pino triger como saída
  pinMode(echopin, INPUT); // define o pino echo como entrada
}
void loop()
{

  distancia = leiaDistancia(); //executa a funcao que retorna a distancia em cm
 
  if (distancia > 16) // se a distancia for maior que 16 cm
     {
       andeParaFrente();  //continua andando.
     }
  else { //senão, lógico, a distancia frontal é MENOR ou IGUAL a 16.

       
       stopMotor(); //pare o motor
       delay(1000); //aguarde 1 segundo
       
       int distEsquerda = 0;
       int distDireita = 0;
       myservo.write(175); //gira o servo a 175 graus
       delay(1000); // tem que ser ajustado para esperar o servo chegar no 175
       distEsquerda = leiaDistancia();
       myservo.write(90); //gira o servo para 90 graus - deve ser a posicao inicial ou central.
              
       //vamos analisar o que foi lido na Esquerda
       if (distEsquerda > 16) // se a distancia ESQUERDA for maior que 16 cm
       {
          giraParaEsquerda(3000); //invoca a funcao que gira para ESQUERDA por 3 segundos. Favor ajustar esse valor.
       
       } else { //senão, lógico, a distancia esquerda é MENOR ou IGUAL a 16. Vamos analisar a DIREITA, então.
           myservo.write(5);
           delay(1000);//tem que esperar o servo chegar em 5 graus.
           distDireita = leiaDistancia(); // lendo a distancia da DIREITA
           myservo.write(90); //gira o servo para 90 graus - deve ser a posicao inicial ou central.
           
           if(distDireita > 16){
             giraParaDireita(3000); // mesma coisa. ajute esse TEMPO para que o robo gire os 5 graus.
           }
       }
  }
}
int leiaDistancia(){ //funcao que devolve a distancia em cm
  digitalWrite(trigerpin, HIGH);
  delayMicroseconds(50);
  digitalWrite(trigerpin,LOW);
  pulsetime = pulseIn(echopin, HIGH);
  return pulsetime/58; // converte para cm
}
void andeParaFrente(){
    analogWrite(enable1, 255); // velocidade do motor 1
    analogWrite(enable2, 255); // velocidade do motor 2
    digitalWrite(in1, LOW); // apenas pinos secundarios em HiGH, definindo o movimento para frente
    digitalWrite(in2, HIGH);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
}
void giraParaEsquerda(long tempo){//funcao para girar a esquerda. Observe o tempo em millissegundos.
      analogWrite(enable1, 255);
      analogWrite(enable2, 0); // gira para esquerda
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      delay(tempo); //o motor só deve ficar ligado esse tempo.
      stopMotor(); //agora eu desligo.
}
void giraParaDireita(long tempo){//funcao para girar a esquerda. Observe o tempo em millissegundos.
      analogWrite(enable1, 0); // girar a direta
      analogWrite(enable2, 255);
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      delay(tempo); //o motor só deve ficar ligado esse tempo.
      stopMotor(); //agora eu desligo.
}

post-721517-0-62515400-1433989163.png

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

olha aviso que não me dou bem com arduíno...voce provavelmente está usando ponte H, né? NÉÉÉ?! Então se a função anda pra frente é essa:

digitalWrite(in1, LOW); // apenas pinos secundarios em HiGH, definindo o movimento para frentedigitalWrite(in2, HIGH);digitalWrite(in3, LOW);digitalWrite(in4, HIGH);

A pra trás tem que inveter os HIGH por LOW e vice versa

digitalWrite(in1, HIGH); // apenas pinos secundarios em LOW, definindo o movimento para trásdigitalWrite(in2, LOW);digitalWrite(in3, HIGH);digitalWrite(in4, LOW);

Pra frente é que se anda... aff que nada a ver...

abç


Obs: não conheço o driver do motor nem seus comandos! Espere alguém te iluminar melhor!


É que as vezes (ou sempre) minha intuição falha.

Link para o comentário
Compartilhar em outros sites

  • 2 semanas depois...

Oi pessoal desculpe a demora para responder é que eu estava com o tempo meio apertado esses dias (muita prova)....
vou passar a programação que a gente usou um cara ajudou a gente dar uma arrumada e que deu certo para o carrinho :

#include <Servo.h>
#include <Ultrasonic.h>
Servo myservo;
int pos = 90;  //posição inicial do servo
int echopin = 9; // a saido echo do SRF05 liga no pin 9
int trigerpin = 8; // a saida triger do SRFo5 liga no pin 8
int BUZZER = 11; // Ligar o buzzer (Som) no pino 11

int in1 = 4; // pino 1 do motor 1
int in2 = 5; // pino 2 do motor 1
int in3 = 6; // pino 1 do motor 2
int in4 = 7; // pino 2 do motor 2

unsigned long pulsetime = 0; // Variavel que faz a leitura do pulso
unsigned long distancia = 0; //Variavel que que armazena a distancia
void stopMotor() {
  //para os motores
   digitalWrite(in1, LOW);
   digitalWrite(in2, LOW);
   //delay(500);
   digitalWrite(in3, LOW);
   digitalWrite(in4, LOW);
   //delay(500);
}

void setup()
{
  pinMode(BUZZER,OUTPUT);// define o pino do buzzer como saída.
  myservo.attach(10); // anexa o servo lógico ao fisico no pino 10
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(trigerpin, OUTPUT); // define o pino triger como saída
  pinMode(echopin, INPUT); // define o pino echo como entrada
}
void loop()
{
  distancia = leiaDistancia(); //executa a funcao que retorna a distancia em cm
  if (distancia > 16) // se a distancia for maior que 16 cm
     {
       andeParaFrente();  //continua andando.
     }
  else { //senão, lógico, a distancia frontal é MENOR ou IGUAL a 16.
      
       stopMotor(); //pare o motor
       delay(1000); //aguarde 1 segundo
       
       int distEsquerda = 0;
       int distDireita = 0;
       myservo.write(175); //gira o servo a 175 graus
       delay(1000); // tem que ser ajustado para esperar o servo chegar no 175
       distEsquerda = leiaDistancia();
       myservo.write(90); //gira o servo para 90 graus - deve ser a posicao inicial ou central.
              
       //vamos analisar o que foi lido na Esquerda
       if (distEsquerda > 16) // se a distancia ESQUERDA for maior que 16 cm
       {
          giraParaEsquerda(3000); //invoca a funcao que gira para ESQUERDA por 3 segundos. Favor ajustar esse valor.
       
       } else { //senão, lógico, a distancia esquerda é MENOR ou IGUAL a 16. Vamos analisar a DIREITA, então.
           myservo.write(5);
           delay(1000);//tem que esperar o servo chegar em 5 graus.
           distDireita = leiaDistancia(); // lendo a distancia da DIREITA
           myservo.write(90); //gira o servo para 90 graus - deve ser a posicao inicial ou central.
           
           if(distDireita > 16){
             giraParaDireita(3000); // mesma coisa. ajute esse TEMPO para que o robo gire os 5 graus.
           }
           if(distDireita <= 16) {
             girar180graus(3000);
         }
       }
  }
}
int leiaDistancia(){ //funcao que devolve a distancia em cm
  digitalWrite(trigerpin, HIGH);
  delayMicroseconds(50);
  digitalWrite(trigerpin,LOW);
  pulsetime = pulseIn(echopin, HIGH);
  return pulsetime/58; // converte para cm
}
void andeParaFrente(){    
    digitalWrite(in1, LOW); // apenas pinos secundarios em HiGH, definindo o movimento para frente
    digitalWrite(in2, HIGH);
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
}
void giraParaEsquerda(long tempo){//funcao para girar a esquerda. Observe o tempo em millissegundos.
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
      delay(tempo); //o motor só deve ficar ligado esse tempo.
      stopMotor(); //agora eu desligo.
}
void giraParaDireita(long tempo){//funcao para girar a direita. Observe o tempo em millissegundos.
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      delay(tempo); //o motor só deve ficar ligado esse tempo.
      stopMotor(); //agora eu desligo.
}
void girar180graus(long tempo){//funcao para girar 180 graus. Observe o tempo em millissegundos.
      tone(11,300,300);
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
      delay(1000); //o motor só deve ficar ligado esse tempo.
      tone(11,300,300);
      stopMotor(); //agora eu desligo.
}

Link para o comentário
Compartilhar em outros sites

  • 3 semanas depois...

Olá meus amigos desse forum, um abraço a todos em especial ao meu queridissimo professor Paulo. Gostaria de aproveitar esse espaço e pedir uma orientação pois estou tendo dificuldades em um pequeno projeto usando o sensor SRF04. Trata-se de um sensor de movimento por ultrassom, o código que desenvolvi é em basic usando o PSI. Se houver alguém interessado em ajudar poderei postar meu codigo para analise.

Link para o comentário
Compartilhar em outros sites

@TcheCara,

 

Opa meu amigo, todos somos professores quando conseguimos repassar um pouco de nossa experiência acumulada, mas também somos todos alunos quando aprendemos pela experiência dos outros !!!! Esse é o segredo, estar de mente aberta sempre !

 

Faz tempo que não uso o PSI mas é um Basic, fica bem mais fácil de entender.

 

Poste o código, eu já usei esse sensor em alguns projetos.

 

Paulo

Link para o comentário
Compartilhar em outros sites

Beleza Mestre, o pouco que eu sei é em basic através da tua apostila, vamos lá: Eu configurei o TIMER0 para fazer interrupções à cada 1 mS e incrementar minha variavel para ter um parâmetro para comprarar o tempo do ECO à cada vez que eu mando um pulso no TRIGGER.

 

'SENSOR DE MOVIMENTO
'07/07/2015
'PIC 16F628A
Define CONF_WORD = 0x3f50
Define CLOCK_FREQUENCY = 4
TRISA = 0xff  'seta todas portas A como entrada
TRISB = 00000111b  'portas 0, 1 e 2 como entrada as demais saida
Dim conta As Byte
Dim tempo(4) As Byte
Dim x As Byte
Dim i As Byte
Dim medida(2) As Byte
PORTB.5 = 0
WaitMs 100  'Vamos esperar o sensor estabilizar e depois mandar o pulso
 
OPTION_REG.T0CS = 0  'USAR CLOCK INTERNO
OPTION_REG.PSA = 0  'PS2, PS1, PS0 CONFIGURADOS PARA PRESCALER = 4
OPTION_REG.PS2 = 0
OPTION_REG.PS1 = 0
OPTION_REG.PS0 = 1
TMR0 = 0x06  'CONTAGEM INICIAL DO TIMER0 EM 6
INTCON.T0IE = 1  'habilita  timer0 interrupção
INTCON.GIE = 1  'habilitas todos interrupções un-masked
OPTION_REG.T0CS = 0  'definir fonte de relógio timer0 de instrução interna do relógio de ciclo
Enable
medida(0) = 0
medida(1) = 0
i = 0
ciclo:
 
conta = 0
tempo(0) = 0
tempo(1) = 0
tempo(2) = 0
tempo(3) = 0
 
x = 0
 
For x = 0 To 4  'Vamos medir 4 vezes e fazer a media
    
    If x = 4 Then
        Goto registra
    Endif
    PORTB.5 = 1  'aqui geramos o pulso TRIGGER de 10 uS aprox para o SRF04
    WaitUs 10
    PORTB.5 = 0
    
verifica:
    
    If PORTA.4 = 1 Then  'aqui monitoramos a porta ECHO do SRF04
    Goto mede
    Endif
    Goto verifica
 
alarme:
If medida(0) = medida(1) Then  'se o tempos forem iguais
        PORTB.7 = 0
        
Else
    PORTB.7 = 1
    WaitMs 10
    PORTB.7 = 0
 
Endif
 
medida(0) = 0
medida(1) = 0
 
Goto ciclo
 
End                                                
mede:
 
On Interrupt  'interrompe a rotina à cada 1 mS
    
        conta = conta + 1  'aqui faz incremento a cada 1 mS
 
TMR0 = 0x06  'zera contagem
INTCON.T0IF = 0  'habilita nova interrupção
 
    If PORTA.4 = 0 Then
    tempo(x) = conta  'AQUI SALVAMOS A MEDIDA DO TEMPO
conta = 0
    Goto retorna
    Endif
    Goto mede
retorna:  'faz voltar para proximo x
 
Next x
 
 
registra:
 
medida(i) = tempo(0) + tempo(1) + tempo(2) + tempo(3)
 
Select Case i
 
Case 0
i = 1
 
Goto ciclo
Case 1
i = 0
Goto alarme
    
EndSelect
 
Resume                                             
      

Link para o comentário
Compartilhar em outros sites

@TcheCara,

Me diz o que que está acontecendo, o que que voce já conferiu.... Isso ajuda bastante.

Só uma sugestão, o PSI usa o Timer0 para algumas funcões, seria mais interessante voce usar o Timer1 para gerar pulsos ( frequência ), por exemplo 1 pulso a cada 100 microsegundos, e usar a função Count() para contar os pulsos ( essa função usa o Timer0 para isso, mas é bem precisa, e é uma maneira simples de saber o tempo do eco ) assim, quando voce faz o pulso de start do módulo, voce também libera o Timer1, e usa o Count() para verificar a contagem durante um tempo máximo de 40 milisegundos ( se demorar mais que esse tempo significa que o objeto está mais distante do que o sensor consegue medir ), entendeu ?

Acho que você precisa também implementar alguma tolerância no seu resultado, para poder ter certeza de que houve movimento.

Paulo

Link para o comentário
Compartilhar em outros sites

Paulo a situação é a seguinte: Montando o circuito eu tenho o led da portb.7 piscando e quando passo a mão na frente do SFR04 dá pra perceber alteração no led e quando chego a 15cm aprox. o led tende a apagar. Implementei uma tolerância de 10% depois de 20% até chegar em 30% mas não houve melhoras significativas. Retirando a conexão que envia pulso para o trigger o led apaga como deveria acontecer. Parece que o sistema em si está ok e o problema estaria no código. Nos testes estou com sensor a 1,80 mt da parede.

Link para o comentário
Compartilhar em outros sites

@TcheCara,

 

A estrutura está toda errada.... voce colocou a interrupção no meio do programa, e ficou muito confuso para mim, imagina para o compilador kkkk !

 

Primeiro, o conceito de interrupção : ela tem de ser muito curta, fazer apenas o necessário, e sair. Não pode ficar esperando dezenas de milisegundos para fazer um RESUME !

 

A rotina de interrupção deve apenas incrementar o contador, e sair com o RESUME.

 

Os teste de valor do contador ( caso ultrapasse um valor máximo, que significa que não houve nenhum retorno de eco , por exemplo 40 milisegundos ) , e o teste para ver se o sinal de eco mudou , tem de ser feito no corpo principal do programa.

 

Outra coisa : após o END, só pode ter código da rotina de interrupção !!  Do jeito que está , tem programa também, e isso confunde o compilador.

 

Mais uma coisa, o ON INTERRUPT tem de ter também o SAVE SYSTEM, pois voce faz uma operação matemática, e isso pode atrapalhar.

 

Por último, essa estrutura SELECT CASE, onde só tem duas possibilidades, melhor fazer com IF mesmo. voce está mudando a variável do CASE dentro de um próprio CASE, pode dar errada a próxima comparação do SELECT CASE.

 

Paulo

Link para o comentário
Compartilhar em outros sites

OK Paulo, implementei as modificações mas na prática continua igual, parece que só trocou 6 por 1/2 dúzia pois o resultado é o mesmo. Ficou assim:

 

'SENSOR DE MOVIMENTO


'PIC 16F628A
Define CONF_WORD = 0x3f50
Define CLOCK_FREQUENCY = 4
TRISA = 0xff  'seta todas portas A como entrada
TRISB = 00000111b  'portas 0, 1 e 2 como entrada as demais saida
Dim conta As Byte
Dim tempo(4) As Byte
Dim x As Byte
Dim i As Byte
Dim medida(2) As Byte
Dim tolerancia1 As Byte
Dim tolerancia2 As Byte
PORTB.5 = 0
WaitMs 100  'Vamos esperar o sensor estabilizar e depois mandar o pulso
OPTION_REG.T0CS = 0  'USAR CLOCK INTERNO
OPTION_REG.PSA = 0  'PS2, PS1, PS0 CONFIGURADOS PARA PRESCALER = 4
OPTION_REG.PS2 = 0
OPTION_REG.PS1 = 0
OPTION_REG.PS0 = 1
TMR0 = 0x06  'CONTAGEM INICIAL DO TIMER0 EM 6
INTCON.T0IE = 1  'habilita  timer0 interrupção
INTCON.GIE = 1  'habilitas todos interrupções un-masked
OPTION_REG.T0CS = 0  'definir fonte de relógio timer0 de instrução interna do relógio de ciclo
Enable
medida(0) = 0
medida(1) = 0
i = 0

 

ciclo:
 
conta = 0
tempo(0) = 0
tempo(1) = 0
tempo(2) = 0
tempo(3) = 0
x = 0
 
For x = 0 To 4  'Vamos medir 4 vezes e fazer a media
    
    If x = 4 Then
        Goto registra
    Endif
        PORTB.5 = 1  'aqui geramos o pulso TRIGGER de 10 uS aprox para o SRF04
       WaitUs 10
       PORTB.5 = 0
    
verifica:
    
    If PORTA.4 = 1 Then  'aqui monitoramos a porta ECHO do SRF04
       Goto mede
    Endif
      Goto verifica
 
alarme:

tolerancia1 = medida(1) + ((medida(1) * 10) / 100)  'tolerancia de 10% para erro
tolerancia2 = medida(1) - ((medida(1) * 10) / 100)
 
If tolerancia2 <= medida(0) And medida(0) <= tolerancia1 Then  'aqui aceito erro de 10% abaixo e acima
 
    PORTB.7 = 0
        
Else
    PORTB.7 = 1
    WaitMs 10
    PORTB.7 = 0
 
Endif
 
tolerancia1 = 0
tolerancia2 = 0
medida(0) = 0
medida(1) = 0
 
Goto ciclo
 
testa:
 
    If PORTA.4 = 0 Then
       

         tempo(x) = conta  'AQUI SALVAMOS A MEDIDA DO TEMPO
        conta = 0
        Goto retorna  'faz voltar para proximo x
 
    Endif
    Goto mede

 

retorna:
Next x
 
registra:
 
medida(i) = tempo(0) + tempo(1) + tempo(2) + tempo(3)
If i = 0 Then
   i = 1
  Goto ciclo
Endif
 
If i = 1 Then
   i = 0
   Goto alarme
Endif
 
End______________________________________________________________________

                                               
mede:

On Interrupt  'interrompe a rotina à cada 1 mS
         Save System
        conta = conta + 1  'aqui faz incremento a cada 1 mS
TMR0 = 0x06  'zera contagem
INTCON.T0IF = 0  'habilita nova interrupção
       Goto testa
Resume___________________________________________________________________                                            
 
                
 
 

Link para o comentário
Compartilhar em outros sites

@TcheCara,

 

voce só mudou a cara do programa, continuam os mesmos erros : a rotina de interrupção, em vez de simplesmente incrementar e sair, vai para um ciclo de testes, e retorna para a mesma rotina, aguardando o eco..... e o tempo vai passando....

 

voce não precisa do INTCON.TOIF=0 , o próprio comando RESUME já habilita de novo a interrupção.

 

Mude o programa, voce tem de ficar fazendo os testes sobre o retorno do eco no seu programa principal; deixe a rotina de interrupção ficar fazendo apenas o incremento da variável.

 

O que voce pode fazer é criar um Flag, que seja setado pela rotina de interrupção. Assim, caso a sua variável conta atingir um valor maior do que 400 voce seta esse flag. E essa mesma rotina de interrupção pode sempre fazer um simples teste no sinal do eco; caso haja retorno do eco, ela seta o flag e pára de incrementar a variável conta enquanto o flag não seja resetado pelo programa principal.

 

Assim, o seu programa principal faz conta=0, gera o pulso de início para o SRf-04, reseta o flag, e depois disto fica simplesmente testando se a variável de flag foi setada; caso tenha sido, basta ler o valor dela, que será o tempo decorrido, ou se tiver o valor de 400, significa que não houve nenhum retorno do eco.

 

voce só precisa implementar um pequeno teste no flag dentro da interrupção; se o flag estiver resetado, pode incrementar a variável conta e fazer o teste; se o flag estiver setado, simplesmente sai, sem incrementar a variável conta, entendeu ?

 

Paulo

Link para o comentário
Compartilhar em outros sites

Paulo agora sim, tu deu nos dedos. Esse é meu problema, eu ainda não consegui entender como pegar o resultado da minha variável conta dentro da rotina de interrupção sem entrar nela. Sei que essa informação está gravada na memória do pic só não sei o caminho para chegar lá. Você fala em criar um Flag, seria esse o caminho? Vou dar uma pesquisada para entender como trabalhar com Flags.

Link para o comentário
Compartilhar em outros sites

@TcheCara,

 

Opa, isso mesmo !

 

Crie uma variável qualquer tipo byte mesmo. Vou dar um exemplo, chame ela de Flag_1 .

 

Sempre antes de gerar o pulso para fazer o eco, faça Flag_1 = 0

 

Dentro da rotina de interrupção, voce primeiro verifica se Flag_1=0 . Se for, continue a rotina, se não for, pode ir ao final e sair.

 

Depois, a rotina de interrupção testa o pino para ver se recebeu o eco. Se sim, então faça Flag_1 = 1, e vai ao final, saindo da interrupção.

 

Se não, incrementa a tua variável conta, e verifica se ela chegou a 40. Se sim, faça Flag_1 = 1, e vai ao final, saindo da interrupção.

Se não, vai ao final da rotina e saia.

 

Agora, olhe o seu programa principal :

 

Após  gerar o pulso de eco, ele só tem de ficar monitorando essa variável Flag_1, esperando ela ficar = 1 !!!

 

Aí, basta ver o valor de conta. Se conta = 40, é que não houve retorno do eco ( muito longe do sensor ). E se conta for diferente de 400, esse é o tempo do eco, entendeu ?

 

Só mais um comentário.... supondo a velocidade do som 300 metros em um segundo, em 1 milisegundo o som já percorreu 30 centímetros !!!!!   Ou seja, como existe o tempo de ida e de volta, significa que a sua resolução é de apenas 15 centímetros de distância !!!!

 

O certo seria usar um tempo menor de interrupção, por exemplo 200 microsegundos, e aí sim voce teria uma resolução de 3 centímetros.

 

Mas para poder fazer isso com mais segurança, tem de usar o maior clock possível, 10 Mhz de cristal.

 

 

Paulo

Link para o comentário
Compartilhar em outros sites

Paulo, agora eu é que fiquei confuso, pois se era para preservar a rotina de interrupção mantendo ela sem muita interferência para não atrapalhar, agora ela está cheia de tarefas agindo durante sua execução. A não ser que tenha entendido tudo errado. Conforme entendi ficou assim:

 

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

flag_1 = 0
PORTB.5 = 1  'aqui geramos pulso de 10 uS para o trigger
WaitUs 10
PORTB.5 = 0
 
If flag_1 = 1 Then
 
    If conta = 40 Then  'não houve retorno do eco
    PORTB.7 = 1  'saida de alarme
    WaitMs 10
    PORTB.7 = 0
    Endif
 
Endif
 
End _________________________________________________________________________________                                              
 
On Interrupt  'interrompe a rotina à cada 1 mS
 
If flag_1 = 0 Then  'se for zero faz a rotina, se for 1 vai direto ao fim
    Save System
    TMR0 = 0x06  'zera contagem
Endif
 
If flag_1 = 1 Then
Goto sair  'pula direto para o fim
 
Endif
 
If PORTA.4 = 0 Then  'se recebeu o eco porta.4 vai de 1 para ZERO
flag_1 = 1
Goto sair   ' pula direto para o fim
Endif
 
conta = conta + 1
If conta = 40 Then
flag_1 = 1
Endif
 
sair:
 
Resume _____________________________________________________________________________________                                   

Link para o comentário
Compartilhar em outros sites

@TcheCara

 

Calma, é bem mais simples ...A rotina de interrupção fica assim :

 

 

On Interrupt  'interrompe a rotina à cada 1 mS
Save System

If flag_1 = 1 Then  'se for zero faz a rotina, se for 1 vai direto ao fim
  goto sair
Endif

 

conta = conta + 1

If PORTA.4 = 0 Then  'se recebeu o eco porta.4 vai de 1 para ZERO
   flag_1 = 1
   Goto sair   ' pula direto para o fim
Endif
 

 

If conta = 40 Then
   flag_1 = 1
Endif

sair:

 

TMR0 = 0x06  'zera contagem

 

Resume

 

 

Viu ? nenhum bicho de sete cabeças....

Agora, o seu programa principal :

 

 

flag_1 = 0
PORTB.5 = 1  'aqui geramos pulso de 10 uS para o trigger
WaitUs 10
PORTB.5 = 0

 

esperando: ' fica sempre esperando a variável flag ser =1

 

If flag_1 = 1 Then

    If conta = 40 Then  'não houve retorno do eco
        PORTB.7 = 1  'saida de alarme
        WaitMs 10
        PORTB.7 = 0

    Else

         goto pode_contuinuar    

    Endif
Else

    goto esperando
Endif
 

pode_continuar:

 

' continue aqui o seu processamento, agora conta tem o tempo do eco !

' e ao final volte para algum lugar, para continuar medindo os tempos.

 

goto sei_lá_aonde_no_seu_programa   ' kkkkkkkk

 

End

 

 

Tá quase chegando lá, falta bem pouco agora !

 

Paulo

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Olá Paulo, retornando ao nosso estudo. Eu implementei a rotina seguindo tuas instruções e fiz ensaios no PSI. Forcei uma situação para Alarme onde PORTB.7 vai a 1 e uma situação em que o ECO chega no tempo previsto e a PORTA.4 vai a 0, até ai tudo OK. Mas estou tendo o seguinte problema: Quando rodo o programa na primeira vez ele vai ate a interrupção e encrementa a variável CONTA após isso vai para verificação para saber se a situação é de ALARME ou não e de lá vai para CICLO onde novamente envio o pulso de 10 uS para o TRIGGER e vou novamente para interrupção pra incrementar novamente a varíavel CONTA =====> śo que isso não ocorre, não há mais interrupções e a variável CONTA não sofre mais incrementos e o programa parece ficar parado no END.

 

///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////

 
ciclo:
conta = 0
flag_1 = 0
PORTB.5 = 1
WaitUs 10
PORTB.5 = 0
Goto contagem

verifica:
 
If flag_1 = 1 Then
    If conta < 40 Then
        PORTB.7 = 1
        WaitMs 10
        PORTB.7 = 0
Goto ciclo  'Eco não retornou no tempo previsto, alarma e retorna novo ciclo
        Else
        Goto ciclo  'Tudo ok eco retornou em tempo portanto faz novo ciclo
    Endif
Else  '===========>>> Se o Flag_1 = 0 significa que o Eco ainda não chegou portanto volta a verificar
Goto verifica

Endif

contagem:

End_______________________________________________________________________________________________                                                
 
On Interrupt  'interrompe a rotina à cada 1 mS
Save System
 
If flag_1 = 1 Then
        Goto sair
Endif
conta = conta + 1
 
If PORTA.4 = 0 Then  'se recebeu o eco porta.4 vai de 1 para ZERO
flag_1 = 1
Goto verifica  'aqui ele tem que ir para esperando para verificar e já leva o valor de conta que se for igual a 10 alarma
Endif
 
If conta = 40 Then
flag_1 = 1
Goto verifica  'aqui conta chegou a 10 e portb = 1 mas portb.4 = 1 ==> ECO não chegou então tem que alarmar
Endif
 
sair:
TMR0 = 0x06
Resume___________________________________________________________________________________________                                             
              

Link para o comentário
Compartilhar em outros sites

@TcheCara,

Bom pode ser 2 coisas :

Pode ser que faltaram algumas instruções no programa, por exemplo pelo que eu ví dos exemplos, tem de fazer mesmo INTCON.T0IF = 0 antes de sair da interrupção.

Também parece que faltou o ALLDIGITAL para configurar o PIC para tudo modo digital.

Experimente compilar este aqui :

'SENSOR DE MOVIMENTO

'PIC 16F628A

Define CONF_WORD = 0x3f50

Define CLOCK_FREQUENCY = 4

AllDigital

TRISA = 0xff 'seta todas portas A como entrada

TRISB = 00000111b 'portas 0, 1 e 2 como entrada as demais saida

Dim conta As Byte

Dim tempo(4) As Byte

Dim x As Byte

Dim i As Byte

Dim medida(2) As Byte

Dim tolerancia1 As Byte

Dim tolerancia2 As Byte

PORTB.5 = 0

WaitMs 100 'Vamos esperar o sensor estabilizar e depois mandar o pulso

OPTION_REG.T0CS = 0 'USAR CLOCK INTERNO

OPTION_REG.PSA = 0 'PS2, PS1, PS0 CONFIGURADOS PARA PRESCALER = 4

OPTION_REG.PS2 = 0

OPTION_REG.PS1 = 0

OPTION_REG.PS0 = 1

TMR0 = 0x06 'CONTAGEM INICIAL DO TIMER0 EM 6

INTCON.T0IE = 1 'habilita timer0 interrupção

INTCON.GIE = 1 'habilitas todos interrupções un-masked

OPTION_REG.T0CS = 0 'definir fonte de relógio timer0 de instrução interna do relógio de ciclo

Enable

medida(0) = 0

medida(1) = 0

i = 0

ciclo:

conta = 0

flag_1 = 0

PORTB.5 = 1

WaitUs 10

PORTB.5 = 0

Goto contagem

verifica:

If flag_1 = 1 Then

If conta < 40 Then

PORTB.7 = 1

WaitMs 10

PORTB.7 = 0

Goto ciclo 'Eco não retornou no tempo previsto, alarma e retorna novo ciclo

Else

Goto ciclo 'Tudo ok eco retornou em tempo portanto faz novo ciclo

Endif

Else '===========>>> Se o Flag_1 = 0 significa que o Eco ainda não chegou portanto volta a verificar

Goto verifica

Endif

contagem:

end_______________________________________________________________________________________________

On Interrupt 'interrompe a rotina à cada 1 mS

Save System

If flag_1 = 1 Then

Goto sair

Endif

conta = conta + 1

If PORTA.4 = 0 Then 'se recebeu o eco porta.4 vai de 1 para ZERO

flag_1 = 1

Goto verifica 'aqui ele tem que ir para esperando para verificar e já leva o valor de conta que se for igual a 10 alarma

Endif

If conta = 40 Then

flag_1 = 1

Goto verifica 'aqui conta chegou a 10 e portb = 1 mas portb.4 = 1 ==> ECO não chegou então tem que alarmar

Endif

sair:

INTCON.T0IF = 0

TmR0= 0x06

resume___________________________________________________________________________________________

Se não der certo de novo, experimente tirar o SAVE SYSTEM e compilar novamente.

Por último, caso ainda não tenha funcionado, lembrei que esse PIC tem só uns 220 bytes de Ram. Pode ser que esse seja o problema também....

Está difícil de testar pois a versão demo que baixei só aceita 50 linhas de programa e não consigo compilar e testar ....

Paulo

Link para o comentário
Compartilhar em outros sites

Oi Paulo, pelos experimentos que fiz, Alldigital não influenciou em nada e sem o Save System não funciona nada e se colocar o Intcon.t0if = 0 também. Troquei  o pic pelo 16F648A que tem 256 bytes de ram também não resolveu. Resumindo só há incremento da variável na primeira passagem pela interrupção e ao sair dela e entrar em um novo ciclo congela no end.

Link para o comentário
Compartilhar em outros sites

@TcheCara

O problema é que o Save System guarda tudo no stack, e pode faltar Ram nesse caso. E sem ele, o programa corrompe os registradores.....

Eu mudei para os Avrs principalmente pela fartura de Ram. Este seu projeto roda fácilmente no Bascom e um Atmega qualquer.....

Mas não consigo te ajudar mais com os Pics, pois a versão demo que eu baixei só aceita até 50 linhas de programa, e não consigo compilar e testar....

Paulo

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...