XMEGA verliert Pin Status

Gast #4695829
Lesenswert?

Hallo alle zusammen,

an einem XMEGA 256A3BU stelle ich folgendes sehr merkwürdiges verhalten 
fest. An dem PORTF des XMEGA sind drei Hall-Sensoren angeschlossen. Ob 
die Sensoren betätigt sind oder nicht, stelle ich mit LEDs fest. Das 
komische ist, sobald ich einen Sensor anspreche, blitzen kurz auch die 
anderen LEDs an. Egal ob diese im Programm abgefragt werden oder nicht. 
Noch schlimmer ist, dass in einer while Schleife verblieben wird, 
solange ein Sensor betätigt ist. In dieser Schleife blinken die LED 
durch Timer Interrupt. Nun passiert aber folgendes, dass diese While 
Schleife sporadisch verlassen wird, wobei sichergestellt ist, dass die 
Sensoren betätigt sind. Das komische, dieses verhalten ist nur an PORTF 
festzustellen.
Kennt jemand diese Probleme?

Grüße Peter
Gast #4695873
Lesenswert?

also abgefragt wird mit

if (PORTF.IN & 0b00000100)
{
    PORTB.OUTSET = PIN5_BM;
}

parallel läuft ein Timer der eine weitere LED blinken lässt. das 
Komische ist auch, dass die Einabfrage mal früher mal später verlassen 
wird, wobei der Pin immer betätigt ist. Das sagt zumindest das Oszi und 
mein Finger am Sensor.
Gast #4695912
Lesenswert?

Habe jetzt nochmal ganz in ruhe meine Schaltung geprüft. Auf einem 
Eingang des XMEGA generiere ich ein Eingangssignal mit ca 1 kHz. Kann 
das sein, dass sich die Frequenz überlagert und im ungünstigen 
Augenblick meinen Eingang an PORTF als LOW erkennen lässt?

Wenn ja wie kann ich das verhindern? Internen PullUp an betroffen Pin 
aktivieren und gegen Masse einen Kondensator?
Gast #4695929
Lesenswert?

Hallo, schau mal, ob der C-Compiler einen Read-Modify-Write Sequenz 
erzeugt?
Wenn der vom Interrupt unterbrochen wird, und auf den Selben Port 
zugegrift wirds Äpfel und Bananen.

Also ich habe einiges schon mit den Xmegas gemacht, nie Probleme gehabt, 
sind klasse Teile. Besonders der 32E5.
Gast #4695946
Lesenswert?

Also am Code kann es nicht liegen. Habe den statt den Eingang an PORTF 
einfach mal durch eine anderen ersetzt und dann läuft das Programm 
normal durch. Nun wenn ich den PIN abfrage, neben welchem diese 1 KHZ 
Frequenz eingeht, gibt es Probleme, Also muss sich doch diese Frequenz 
da mit Übertragen?
Gast #4695956
Lesenswert?

Ganz geschmeidig ;)Also der Schaltplan ist quasi nicht vorhanden, da es 
ein XPLAIn Board ist. an das schliesse ich einfach paar tasten mit 
PULLDown 10K an und drei Hellsensoren. An diesen sind zwischen VCC und 
GND 100nF und zwischen OUT und VCC 10 K. Dazu liegt an den gleichen Eins 
ein zweiter AVR "Arduino" der einfach in 1 KHZ Takt einen Ausgang 
triggert.
Gast #4695962
Lesenswert?

Danke für die sehr hilfreichen Ratschläge. Wenn der Code mit Abfrage 
eines anderen PINS läuft, muss es doch an der Hardware liegen? Wie 
gesagt vermute ich eine Überlagerung der Frequenz. Gibt es denn 
Hardwaremittel um das zu verhindern?
Gast #4695970
Lesenswert?

Habe nochmal folgendes Aufgebaut. Ein Hallenser wird mit einem Magneten 
dauerhaft geschalten. Programm macht was es soll. Nun lege ich an dem 
zweiten Hallsensor mit einem Ringmagneten und einer Bohrmaschine ein 
wechselndes Signal an. Dieses Signal ist dem immer geschaltetem Sensor 
wirklich überlagert. Dann spinnt auch das Programm!
#4695983
Lesenswert?

Wenn du den ganzen Code postest dann sieht man vielleicht ob an andere 
Stelle was nicht passt.

Nur weil die eine Stelle geht heisst es nicht das der ganze Code passt.

Sicher das deine Abfrage alle passen ?

Bei
1
if (PORTF.IN & 0b00000100)
2
{
3
    PORTB.OUTSET = PIN5_BM;
4
}

kannst dich ja leicht um ne Null verschrieben haben.

Einfacher ist doch
1
if (PORTF.IN & PIN2_bm)
2
{
3
    PORTB.OUTSET = PIN5_BM;
4
}

Im Else Zweig löscht den Port wieder oder machst du das ein ner weiteren 
Abfrage.

Gruß JackFrost
Gast #4696000
Lesenswert?

Die Abfrage ist in einer While-Schleife. Solange gedrückt wird leuchtet 
es. Darum sehe ich auch das Flakern. Schreibstill mit 0b oder Pin2 
bringen beide den selben Fehler. Nur ein gänzlich anderer Pin läuft
Gast #4696068
Lesenswert?

> Habe den Code leider jetzt nicht mehr zu Hand

Du verschaukelst uns, oder?
Dann schreib jetzt nochmal den ganzen Code neu, teste ihn und fange 
nochmal ganz von Vorne mit vernünftigen Fragen an. Vernünftig Fragen 
beginnt mit Schaltplan und dem kompletten Code.
Gast #4696077
Lesenswert?

Nein ich verschaukel keinen. Möchte doch nur wissen ob sich solch ein 
Signal überlagern kann und wenn ich mit welchen Komponenten ich es 
unterdrücken kann. Das Programm läuft ja wenn ich statt dem Pin einen 
anderen Abfrage!
#4696362
Lesenswert?

Peter schrieb:
> Wenn der Code mit Abfrage
> eines anderen PINS läuft, muss es doch an der Hardware liegen?

Nö.
Solange man den Fehler nicht gefunden hat, ist ein SW-Fehler am 
warscheinlichsten.
Und insbesondere dann, wenn man den kompletten Code nicht zeigt.

Es kann aber nichts schaden, wenn man sich die Erratas im Datenblatt 
anschaut.
Z.B. der Attiny1634 hat nen ganz fiesen Bug, da geht Pin PB3 nicht als 
Eingang, solange der Watchdog nicht läuft.
Gast #4696440
Lesenswert?

1
 #define F_CPU 32000000UL
2

3
 #include <avr/io.h>
4
 #include <avr/interrupt.h>
5
 #include <util/delay.h>
6

7
volatile uint8_t Null = 0;
8

9
 ISR(PORTD_INT0_vect)
10
 {
11
   Null = 1;
12
 }
13

14
 void main()
15
 {
16
        // Takt auf extern 16 MHZ und PLL so dass 32 MHZ aktiv sind
17

18
  OSC_XOSCCTRL = OSC_XOSCSEL_XTAL_16KCLK_gc | OSC_FRQRANGE_12TO16_gc;
19
  OSC.CTRL = OSC_XOSCEN_bm;
20
  while(!(OSC.STATUS & OSC_XOSCRDY_bm));
21
  OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | 2;
22
  OSC.CTRL |= OSC_PLLEN_bm;
23
  while(!(OSC.STATUS & OSC_PLLRDY_bm));
24
  CCP = CCP_IOREG_gc;
25
  CLK.CTRL = CLK_SCLKSEL_PLL_gc;
26
  
27
  /*
28
  Ein und Ausgänge konfigurieren
29
  */
30
  PORTE.DIRSET = PIN4_bm;
31

32
  PORTF.DIRCLR = PIN2_bm;
33
  
34
  PMIC.CTRL = PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm |PMIC_LOLVLEN_bm;
35
  
36
  sei();
37
  while(1)
38
  {
39

40
   if (!(PORTF.IN & 0b00000100)) // Wenn einschalter gedrückt ausführen
41
   {
42
                 // Interrupt für Nulldurchgänge
43
     PORTD.INTCTRL = PORT_INT0LVL_HI_gc;
44
     PORTD.INT0MASK = 0b00000001;
45
     PORTD.PIN0CTRL = PORT_ISC_BOTHEDGES_gc;
46
    
47
     while (!(PORTF.IN & 0b00000100))
48
     {
49
      if (Null == 1)
50
      {
51
        Null = 0;
52
        _delay_ms(6);
53
        PORTE.OUTSET = PIN4_bm;
54
        _delay_ms(1);
55
        PORTE.OUTCLR = PIN4_bm;
56
      }
57

58
     }
59

60
     _delay_ms(1000);
61
     PORTE.OUTCLR = PIN4_bm;
62
     TCE0.CTRLA = TC_CLKSEL_OFF_gc;
63
     counter = 0;
64
     PORTD.INTCTRL = 0x00;
65
     PORTD.INT0MASK = 0b00000000;
66
   }
67
   if (PORTF.IN & 0b00000100)
68
   {
69
     update = 0;
70

71
     PORTE.OUTCLR = PIN4_bm;
72
     TCE0.CTRLA = TC_CLKSEL_OFF_gc;
73
     //TCF0.CTRLA = TC_CLKSEL_OFF_gc;
74
     counter = 0;
75
     PORTD.INTCTRL = 0x00;
76
     PORTD.INT0MASK = 0b00000000;
77
   }
78
   }
79
 }

hier der Code.

Die While Schleife "Solange taster nicht gedrückt (umgekehrte Logik da 
Hallsensor aktiv LOW ausgibt), wird in ungleichen Abständen verlassen. 
Wenn die Abfrage an einem anderen PORT als an PORTF gemacht wird, läuft 
es aber durch. So scheint es jedenfalls.
Gast #4696592
Lesenswert?

>  Möchte doch nur wissen ob sich solch ein Signal überlagern kann

Signale können sich überlagern. Ohne Schaltplan kann ich Dir keine 
Antwort geben, die in diesem konkreten Fall hilft.

> schliesse ich einfach paar tasten mit PULLDown 10K an

Das passt aber nicht zum Programmcode.

> if (!(PORTF.IN & 0b00000100)) // Wenn einschalter gedrückt ausführen

Hier wird etwas gemacht, wenn der Eingang auf LOW liegt. Wenn dein 
Taster in gedrücktem Zustand ein LOW liefert und du auch noch einen 
Pull-Down Widerstand parallel geschaltet hast, kann niemals ein HIGH 
anliegen.

Also: Schaltplan bitte!

Rücke den Quelltext anständig ein, so kann das ja keiner lesen.

Was mir spontan auffällt:

[code]
if (!(PORTF.IN & 0b00000100)) // Wenn einschalter gedrückt ausführen
{
    ...
    while (!(PORTF.IN & 0b00000100))
    {
    }
}
if (PORTF.IN & 0b00000100)
{
}

Du willst hier wohl irgendwas machen, wenn der Taster gedrückt wird und 
solange wiederholen, wie er gedrückt ist.

Taster prellen aber. Zwischen der if Abfrage und der while Schleife kann 
der Taster durchaus wieder in den "losgelassen" Zustand wechseln, so 
dass die while Schleife manchmal gar nicht ausgeführt wird.

Weiterhin kann es aus dem selben Grund passieren, dass weder der erste 
noch der zweite if Ausdruck wahr ist und es kann passieren, dass beide 
wahr sind.

Hast du das berücksichtigt?

> Noch schlimmer ist, dass in einer while Schleife verblieben wird,
> solange ein Sensor betätigt ist.

Naja, das st doch der Sinn von while(). Kann es sein, dass nicht einmal 
du Dir darüber im klaren bist, was wo angeschlossen ist und wann die 
Eingänge HIGH bzw. LOW sind?

Ich wundere mich auch sehr darüber, dass du hier mit Interrupts 
arbeitest. Dein Programm sieht ziemlich wirr aus. Wie soll es überhaupt 
funktionieren? Zeichne mal einen Programmablaufplan, zerlege es in 
Funktionen mit sprechenden Namen und benutze anständige Variablen-Namen. 
"Null" ist ein schlechter Witz.

Ich denke, wenn du die Struktur sauber hast und den Plan gezeichnet 
hast, wird Dir schon selbst auffallen, wo der Denkfehler ist. Wenn 
nicht, helfen wir dann auch gerne weiter.

> TCE0.CTRLA = TC_CLKSEL_OFF_gc;

Welche Funktion hat der Timer in deiner Anwendung und warum ist das der 
einzige Wert, den du bei unterschiedlichen Ereignissen wiederholt in 
dieses Register schreibst? Das kann so keine Sinnvolle Funktion haben!
Gast #4696655
Lesenswert?

Hallo, danke für die Antwort. Vieles im Programm ist vom Testen über 
geblieben. Daher auch sinnlose Variablennamen oder übrig geblieben 
Timer.

Das prellen der Taster ist mir bekannt. Hier sind Hallsensoren verbaut, 
die aktiv LOW liefern. Diese Prellen nicht!
#4696688
Lesenswert?

1
if (!(PORTF.IN & 0b00000100)) // Wenn einschalter gedrückt ausführen
2
   {
3
                 // Interrupt für Nulldurchgänge
4
     PORTD.INTCTRL = PORT_INT0LVL_HI_gc;
5
     PORTD.INT0MASK = 0b00000001;
6
     PORTD.PIN0CTRL = PORT_ISC_BOTHEDGES_gc;
7
    
8
     while (!(PORTF.IN & 0b00000100))
9
     {
10
      if (Null == 1)
11
      {
12
        Null = 0;
13
        _delay_ms(6);
14
        PORTE.OUTSET = PIN4_bm;
15
        _delay_ms(1);
16
        PORTE.OUTCLR = PIN4_bm;
17
      }
18

19
     }
20

21
    ...
22
   }

Ich geh mal davon aus das an PD0 der 1kHz Taktgeber sitzt, oder ? Du 
setzt die Variable bei jeder Flanke und damit ist das keine 
Nulldurchgangserkennung.


Du mischt 0x mit 0b und den "Definitions". Bleib doch bei einem

Den Intlvl kannst du doch auch einfach damit löschen :
1
PORTD.INTCTRL = TC_OVFINTLVL_OFF_gc


Vorallem sollte das reichen. Die Maske wegen dem INT0 Pin brauchst du 
dann nicht mehr ändern. Auch kannst du die PORTD.PIN0CTRL vor dein 
while(1) setzen.
1
if (Null == 1)
2
      {
3
        Null = 0;
4
        _delay_ms(6);
5
        PORTE.OUTSET = PIN4_bm;
6
        _delay_ms(1);
7
        PORTE.OUTCLR = PIN4_bm;
8
      }

Du setzt 0 Null auf 0 und wartest dann 6 ms und dann triggerst du den 
PE4 für eine ms ? Sind da deine LEDs dran , siehst du das oder willst du 
das nur mit dem Oszi sehen ?

Während der Wartezeit ist Null wieder 1 da die ISR bei 1kHz mindestens 6 
mal ausgelöst wurde. Dein Null=0 am Anfang bringt also nix. Wenn das 
Programm wieder bei if steht wird das ausgeführt und es ist nicht 
definiert wie der Zustand an deinem PD0 ist.

Du wartest dann noch eine Sekunde
1
_delay_ms(1000);

Und auch da wird Null wieder auf 1 gesetzt.

Die beiden
1
PORTE.OUTCLR = PIN4_bm;
weiter unten kannst du dir auch sparen , da der PE4 bereits 0 ist wenn 
du die while Schleife verlässt. Vermutlich wird das Compiler eh löschen.

Wie hast du denn die Hallsensoren an den PORTF gehängt ? Laut dem 
Schaltplan vom XPLAIN 256A3BU sind an PF die Taster, der Flash und der 
Qtouch aber da geht kein PIN von PF auf die Stiftleisten.

Peter schrieb:
> an das schliesse ich einfach paar tasten mit
> PULLDown 10K an und drei Hellsensoren. An diesen sind zwischen VCC und
> GND 100nF und zwischen OUT und VCC 10 K. Dazu liegt an den gleichen Eins
> ein zweiter AVR "Arduino" der einfach in 1 KHZ Takt einen Ausgang
> triggert.


Zeichne mal einen Plan das kann doch keiner mehr verstehen wie deine 
Hardware aufgebaut ist. Sind da nun Taster oder nicht ? Was meinst du 
mit an den gleichen PINs ist der Taktgeber ?

Gruß JackFrost
Gast #4696922
Lesenswert?

Bin gerade im Auto und kann leider nicht malen. Das Programm von vorhin 
passt nicht mehr zur gestrigen Beschreibung, da ich das mit der Frequenz 
ausschließen wollte. Habe nur noch mit 50Hz getriggert und dann den 
Hallsensor mit einem Magneten angesprochen. Laut Oszi ist das Signal 
dauerhaft auf Low, der Xmega verliert aber den Status. Der Fehler 
scheint weg zu sein, wenn ich nah an den bin einen Kondensator mit 4.7 
nF schalte.
Gast #4697001
Lesenswert?

Ich bilde mir auch ein, dass das Programm geht weil: wird ein anderer 
Pin abgefragt als der Hallsensor läuft alles ohne Probleme. Demnach muss 
der Hallsensor was einkoppeln. Und der Fehler kommt mal nach 5 min dann 
lange gar nicht mehr oder in kurzen Abständen hintereinander. Darum 
vermute ich halt dass die Hardware nicht ganz klappt. Der Hallsensor ist 
mit dem Ausgang direkt am Pin des Xmega inkl Pullup.
#4697052
Lesenswert?

Peter schrieb:
> Ich bilde mir auch ein, dass das Programm geht weil: wird ein anderer
> Pin abgefragt als der Hallsensor läuft alles ohne Probleme. Demnach muss
> der Hallsensor was einkoppeln. Und der Fehler kommt mal nach 5 min dann
> lange gar nicht mehr oder in kurzen Abständen hintereinander. Darum
> vermute ich halt dass die Hardware nicht ganz klappt. Der Hallsensor ist
> mit dem Ausgang direkt am Pin des Xmega inkl Pullup.

Du hast also an den Pin des XMEGA eine Pullup und die Flachbandleitung 
angelötet. An dem gleichen Pin an dem auf dem Board der Taster ist und 
ein 100 k Pullup ? Schonmal auf Zinnbrücken überprüft ?

Und wenn du einen x belobigen Pin abfragst obwohl de Hallsensor 
angeschlossen ist dann geht dein Program ? Wenn ja, dann liegt der 
Fehler in der Software.
Gast #4697067
Lesenswert?

Nein. Sorry blöd ausgedrückt. Habe ein weiteres Board gekauft wo ein 
Xmega mit randbeschaltung vorhanden ist aber keine Taster. Dann schließe 
ich einen Taster an mit 10k pullup und löte ein Flachbandkabel ca 20cm 
lang an. An dem Ende an Vcc und Gnd den Hallsensor und dann den dritten 
Pin über das Kabel an den Xmega. Dazu kommt nur ein pullup vom Ausgang 
des Sensors auf Vcc. Wenn ich nun das Programm laufen lasse und den 
Taster Abfrage läuft es richtig durch. Beim Abfragen des Hallsensor 
springt es in unterschiedlichen Abständen aus der while schleife. Die 
korrekte Funktion wird durch ein blinken einer LED angezeigt.
Gast #4697137
Lesenswert?

Hier der Anschluss von Sensor und Taster. Der Kondensator im 
gestricheltem Kästchen bewirkt dass das Programm scheinbar richtig 
läuft. Kann es nicht hundert pro sagen da es auch ohne mal länger mal 
kürzer läuft. Mit Kondensator jedoch bis jetzt ohne Aussetzer.
Angehängte Dateien:
Gast #4697245
Lesenswert?

Findet ihr noch grobe Fehlet im Code oder sollte es vom Prinzip so 
laufen? Mögliche Bugs oder Stolperstellen mit Atmel Studio 7 oder Xmega? 
Könnte mir sonst nur mit dem eingezeichneten Kondensator helfen oder die 
whileschleife eventuell erst verlassen wenn 10 ms hintereinander der Pin 
einen High Zustand hat? Dafür müsste man aber genau wissen dass der 
Fehler vom Hallsensor kommt. Warum sieht man nichts auf dem Oszi?
#4697261
Lesenswert?

Wir wissen nicht was da an Störungen bei dir herumläuft.
Mir hat in einem ähnlichen Fall folgendes geholfen:
Nimm ein 5adriges Flachbandkabel, Q in die Mitte. Die Leitungen links 
und rechts davon legst du nur auf der µC Seite auf GND. Für VCC und GND 
zum Sensor nimmst du die jeweils äußeren Adern.
Gast #4698019
Lesenswert?

Wenn deine Pull-Up Widerstände 10MΩ hätten oder deine Leitung 20m lang 
wäre, dann hätte ich Dir geschrieben, dass dein Problem kein Wunder ist.

Aber bei 10kΩ und 20cm ist ein kapazitives Übersprechen von einer 
Leitung zur Nächsten so gut wie ausgeschlossen. Es sei denn, der Ausgang 
vom Hall Sensor liefert keine sauberen Pegel.

Bei einer ungültigen Spannung zwischen HIGH und LOW genügen schon 
geringste Schwankungen, um einen Wechsel zwischen 1 und 0 auszulösen.

Mess da mal die Spannung nach. HIGH sollte >2V sein und Low sollte <0,7V 
sein. Wenn nicht, dann sind die Signale, die der Sensor liefert nicht zu 
deinem Mikrocontroller kompatibel. Dann kann man sicher mit einem 
Transistor oder CMOS Gatter nachhelfen.
Gast #4698083
Lesenswert?

Also der Sensor liefert exakt 3,3 Volt High und 0,1V Low. Werde die 
Randbeschaltung vom Sensor ein zweites Mal inkl Kondensator vom Ausgang 
auf Masse ein zweites Mal direkt vor den Controller bringen. Ich hoffe 
das Problem ist dann weg.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren