www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Fenster/Türkontakte auswerten


Autor: RN (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum,

ich möchte mit einem Mega8 Fenster und Türkontakte überwachen. Die Daten 
werden alle ca. 1 Sek. übertragen und in einem Programm ausgewertet.
Jetzt soll aber, wenn eine Tür/Fenster geöffnet wird die Meldung sofort 
kommen und nicht erst nach Durchlauf der Schleife.

Da ich in Sachen Microcontroller nicht allzu fit bin, bräuchte ich mal 
einen Denkanstoss. Ich denke, hier wäre ein Interrupt wohl angebracht, 
der bei Kontakt Betätigung die Schleife unterbricht und entsprechend 
sendet.
Tutorial Interrupt habe ich mir schon angesehen, doch sehe ich vor 
lauter Bäumen den Wald nicht.

Hier mal der bis jetzt funktionierende Code.

Schon mal Vielen Dank im voraus.

Gruß
RN
//--------------------------------------------------------------------
#define F_CPU 3686400
#include <avr\io.h>
#include <util/delay.h>
#define UART_BAUD_RATE 9600
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_CPU)/((UART_BAUD_RATE)*16L)-1)
//--------------------------------------------------------------------

// Zeichen zu Uart senden
void uartPutChar(char data)
{
    //warte bis Senden möglich
    while (!(UCSRA & (1<<UDRE)));
    //sende
    UDR = data;
}
//----------------------------------------------------------------------
// Zeichen sammeln
void print(char buffer[])
{
  for (int i=0;buffer[i]!=0;i++)
    uartPutChar(buffer[i]);
}
//------------------------------------------------------------------------
// Initialisierungen
//------------------------------------------------------------------------
void init()
{
   // Ports initialisieren
   //DDRC = 0x00; //alle Pins von Port C als Eingang 
  //PORTC = 0xff: // interne Pull-Ups an allen Port-Pins aktivieren 
  DDRC &= ~(1<<DDC0); // Pin PC0 als Eingang 
  PORTC |= (1<<PC0);  // internen Pull-Up an PC0 aktivieren 
  DDRC &= ~(1<<DDC1); // Pin PC1 als Eingang 
  PORTC |= (1<<PC1);  // internen Pull-Up an PC1 aktivieren 
  DDRC &= ~(1<<DDC2); // Pin PC2 als Eingang 
  PORTC |= (1<<PC2);  // internen Pull-Up an PC2 aktivieren 
  DDRC &= ~(1<<DDC3); // Pin PC3 als Eingang 
  PORTC |= (1<<PC3);  // internen Pull-Up an PC3 aktivieren 
  DDRC &= ~(1<<DDC4); // Pin PC4 als Eingang 
  PORTC |= (1<<PC4);  // internen Pull-Up an PC4 aktivieren 
  DDRC &= ~(1<<DDC5); // Pin PC5 als Eingang 
  PORTC |= (1<<PC5);  // internen Pull-Up an PC5 aktivieren 
   
   // UART initialisieren
   UCSRB |= (1<<TXEN);  // TX aktiveren
  UCSRC |= (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1
  // Baudrate setzen
   UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
  UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);
   
}

/////////////////////////////////////////////////////////////////////////////
// Main-Funktion
/////////////////////////////////////////////////////////////////////////////
int main(void)
{
   init();   // Initialisierungen
  while (1)    // Mainloop-Begin  
   {
     if (!(PINC &(1 << DDC0))) // Eingang 1 
    {
      print ("A1:1;");
    }
    else
    {
      print("A1:0;");
    }
    _delay_ms(1000);
    if (!(PINC &(1 << DDC1))) // Eingang 2
    {
      print ("A2:1;");
    }
    else
    {
      print("A2:0;");
    }
    _delay_ms(1000);
    if (!(PINC &(1 << DDC2))) // Eingang 3
    {
      print ("A3:1;");
    }
    else
    {
      print("A3:0;");
    }
    _delay_ms(1000);
    if (!(PINC &(1 << DDC3))) // Eingang 4
    {
      print ("A4:1;");
    }
    else
    {
      print("A4:0;");
    }
    _delay_ms(1000);
    if (!(PINC &(1 << DDC4))) // Eingang 5
    {
      print ("A5:1;");
    }
    else
    {
      print("A5:0;");
    }
    _delay_ms(1000);
     
  }
  
}

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Interrupt brauchst du dafür noch nicht.
Nimm einfach die Delays raus, die wenigen Abfragen laufen so schnell 
durch, dass die Daten fast in Echtzeit im Controller sind.
Da die Datenübertragung dann viel zu schnell läuft, hast du zwei 
Möglichkeiten: Entweder muss dein Programm die Übertragung erst 
anstoßen, d.h. es muss z.B. "START" senden und der Controller schiebt 
dann die Daten der Reihe nach raus. Oder du arbeitest mit einem Timer 
oder einfachem Zähler, der jede Sekunde die Schleife unterbricht und die 
Daten rausgibt.

Die Abfrage der Startbedingung kannst du auch in der Hauptschleife 
ständig laufen lassen, so verlierst du auch keine Abfrage.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:

> dann die Daten der Reihe nach raus. Oder du arbeitest mit einem Timer
> oder einfachem Zähler, der jede Sekunde die Schleife unterbricht und die
> Daten rausgibt.

Oder aber Mega8 meldet sich beim PC nur dann, wenn sich an einem Sensor 
eine Veränderung ergibt.

Fährt das Programm hoch, wird einmal der komplette aktuelle 
Sensorzustand übertragen und danach wird nur noch bei Änderungen 
reagiert. Ab und zu kann der PC wieder einen kompletten Zustand oder den 
Zustand einzelner Sensoren abfragen. Damit wird zum einen kontrolliert, 
ob die Verbindung noch da ist und zum anderen hat man die Sicherheit, 
dass der PC auch wirklich den aktuellen Stand hat.
Aber auf jeden Fall bleibt die Leitung dadurch soweit frei, dass der 
Mega bei einer Sensoränderung sofort losplärren kann.

> Da ich in Sachen Microcontroller nicht allzu fit bin, bräuchte
> ich mal einen Denkanstoss.

Der Denkanstoss sollte sein: Wenn du schnellstmögliche Reaktion willst, 
dann eleminiere erst einmal alle delay...

Autor: Martin Vogel (oldmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
So ganz versteh ich dein Problem nicht. Wieso alle Sekunden etwas 
übertragen, wenn sich sowieso nichts ändert ? Warum nicht nur bei einer 
Änderung etwas senden und den PC einen Zeitstempel dazu setzen ?
etwas so...
LOOP: In R16, Portx
      LDS R17, InByte ; Ablage gelesene Eigänge
      STS InByte, R16 ; neue Werte ablegen
      CP R16, R17     ; Vergleich
      BREQ LOOP       ; is nix ?
      RCALL Send_Action
      RJMP  LOOP

Send_Action: ....  ; was auch immer
             RET

So rotiert dein µC zwar fleißig, aber eine Info an den PC erfolgt nur 
bei einer Änderung. Dieses Ereignis kannst du im PC mit der Zeit 
versehen, wenn du bspw. dazu ein Empfangsprogramm geschrieben hast. Es 
geht auch, das du im Controler eine Zeit laufen läßt, diese stellst und 
dann zum Ereignis ein Telegramm baust, wo du einen Zeitstempel 
mitsendest.  Solange wie sich nix tut, brauchst du auch nix senden. Was 
soll auch die Info im Sekundentakt:" die Tür ist zu, die Tür ist zu, die 
Tür ist zu ...."
Gruß oldmax

Autor: Martin Vogel (oldmax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zu spät...

Autor: RN (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

"Der Denkanstoss sollte sein: Wenn du schnellstmögliche Reaktion willst,
dann eleminiere erst einmal alle delay..."

Das ist mir schon klar, nur müllt er mir dann die Schnittstelle zu.

"Wieso alle Sekunden etwas
übertragen, wenn sich sowieso nichts ändert ?"

Da ich dann weiß, dass noch alles funktioniert. Muss ja nicht alle Sek 
sein.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
RN schrieb:
> Hallo,
>
> "Der Denkanstoss sollte sein: Wenn du schnellstmögliche Reaktion willst,
> dann eleminiere erst einmal alle delay..."
>
> Das ist mir schon klar, nur müllt er mir dann die Schnittstelle zu.

Dann musst du das abstellen.
Daher dann sofort die nächste Frage: Warum müllt er mir die 
Schnittstelle zu. Antwort: Weil ständig Daten übertragen werden, die 
eigentlich eh keinen interessieren, weil sie sich nicht verändert haben.

> Da ich dann weiß, dass noch alles funktioniert. Muss ja nicht alle Sek
> sein.

Siehst du. Jetzt hast du den Dreh gefunden.
Und noch ein Tip. Um zu wissen, dass die Schnittstelle noch da ist und 
das Kabel nicht gerissen ist, muss man nicht alle Sensorzustände 
übertragen. Ein simples regelmässiges 'x' erfüllt den gleichen Zweck. 
Und das ist schnell übertragen.

Autor: icha (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hole Dir doch den kompletten Port auf einmal in ein Byte, vergleiche mit 
dem letzten (gespeicherten) Zustand und gibt dann eine Meldung aus, wenn 
sich was ändert. Das einen Timer, der die Abfrage alle x Zeitabstände 
macht und bei jeder y-ten ein "Alles OK" ausgibt, wenn keine Änderungen 
da sind.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.