Xmega Timer Interrupt und Servoport

Lschreyer
Schreiberling
Avatar
Gender: n/a
Posts: 527
Registered: 02 / 2007
Subject:

Xmega Timer Interrupt und Servoport

 · 
Posted: 07.05.2014 - 20:09  ·  #1
Ich habe eine Problem mit einem Xmega128A4U.

Ich habe einen Servoport definiert,

Servoport = PortB, 0, iData;
ServoChans = 2, Positive;
ServoNeutral = 1.5, Timer_D0;
ServoSwing = 0.5;

Dazu nutze ich noch den Timer TCE0 um alle 5ms einen Interrupt aufzurufen:

TCE0PERL := $40;
TCE0PERH := $9C;
TCE0CTRLA := $03;
TCE0INTCTRLA := $02;

Alle 5ms wird so

Interrupt TCE0_INTOVF; aufgerufen

Das klappt auch, aber sobald ich in den Timer aktiviere spinnen die Servos, sie zittern heftig, fahren langsam auf eine Endstellung um dann schnell wieder zurück zu fahren. Ca. alle 5 Sekunden wiederholt sich das.

Ich habe alle möglichen Kombinationen von Timern hier schon probiert, ohne Erfolg.
Die Servos hängen an PB.0 und PB.1

Ich habe mal ein Minimalprogramm geschrieben, dass dieses Verhalten auslöst.

Es konfiguriert die Ports, setzt einen Timer in Gang und ruft im Interrupt ein paar Bytes über SPI_C ab. Das bringt die Servos schon durcheinander.
Schalte ich den Timer ab, stehen die Servos ruhig.
Ohne Timer kann ich über SPI soviel abrufen wie ich will, das beeinflusst die Servos nicht.

Code

program testxmega;

{$NOSHADOW}
Device = xmega128A4U, VCC=3.3;

Import SysTick, ServoPort, SPI_C;

Define
  OSCtype        = int32MHz, PLLmul=4, prescB=1, prescC=1;
  SysTick        = 10;             {msec}
  StackSize      = $0064, iData;
  FrameSize      = $0064, iData;
  ServoPort      = PortB, 0, iData; {use Portx, startbit n, RAMpage}
  ServoChans     = 2, positive;     {channel count, pulse polarity}
  ServoNeutral   = 1.5, Timer_D0;     {msec zero pulse width, Timer used}
  SPIorderC       = MSB;
  SPImodeC        = 0; //3;
  SPIprescC       = 3; // presc = 0..3 -> 4/16/64/128
  SPI_SSC         = none; // don’t use SS pin as chipselect

Implementation

{$IDATA}
var
   LED1[@PORTD, 5]      : Bit;
   MMA655X_CS[@PORTD, 2]      : Bit; // Anpassen!
   b1, b2: Byte;


function MMA655x_VALUE : Word;
var w1, temp       : word;
begin

  b1:= %00110000;
  b2:= %00001101;

  excl(MMA655X_CS);
  spioutbyteC(b1);
  spioutbyteC(b2);
  incl(MMA655X_CS);

  udelay(2);

  excl(MMA655X_CS);
  b1:= spiinoutbyteC($80);  // Dummy read, Adress 0 mit Parity Bit 7 gesetzt
  b2:= spiinoutbyteC(0);
  incl(MMA655X_CS);

  // Ein Word draus machen...
  temp:= word(b1);
  temp:= (temp shl 8) + word(b2);

  // Bits sortieren...
  w1:= (temp shl 2) AND $0FFF; //%0000111111111111;
  w1:= w1 OR word(b1 shr 6);
  return(w1);
end;




Interrupt TCE0_INTOVF;
begin
 toggle(led1);
 MMA655x_VALUE;
end;



{--------------------------------------------------------------}
{ Main Program }
{$IDATA}

begin

  DDRA:=  %11100000;    // 0= input, 1= Output
  PortA:= %00000000;    // 1 = Pullup!!  // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro

  DDRB:=  %00000011;    // 0= input, 1= Output
  PortB:= %00000000;    // 1 = Pullup!!  // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro

  DDRC:=  %11110000;    // 0= input, 1= Output
  PortC:= %00000000;    // 1 = Pullup!!  // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro

  DDRD:=  %00111111;   // 0= input, 1= Output
  PortD:= %00011110;   // 1 = Pullup!!  // Letzte 3 Bits sind Erkennung ob SD, Mini oder Micro

  // Timer setzen für 5 ms Overflow
  TCE0PERL := $40;
  TCE0PERH := $9C;
  TCE0CTRLA := $03;
  TCE0INTCTRLA := $02;
  
  EnableInts($87);
  
  loop
   nop;
   nop;
  endloop;

end testxmega.
rh
Administrator
Avatar
Gender:
Location: Germany
Age: 24
Homepage: e-lab.de
Posts: 5558
Registered: 03 / 2002
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 07.05.2014 - 21:06  ·  #2
mächtige Interrupt Service Routine und {$NoShadow} ??

rolf
golf
Benutzer
Avatar
Gender:
Location: Donauwörth
Age: 71
Posts: 256
Registered: 11 / 2009
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 08.05.2014 - 04:04  ·  #3
ich nutze bei sowas einfach eine word-variable, die in der loop hochzählt bis die 5 msec erreicht sind.

golf
Lschreyer
Schreiberling
Avatar
Gender: n/a
Posts: 527
Registered: 02 / 2007
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 08.05.2014 - 09:34  ·  #4
Noshadow ist laut Handbuch
"Bei non-Multitask Anwendungen werden bei allen Interrupts nur die durch die Interrupts benutzten Register gesichert. Dies
spart wesentlich Ram, Rom und Rechenzeit. "

Klingt für mich einleuchtend es dann auch zu nutzen.
Aber auch ohne ändert das nichts.

Das selbe läuft auf einem Mega1284P problemlos, da ist die Interruptroutine aber noch wesentlich größer (ich habe das obenstehende ganz erheblich eingekürzt), der Mega1284 läuft mit 10 MHz statt 32 MHz. Die gesamte Interruptroutine läuft da in 2,4 ms durch, ruft 3 Sensoren nacheinander über SPI ab, wertet die Daten aus und schreibt das Rechenergebnis in ein externes Flash (auch per SPI). Nebenher laufen diverse Funktionen, u. A. ein LCD-Modul über I2C, Serport usw. Trotzdem zittert da nichts.

Beim Xmega zucken die Servos sofort nach Aktivierung des Timers heftigst, fahren dann wieder in die Sollposition, und bewegen sich langsam davon weg um dann nach ca. 5 Sekunden wieder Ruckartig in die Sollposition zu fahren. Hier scheint der Timer des Servotreibers irgendwie beeinflusst zu werden.

Vielleicht hat ja jemand eine Idee was das sein könnte, da ich mit meinem Latein da langsam am Ende bin.


@golf: Das ist nicht wirklich der richtige Weg um genau 5ms Abstände zu bekommen. Dafür wurden Timer/Counter ja erfunden. Ich bin auf eine genaue Zeitbasis angewiesen, weil es hier um die Integration von Sensordaten geht, um daraus Beschleunigung und Geschwindigkeit zu berechnen.

Louis
miparo
Administrator
Avatar
Gender:
Location: Germany
Age: 58
Posts: 959
Registered: 09 / 2007
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 08.05.2014 - 14:03  ·  #5
Hallo Louis,
mit {$NOSHADOW} zerstört Dein INT diverse Register, wie man im ASM sieht.
Das geht natürlich nur Zufällig mal gut.
Zusätzlich würde ich

// XMEAG AU Types
FuseBits5 = [BODACT0, BodLevel0, BodLevel1, BodLevel2]; // 3,0 Volt
// XMEAG A Types without U
// FuseBits5 = [BODACT0, BodLevel0, BodLevel2]; // 2,9 Volt

beim Xmega setzten damit er kein komischen Sachen beim Start-Up macht.

miparo
Lschreyer
Schreiberling
Avatar
Gender: n/a
Posts: 527
Registered: 02 / 2007
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 08.05.2014 - 18:38  ·  #6
Mittlerweile habe ich im Forum gelesen, dass $Noshadow wörtlich das macht was im Handbuch steht, nämlich nur die durch den Interrupt benutzten Register, sonst nichts.

Ich habe also $Noshadow entfernt dann wie nach Handbuch {$NOSAVE} davor und am Anfang und Ende der Routine Pushallregs und Popallregs rein.
Dennoch fangen die Servos an zu fahren. Auch mit nur ein paar dummen Zeilen Code, die nur ein paar µs lang ein paar Zahlen rechnen passiert das.
Das ist schon seltsam, dieses Verhalten hatte ich bisher noch nie, und ich habe schon oft solche Dinge gemacht, eben alle mit dem alten Atmega.

Ich habe es jetzt umgangen, setze im Interrupt nur noch ein Bit, in der Programmschleife frage ich das ab und führe dann den Code aus, das läuft prima. Da stehen die Servos.

Louis
Thomas.AC
Benutzer
Avatar
Gender: n/a
Age: 43
Posts: 308
Registered: 07 / 2013
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 09.05.2014 - 12:47  ·  #7
bezüglich BODLEVEL muss man zwischen XMEGA A und XMEGA AU unterscheiden!
Die Levels sind laut datasheet/maual unterschiedlich.
miparos Einstellungen führen bei einem XMEGA ohne U zu einem BOD Level von 3.4V!


Siehe auch Atmel AVR1019: Migration from ATxmega128A1/64A1 to ATxmega1281U/64A1U
http://www.atmel.com/Images/doc8415.pdf

Gruß
Thomas.AC
miparo
Administrator
Avatar
Gender:
Location: Germany
Age: 58
Posts: 959
Registered: 09 / 2007
Subject:

Re: Xmega Timer Interrupt und Servoport

 · 
Posted: 09.05.2014 - 19:46  ·  #8
Hallo Thomas,
Danke,ist geändert.

Gruß
miparo
Selected quotes for multi-quoting:   0

Registered users in this topic

Currently no registered users in this section

The statistic shows who was online during the last 5 minutes. Updated every 90 seconds.
MySQL Queries: 15 · Cache Hits: 14   139   153 · Page-Gen-Time: 0.043213s · Memory Usage: 2 MB · GZIP: on · Viewport: SMXL-HiDPI