Forum: Mikrocontroller und Digitale Elektronik Ultraschallsensor AVR


von jan (Gast)


Lesenswert?

Hallo, Ich habe einen Ultraschallsensor aufgebaut. Das 
Ultraschallsendesignal wird bei jedem Timer overflow gesendet(geht 
auch). Wenn die Empfänger Kapsel Signal sieht zieht sie den INT0 auf 1 
(Es liegt eine 1 An ab dem Sendezeitpunkt bis kein Signal mehr gesehen 
wird, funktioniert ebenfalls) Der Interrupt darf nur auf die erste 
fallende Flanke reagieren und dann bis zum nächstem Senden nicht mehr 
auf Flanken reagieren. Je nachdem welche Zeit ermittelt wird sollen die 
LED's angesteuert werden.

out = PD2 die Ansteuerung für das Senden
Out = PB0-7 LED's
IN = PC2 High wenn Signal empfangen wird low bei keinem Signal.

Allerdings funktioniert das ganze nicht wirklich... vill. hat ja jemand 
eine Idee oder einen Verbesserungsvorschlag zu dem bestehendem Programm.
danke.


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define P_ENABLE_HIGH  PORTD |= (1<<PD2);
#define P_ENABLE_LOW  PORTD &= ~(1<<PD2);

#define INT0_ENABLE    EIMSK  |= (1<<INT0);
#define INT0_DISABLE  EIMSK  &= ~(1<<INT0);
#define true   1
#define false   0
volatile uint8_t Merker;
volatile unsigned char c;

ISR (INT0_vect)                      //Interrupt0
{

  c = TCNT0;

  if ( c < 15 )
  {
    PORTB   = 0b00000001;
  }
  else if ( c < 44 )
  {
    PORTB   = 0b00000011;
  }
  else if ( c < 76 )
  {
    PORTB   = 0b00000111;
  }
  else if ( c < 108 )
  {
    PORTB   = 0b00001111;
  }
  else if ( c < 140 )
  {
    PORTB   = 0b00011111;
  }
  else if ( c < 172 )
  {
    PORTB   = 0b00111111;
  }
  else if ( c < 204 )
  {
    PORTB   = 0b01111111;
  }
  else if ( c <= 255)
  {
    PORTB   = 0b11111111;
  }

}
ISR (TIMER0_OVF_vect)                  {
  Merker ^= true;                    }

int main (void)                 {
   DDRC  = 0b00000000;
  DDRD  = 0b00000100;
     DDRB    = 0b11111111;
     PORTB   = 0b00000000;
   EICRA  = 0b00000011;
         TCCR0A = 0;
  TCCR0B = 0b00000101;
  TIMSK0 = 0b00000001;
  Merker = 0;              sei();

  while(true)                 {
    wdt_reset();
    if (Merker == true)            {
    P_ENABLE_HIGH;

      INT0_DISABLE;
    }
    else                {
      P_ENABLE_LOW;
      if (TCNT0 > 5 && TCNT0 <128)               {
        INT0_ENABLE;
                            }
      else
      {
        INT0_DISABLE;              }
    }

   }
   return 0;                               }

von MWS (Gast)


Lesenswert?

Erstens, nimm Code-Tags, außerdem gewöhn' Dir die Binär-Schreibweise ab, 
die ist hier nicht angebracht.

Und ohne jetzt geschaut zu haben ob der Code überhaupt funktionieren 
kann, muss man beim (wieder-)erlauben von Interrupts darauf achten, dass 
man die in den entsprechenden Flag-Registern evtl. gesetzten Flags 
vorher löscht.

Sonst löst ein "gemerkter" Interrupt sofort zu dem Zeitpunkt aus, an dem 
er wieder erlaubt wird. Das kann die ganze Mechanik 
durcheinanderbringen.

von jan (Gast)


Lesenswert?

Hallo, in welchem register stehen denn werte des INT0 bei dem ATmega 48? 
( Int. bedingung erreicht)
in dem EIFR? mfg.

von Floh (Gast)


Lesenswert?

jan schrieb:
> Es liegt eine 1 An ab dem Sendezeitpunkt bis kein Signal mehr gesehen
> wird, funktioniert ebenfalls

Kannst du mal die Empfangsschaltung zeigen?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.