Forum: Compiler & IDEs Beim Zustandwechsel an einem Pin eine Botschaft über UART rauschicken


von Hemi 8. (hemi850)


Lesenswert?

Hallo miteinander,

ich bin ein absoluter Anfänger, was die Mikrocontroller angeht.

Ich habe einen AtMega162 bei dem mit 8 Pins frei zur Verfügung stehen, 
die PA0 bis PA7.

Mein Problem:

Wie kriege ich das hin, dass ich beim Zustandswechsel, zum Beispiel am 
PA0 (von low auf high und dann von high auf low) eine Botschaft über 
UART1 rauschicken kann?

Vielen Dank im Voraus.

Grüsse
Hemi

von Stefan B. (stefan) Benutzerseite


Lesenswert?

PORTA als Eingang konfigurieren
UART1 als Sender konfigurieren
Endlosschleife:
  PINA abfragen
  auf Zustandswechselabfragen
  in die gewünschte Form umwandlen
  und per UART1 verschicken.

Wie das Abfragen konkret einzurichten ist, hängt einmal davon ab, wie 
schnell sich die Werte an PORTA ändern. Hast du da eine Vorstellung wie 
schnell/langsam das passiert?

Und zum zweiten wie sicher der Zustandswechsel ist, d.h. ob Prelleffekte 
vorkommen und eine Entprellung nötig ist. Bei Tastern sollte man immer 
mit Prellen rechnen. Wenn saubere Digitalsignale anliegen, eher nicht.

Das Senden hängt vom Datenaufkommen ab. Wenn zeitweise viel zu senden 
ist, lohnt es sich das Senden mit Interrupts und Puffern zu machen. Im 
Extremfall trennt man in eine Messzeit und eine Sendezeit und benutzt 
soviel Puffer wie das RAM hergibt. Dann hat man quasi einen 
Logikanalysator. Tja und das haben schon andere entwickelt - schau in 
die Codesammlung.

von Hemi 8. (hemi850)


Lesenswert?

Also das ist so eine Art Schalter.

Erklärung: Das Gerät ist dazu da um etwas ein- und auszuschalten, in dem 
es eine Botschaft schickt. Das Gerät hat eine eigene Stromversorgung. 
Wenn man die Zündung anmacht, liegt am PA0 eine Spannung von +12V an. 
Wenn es passiert ist, muss eine Botschaft rausgeschickt werden. Wenn die 
Zündung wieder ausgemacht wird, liegen am PA0 0V an. Wenn es passiert, 
wird eine andere Botschaft rausgeschickt.

Mehr macht das Ding nicht.

Kann man das evtl. in einem Interrupt realisieren, weil das 
Hauptprogramm schon ziemlich viel macht.

Danke & Grüsse
Hemi

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich hoffe die +12V liegen nicht direkt an PA0 an, denn dann haben die 
armen Schutzdioden viel zu tun, um die zu hohe Spannung vom µC 
fernzuhalten.

Es hat Vorteile, einen Hauptteil in einem Interrupt (oder Timer) zu 
programmieren. Du erhälst eine Nebenläufigkeit zum Hauptcode. Vom Platz 
her sprst du aber eher nichts. Und das langwierige Senden innerhalb des 
Interrupts wird als schlechter Stil betrachtet. Ändern von vorhandenem 
Interruptcode kann dazu führen, dass der Rest des Programmes soweit 
blockiert wird, dass Funktionsfehler auftreten.

Eine Älternative insbesondere ohne Quellcode bzw. ohne Eingriff in 
denselben wäre, mit einem zweiten (schwachbrüstigen und preiswerten) µC 
an der 12V Leitung zu spionieren und den eigentlichen AVR komplett in 
Ruhe zu lassen. Wie man die Botschaft dann auf die Sendeleitung gibt, 
hängt vom Rest des Gerätes ab.

von Hemi 8. (hemi850)


Lesenswert?

Doch, die +12V liegen direkt am PA0 an. Wie kann ich das besser lösen?

Hier habe ich gestern noch was zusammgengehackt:
1
DDRA &= ~( 1 << PA0 );  // PIN PA0 als Eingang definieren
2
  PORTA |= ( 1 << PA0 );  // PullUp Widerstand aktivieren.
3
  
4
  // Prüfen ob PA0 high ist, wenn ja, MK4 hochfahren:
5
6
  if ( PINA & (1<<PINA0) )
7
  {
8
    uart1_sendibus_EEP (mk4_startup_msg);
9
  }
10
11
  // Prüfen ob PA0 low ist, wenn ja, MK4 runterfahren:
12
13
  if ( !(PINA & (1<<PINA0)) )
14
  {
15
    uart1_sendibus_EEP (mk4_shutdown_msg);  
16
  }

Grüsse
Hemi

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ah, es geht um die BMW/MK4/Alextronic Geschichte. Ich hatte schon 
Bedenken, als du was von externem Gerät, Fernsteuern und Zündung 
geschrieben hast.

Die 12V würde ich mindestens mit einem Spannungsteiler runtersetzen 
auf die Betriebsspannung des AVR. Und da das Ganze an einem KFZ 
installiert wird, muss man damit rechnen, dass 12V ein nomineller Wert 
ist. Die tatsächliche Spannung kann beträchtlich davon abweichen. Eine 
Strombegrenzung (Sicherung) ist auch eine Überlegung wert.

Ideen zur Pegelanpassung gibt es bei Alextronic:
http://www.alextronic.de/bmw/projects_bmw_info_ibus.html#_2

Alles zusammen betrachtet, würde ich eine galvanische Trennung 
bevorzugen und das über einen Optokoppler (Vorwiderstand nicht 
vergessen!) lösen. Wenn das zu lahm ist, dann einen professionellen 
Pegelwandler IC benutzen (Melexis TH8080 LIN-Transceiver laut 
Alextronic).

Das Codestück sieht vernünftig aus. Den internen Pullup würde ich 
weglassen. Was soll der hochziehen, da sehe ich im Moment nichts. Und 
ich würde einer statischen oder globalen Variablen festhalten, ob die 
mk4_startup_msg bzw. mk4_shutdown_msg bereits gesendet wurden. Oder 
stört das den Empfänger nicht, wenn diese Nachricht öfters kommt?

von Hemi 8. (hemi850)


Lesenswert?

Ja, genau, es handelt sich um ein MK4-Projekt.

Die Hardware ist ein AtMega162 mit zwei TH3122 LIN Transceiver. Also 
bustechnisch ist alles okay und da brauche ich nichts mehr.

Auf der Platine habe ich noch 8 Ein- / Ausgänge, die ich beliebig 
verwenden kann und einen daon wollte ich zum Hoch- und Runterfahren 
verwenden. Was Elektronik und Mikrocontroller angeht, bin ich ein 
Anfänger. Kann nur C/C++ und tralala. Aber nichts mit der Hardware.

Die Variable werde ich natürlich auch verwenden, es stört zwar nicht, 
wenn die Botschaft mehrmals kommt, aber es muss nicht sein.

Hier leicht modifizierter Code:
1
int main ( void ) 
2
{
3
  
4
  bool switched_on = false;
5
6
  uart0_init (9600);
7
  uart1_init (9600);
8
9
  // Setzen der Einstellungen am Port 0:
10
11
  DDRA &= ~( 1 << PA0 );  // PIN PA0 als Eingang definieren
12
  
13
  // Prüfen ob PA0 high ist, wenn ja, MK4 hochfahren:
14
15
16
  while (1)
17
  {
18
    if ( (PINA & (1<<PINA0)) & (switched_on == false) )
19
    {
20
      uart1_sendibus_EEP (mk4_startup_msg);
21
      switched_on = true;
22
    }
23
24
    // Prüfen ob PA0 low ist, wenn ja, MK4 runterfahren:
25
26
    if ( (!(PINA & (1<<PINA0))) & (switched_on == true) )
27
    {
28
      uart1_sendibus_EEP (mk4_shutdown_msg);
29
      switched_on = false;  
30
    }
31
  }
32
  return 0;
33
}

Das mit Spannungsteiler sind gut aus, so werde ich es machen. Kannst Du 
mir sagen, auf wieviel Volt ich runter muss? Sind es diese 2,7V bis 
5,5V?

Grüsse
Hemi

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Im Datenblatt vom ATmega162 steht ab wo bis wohin LOW und HIGH 
garantiert erkannt werden. Der Spannungsteiler muss so dimensioniert 
werden, dass die HIGH/LOW Bereiche darin abgebildet werden.

AVR (typ.)
      Vin HIGH [V]  0,7*Vcc ... Vcc+0,5
      Vin LOW [V]   -0,5 ... 0,3*Vcc

IBUS
1     U high [V]    7 V ... Ubatt
2     U low  [V]    0 V ... 2 V

Angenommen der AVR läuft mit Vcc 5V, dann sind die Untergrenze Vin HIGH 
3,5V und die Obergrenze Vin LOW 1,5V. Sieht nach einer einfachen 
Halbierung der IBUS-Spannung mit zwei gleichen Widerständen aus.

Das Problem ist die maximale Eingangsspannung Ubatt. Da muss stärker 
reduziert werden (12V => max. 5,5V => Faktor X). Dadurch verschiebt sich 
aber 7V/X unter die 0,7*Vcc Bedingung von Vin HIGH. Das kann erkannt 
werden, wenn der AVR etwas toleranter ist oder wenn auf dem IBUS ein 
High-Pegel >7V (7,7V) liegt.

Jetzt könnte es sein, dass du daran denkst nicht mit einem IBUS Signal 
auf PA0 zu gehen sondern z.B. mit einem analogen "Zündung ein" Signal 
vom Zündschloss. Dann mach dir unbedingt Gedanken um die 
Strombegrenzung, Bedenke den Fall Ubatt >>12V und es sind Störspitzen 
auf der Leitung und überlege, ob ein Optokoppler nicht die bessere 
Lösung wäre.

von Hemi 8. (hemi850)


Lesenswert?

Die IBus Transceiver hängen direkt an den UARTs, die haben gar nichts 
mit den PA0-7 zu tun.

Die Botschaften werden ja über einen der beiden TH3122 Transceiver 
verschickt und empfangen.

Das, was ich will, ist einfach nur den Zustandswechsel mitzukriegen, 
wenn die Zündung an ist. Also genau das, was Du im letzten Abschnitt 
beschrieben hast. Der Optokoppler scheint wohl die bessere Alternative 
zu sein.

Grüsse
Hemi

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.