Forum: Mikrocontroller und Digitale Elektronik Garagentorsteuerung - Hörmannfunk nachrüsten


von mistake (Gast)


Angehängte Dateien:

Lesenswert?

Hilfe ich find das Problem nicht.

Es soll ein alter Torantrieb mit einem Funksenderset von Hörmann 
aufgerüstet werden. Das Problem ist, dass der Torantrieb für die Dauer 
des öffnen oder schließens 24VAC dauerhaft benötigt. Der Hörmann 
Empfänger liefert lediglich einen Impuls. Dafür habe ich die beigefügte 
Schaltung mit dem folgenden Code zusammengestellt. Die Platine ist 
geätzt und bestückt. Der Chip wurde laut AtmelStudio geflasht und 
verifiziert.
Irgendwie zeigt die Schaltung aber kein leben. Was mach ich falsch?

Bitte helft mir weiter.

Danke und Gruß

Mistake

Hier noch der Code
1
//----------------------start------------------------------------------
2
#ifndef F_CPU
3
#define F_CPU 1000000UL
4
#endif
5
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <util/delay.h>
9
10
/*
11
interrupt
12
int0 = PD2 = pin4 FB
13
int1 = PD3 = pin5 Lichtschranke
14
15
input
16
PB1 = pin15 endkontakt offen
17
PB2 = pin16 endkontakt zu
18
PB3 = schalter auf
19
PB4 = schalter zu
20
  
21
output
22
PC4 = pin27 impuls auf
23
PC5 = pin28 impuls zu
24
*/
25
26
int impuls=0; //stop=0 oeffnen=1 stop=2 schließen=3
27
//----------------------------------------------------------------
28
void wait(int mseconds)
29
{
30
  
31
  for (int i = 0; i < mseconds; ++i)
32
  _delay_ms(1); 
33
34
}
35
//----------------------------------------------------------------
36
void init(void)
37
{
38
  DDRC=0xff; //alle pins von portc als output
39
  DDRB=0x00; //alle pins von portb als input
40
  DDRD=0x00; //alle pins von portd als input
41
  //interne pull-ups deaktivieren
42
  //aktivieren mit 0xff
43
  PORTB = 0x00;
44
  PORTD = 0x00;
45
  //Datenrichtungsregister setzen:
46
  //Interrupt initialisieren:
47
  MCUCR|=(1<<ISC01)|(1<<ISC00); //Steigende Flanke löst aus
48
  GICR|=(1<<INT0)|(1<<INT1); // INT0 enable
49
  // Interrupt starten
50
  sei();
51
}
52
//----------------------------------------------------------------
53
//interrupt Fernbedienung
54
ISR(INT0_vect)
55
{
56
  GICR&=~(1<<INT0);
57
  sei();
58
  if(impuls < 3)
59
    ++impuls;
60
  else
61
    impuls=0;
62
  GICR|=(1<<INT0);
63
  sei();
64
}
65
//----------------------------------------------------------------
66
//interrupt Lichtschranke, Schleisskantensicherung, Motorüberlast
67
ISR(INT1_vect)
68
{
69
  GICR&=~(1<<INT1);
70
  sei();
71
  //evt. sofortiges oeffnen
72
  if(impuls==1)
73
    impuls=2;
74
  if(impuls ==3)
75
    impuls=0;
76
  GICR|=(1<<INT1);
77
  sei();
78
}
79
//----------------------------------------------------------------
80
int main(void)
81
{
82
  init();
83
  {
84
    //endschalter ist geoeffnet bei endlage
85
    //pruefe endlagenschalter offen
86
    if(PINB | ~(1<<PINB1))
87
      impuls=0;
88
89
    //endschalter ist geoeffnet bei endlage
90
    //pruefe endlagenschalter geschlossen
91
    if(PINB | ~(1<<PINB2))
92
      impuls=2;
93
94
    if(PINB & (1<<PINB3))
95
      impuls=1;
96
    
97
    if(PINB & (1<<PINB4))
98
      impuls=3;
99
      
100
    switch(impuls)
101
    {
102
103
      case 1://impuls=oeffnen
104
      PORTC |=  (1<<PC4);
105
      PORTC &= ~(1<<PC5);
106
      break;
107
108
      case 3://impuls=schließen
109
      PORTC &= ~(1<<PC4);
110
      PORTC |=  (1<<PC5);
111
      break;
112
113
      default:
114
      PINC=0x0;
115
      break;
116
    }
117
//    wait(50);
118
  }
119
  while(1);//Endlosschleife, die nichts macht
120
  return 0;
121
}
122
123
//-------------------------end---------------------------------------

von amateur (Gast)


Lesenswert?

1. Leg doch erst mal den Sender in die unterste Schublade. Ersetze ihn
   durch einen stinknormalen Taster. Das erleichtert Dir die Fehlersuche
   immens.
2. Warum zum Geier all die Unterbrechungen. Dein Programm hat doch
   praktisch nichts zu tun. Hauptbeschäftigung: Warte auf piep. Warte
   auf Schalter. Warte auf besseres Wetter…
3. Alles was dann kommt ist die Zustandssteuerung.
   Zu jedem Status gehören bestimmte Schalterstati und definierte
   Verzögerungen.
   Die einzig sinnvolle Unterbrechung währe aus meiner Sicht die
   Lichtschranke.
   Das einzig Trickreiche ist die Definition der einzelnen Stati.
Übrigens: Die Problemzerlegung erleichtert Dir vieles. Dazu ein 
einfaches Beispiel: Du schaltest die Anlage ein und der untere Schalter 
ist – warum auch immer (z.B. Stromausfall) – noch nicht geschlossen. Ein 
normaler, sequenzieller Ablauf bekommt in einem solchen Fall leicht 
Durchfall.
Ein weiterer Fall: Du öffnest das Tor; der obere Endschalter kommt aber 
nicht; die Lichtschranke wird brav viermal (Lichtschranke tief, Fahrzeug 
mit Doppelachsanhänger) unterbrochen. Eine Ablaufsteuerung lässt jetzt 
dein Tor bis zum St. Nimmerleinstag offen.
Natürlich kannst Du auch dreimal im Monat die Handkurbel bemühen. Wenn 
Du dich aber mal richtig in die Materie einarbeitest, so wirst Du 
folgendes feststellen: Den Ablauf zu definieren ist pipifax. Die 
Sonderfälle haben‘s in sich.
Also vergiss mal den spielerischen ersten Ansatz und grüble nochmal 
gründlich.

von mistake (Gast)


Lesenswert?

Das mit dem Taster hab ich schon probiert. Leider hat das auch keinen 
Rückschluß auf die Funktionalität gegeben.

Du hast recht, das mit dem Interrupt für die Fernbedienung kann auch 
anderst gelöst werden. Solange der µC kein leben zeigt brauche ich mir 
darüber aber kein Kopf zu machen.

ich habe auch direkt an den µc Beinchen gemessen ob sich da was ändert.

zu guter letzt habe ich eine einfach Schleife geschrieben, welche die 
beiden Relais für den Motor 10 sek Ein- und wieder Ausschaltet.

irgendwie passiert da garnix.
1
DDRC=0xff; //alle pins von portc als output
2
while(1)
3
{
4
  PORTC=0xff;
5
  wait(10000);
6
  PORTC=0x00;
7
  wait(10000);
8
}

Ich habe drei Vermutungen
1) irgendwas an meiner Schaltung stimmt nicht und ich blockiere den µC 
selber
2) der µC ist Defekt
3) der µC ist garnicht beschrieben worden

Geflasht wurde mit AtmelStudio6 & myavr light
Nach dem Schreiben wurde der Inhalt verifiziert durch AtmelStudio und 
mit OK bewertet. Aus diesem Grund gehe ich davon aus, dass 2 und 3 nicht 
zutreffen.
Nun die Frage, ob jemand einen Fehler in der Schaltung gefunden hat.

von amateur (Gast)


Lesenswert?

Wenn der Einheitstest nicht läuft, solltest Du mal folgende Sachen
überprüfen.
1. Oszi oder Frequenzzähler an einen der Pins und gucken ob das Teil
   "zu schnell ist".
2. Gucken ob Du nicht die Sicherungen falsch gesetzt hast. Z.B. einen
   ext. Quarz den es aber physikalisch nicht gibt.
3. In der Standartentwicklungsumgebung Studio ? gibt es im Flascher die
   Möglichkeit eines Verify.
4. Zumindest beim Studio 4, war das Programm, was den Flasher betrifft,
   sehr nachtragend. Beim Wechsel des Projektes (neu oder anderes) wird
   der Quellpfad der .Hex Datei nicht automatisch geändert. So kann es
   sein, das Du, wenn Du es nicht explizit überprüfst, dein vorheriges,
   z.B. für einen ATTiny geschriebenes Programm in die falsche Hardware
   schiebst.
5. Es ist zwar recht unwahrscheinlich, aber ist an Deinem Flasher die
   richtige Hardware angekommen?
Mit Flasher meine ich das Studio-Menü. Deine Hardware kenn‘ ich sowieso 
nicht.

von LCD (Gast)


Lesenswert?

Mit Sicherungen sind die Fuses des Prozessors gemeint.

Hier wird Dein Problem liegen?!

Geh ansonsten so vor wie "Amateur" es beschreibt.

von troll (Gast)


Lesenswert?

Ohne alles gelesen zu haben: sei() hat in einer ISR nichts verloren. 
Jede Abweichung von dieser Regel muss genau begründet werden.

von amateur (Gast)


Lesenswert?

@troll
Stimmt, sollte aber nicht das Problem sein, da ja sowieso an. Vor allem, 
wenn sein 08/15 Test nichts bringt. Sprich: Ohne überhaupt den Inder zu 
rupfen.

von LCD (Gast)


Lesenswert?

Wo liegen denn die Emitter deiner Treibertransistoren?

Die Pullups sollten aktiviert sein !

Miss doch mal mit Deinem Testprogramm an deren Basen.

von LCD (Gast)


Lesenswert?

Bevor mit Deinem Testprogramm nicht die Relais klackern vergiss alles 
Andere erst einmal!

von mis t. (mistake)


Lesenswert?

Zum Flashen benutze ich den mysmartusb light von myavr
http://shop.myavr.de/index.php?sp=article.sp.php&artID=200006

der wird im atmelstudio als stk500 verwendet.

im Studio hab ich die richtige .elf Datei angegben und es ist auch der 
atmega8 als Target eingestellt.

ich hab auch vorsichtshalber mal mit dem myavr eigenen Programm den µC 
ausgelesen um sicher zu gehen, dass überhaupt etwas geschriebn wurde.

Oszi oder Funktionszähler hab ich leider nicht zur Verfügung.

Das Verify wird automatisch nach dem Schreiben ausgeführt.
Hab es auch händisch noch mal gestartet. Es wird als OK bewertet.

------------------------------------
|Fuses|
------------------------------------
RSTDISBL = [ ]
WTDON = [ ]
SPIEN = [X]
EESAVE = [ ]
BOOTSZ = 1024W_0C00
BOOTRST = [ ]
CKOPT = [ ]
BODLEVEL = 2V7
BODEN = [ ]
SUT_CKSEL = INTRCOSC_1MHZ_6CK_64MS_DEFAULT

HIGH = 0xD9 (valid)
LOW = 0xE1 (valid)

---------------------------------------
Lock bits
---------------------------------------
LB = NO_LOCK
BLB0 = NO_LOCK
BLB1 = NO_LOCK

LOCKBIT = 0xFF (valid)

von mis t. (mistake)


Lesenswert?

ich dachte die internen Pullups braucht man nur, wenn man keine externen 
verbaut.

der sei() Aufruf in der isr soll verhindern, dass der isr rekursiv 
aufgerufen wird. aber diese Problematik stelle ich mal hinten an.

wie @LCD schon sagt, muss zuerst das Testprogramm die Relais zum 
klackern bringen, bevor ich irgendwas an dem Programm optimiere.
Die Emitter sind direkt an den GND angeschlossen.

von troll (Gast)


Lesenswert?

mis take schrieb:
> der sei() Aufruf in der isr soll verhindern, dass der isr rekursiv
> aufgerufen wird. aber diese Problematik stelle ich mal hinten an.
Du erreichst genau das Gegenteil von dem was du willst. Wenn beim AVR 
ein Interrupt ausgelöst wird wird automatisch das I-Flag im SREG 
gelöscht und mit dem reti (return from interrupt) aus der ISR wieder 
gesetzt. Mit dem sei() in der ISR setzt du diesen Mechanismus ausser 
Kraft, weil sei() ja die Interrupts global aktiviert/zulässt.

von mis t. (mistake)


Lesenswert?

@troll
okay dann hab ich da was missverstanden. Danke für den Hinweis, ich werd 
es bei gelegenheit aus den Routinen entfernen.

Hat mir jemand eine Alternative zum Oszi bzw. Frequenzzähler?
Evt. sind die Schaltzyklen doch so schnell, dass mein Multimeter das 
garnicht erfassen kann

von amateur (Gast)


Lesenswert?

Zum Flashen habe ich immer den AVRISP mkII oder das STK500 verwendet. 
Die stehen aber beide auf .HEX-Dateien.
Versuch doch mal die Sicherungen auszulesen. Nicht den Soll-Zustand 
anschauen sondern den Ist-.
Wie weit hast Du deine Schaltung überprüft? Ich kann's nur sehr schwer 
lesen - liegt wohl an meinem Bildschirm. Einfach mal nicht glauben 
sondern das Multidingsbums anschmeißen. Z.B. stimmt dein Reset oder so 
simple Sachen wie Betriebsspannungen?
Lass auf jeden Fall das minimal Programm drinnen oder spiel's nochmal 
Sam.

von mis t. (mistake)


Lesenswert?

Die Sicherungen / Fuses hab ich ein paar mal mit dem Studio ausgelesen. 
Es kommt immer das gleiche raus, was ich weiter oben geschrieben habe.



Nur um sochefr zu gehen. Das ist gerade mein komplettes Testprogramm, 
welches eigentlich die zwei Relais zum klackern bringen sollte

ich werde noch mal die HEX Dateien explizit in den µC Flashen.
1
void wait(int mseconds)
2
{
3
4
  for (int i = 0; i < mseconds; ++i)
5
  _delay_ms(1);
6
7
}
8
//----------------------------------------------------------------
9
10
11
int main(void)
12
{
13
  DDRC=0xff; //alle pins von portc als output
14
  while(1)
15
  {
16
    PORTC=0xff;
17
    wait(10000);
18
    PORTC=0x00;
19
    wait(10000);
20
  }  
21
}

von amateur (Gast)


Lesenswert?

Ich habe es überlesen: Für Signale ist ein DMM meist zu langsam. Die 
bügeln alles platt.
Wenn Du keinen flotten Heinrich gebrauchen kannst, spiegle doch einfach 
einen Port. Einen Pin/Port zum Eingang erklären. Ohne weitere 
Verarbeitung auf einem anderen Port/Pin ausgeben. Dann bestimmst Du die 
Geschwindigkeit.
Dann kannst Du mit Tastern oder Drahtbrücken spielen.

Z.B.
DDRC=0xff;
DDRB=0x00;

char Variable;

for (;;){
Variable=PINB;
PORTC=Variable;
}

Gibst Du jetzt auf Port B Pin 7 ein Signal, so sollte Port C Pin 7 
diesen Status spiegeln. Oder so. Small is beautiful.

So, jetzt geht's in die Heia.

von mis t. (mistake)


Lesenswert?

Mist ich glaub ich hab das Problem gefunden. Danke @amateur für deine 
Geduld. Beim Reset hab ich nen Fehler in der Schaltung. shame on me 
statt den Reset über den 10k Widerstand auf +5VDC zu setzten hab ich ihn 
versehentlich auf den GND gelegt. Werde das Morgen mal provisorisch auf 
der Platine umlöten. Das würde die ganze Situation erklären. Enn ich 
einen dauerhaften Reset hab, dann klackert auch nix. Kann der 10k auch 
weggelassen werden oder hab ich dann einen undefinierbaren Zustand oder 
gar andere Probleme?

von amateur (Gast)


Lesenswert?

Hätte ich Dein Schaltbild besser Lesen können, hätte ich Dich schon viel 
früher darauf angesprochen.
Ich würde die 10K drinnen lassen und zusätzlich noch einen kleinen Elko 
gegen Masse legen. Dadurch wird der Reset verzögert und kommt erst dann, 
wenn die Spannung(en) sich beruhigt haben.

von LCD (Gast)


Lesenswert?

Und zieh beim Test mal den ISP Stecker raus.
Wo geht denn Dein Pin 1 noch hin?
Ich kanns auf dem ipad auch schlecht erkennen.....

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

troll schrieb:
>> der sei() Aufruf in der isr soll verhindern, dass der isr rekursiv
>> aufgerufen wird. aber diese Problematik stelle ich mal hinten an.
> Du erreichst genau das Gegenteil von dem was du willst. Wenn beim AVR
> ein Interrupt ausgelöst wird wird automatisch das I-Flag im SREG
> gelöscht und mit dem reti (return from interrupt) aus der ISR wieder
> gesetzt. Mit dem sei() in der ISR setzt du diesen Mechanismus ausser
> Kraft, weil sei() ja die Interrupts global aktiviert/zulässt.

So ist es. Wenn du wirklich willst, das ein Interrupt von einem 
anderen unterbrochen werden darf, deklarierst du ihn als ISR_NOBLOCK:
1
ISR(ADC_vect, ISR_NOBLOCK)
2
{
3
// Der ADC Interrupt darf von einem anderen unterbrochen werden
4
}
So geht das, ohne alle Mechanismen des Compilers auszuhebeln. 
Normalerweise ist das alles nicht nötig, da die Hardware des AVR das 
schon recht elegant regelt.

von mis t. (mistake)


Lesenswert?

Vielen Dank für eure gemeinsame Hilfe.
Der Pullup vom Reset war schuld. Hab ihn jetzt provisorisch auf die 
+5VDC gelötet und auf einmal ziehen die zwei Relais alle 10 sek an wie 
im Testcase gewünscht.

Jetzt werde ich noch eure einwürfe mit den ISR Routinen beherzigen und 
dann mal an den Antrieb ran hängen.

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.