-         

Ergebnis 1 bis 10 von 10

Thema: 100 kHz-Clock mit ATMega (16MHz) noch verarbeitbar?

  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987

    100 kHz-Clock mit ATMega (16MHz) noch verarbeitbar?

    Anzeige

    Hi.

    Hab hier nen ATMega2560 auf 16MHz.
    Ich versuche gerade, Daten zu empfangen und Auszuwerten, die auf 3 Pins ankommen und mit 100 kHz auf einem Interrupt-Pin getaktet werden (digitaler Joystick)

    Rechnerisch heisst das ja, dass für jeden Interrupt dann nur 160 Zyklen zur Verfügung stehen.

    Die Tatsache, dass statt der erwarteten 48 Datenbits nur ca 20 ankommen, lässt mich vermuten, dass die 160 Zyklen aber nicht zu reichen scheinen.

    Hier der Code der ISR vom Interrupt 3; jeweils 3 Datenbits (Triplett) an PINA1-3 werden eingelesen, an js_inbits angehängt und das ganze dann 3 Bit nach links verschoben.

    Code:
    SIGNAL (SIG_INTERRUPT3)
    {
      js_inbits |= ((PINA & 0x0E) >> 1);
      js_inbits = (js_inbits << 3);
      js_bitcount++;
    }
    Gibts da noch irgendwelche Tricks oder reichen die 16MHz einfach nicht?

    mfg
    #ifndef MfG
    #define MfG

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.02.2006
    Ort
    3. Planet eines kleinen Sonnensystems in einem Seitenarm der Milchstraße
    Alter
    63
    Beiträge
    622
    Hallo,

    in Abhängigkeit von der Anzahl anderer Interrupts sollte das schon funktionieren! Wie sind denn Deine Variablen deklariert? Bei js_inbits (ich nehme an, diese Variable ist global und volatile -- aber wieviele Bits breit?) multiplizierst Du jeweils mit 8, diese Variable wird also schnell überlaufen; oder setzt Du sie in einem anderen Teil des Programs zurück, wenn sich js_bitcount verändert hat? Vielleicht kannst Du auch den Rest des Codes mal posten? Erkennst Du an js_bitcount, dass Du nicht genügend Daten erhältst?

    Gruß

    Fred

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Naja Rest des Codes wird schwierig, da es ausserhalb nur noch Debug-Funktionen gibt; also Daten per UART ein/ausgeben, Timer etc.

    Die js_inbits ist zwar global, aber nicht volatile. Typ ist ui64, also unsigned long long; Platz für 64 Bits; da nur 48 erwartet werden, würde mit einem Datensatz sowieso nichts überlaufen, v.a. da sowieso nicht alles ankommt.

    Als andere Interrupts gibts nur noch den Timer1 im Sekundentakt.
    #ifndef MfG
    #define MfG

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Bei 64 bit Zahlen ist das shiften relativ aufwendig. Das dürft der langsamste teil sein. Mit dem Hardware multiplizeirer könnte da sogar ein einfaches *8 schneller sein, je nachdem wie gut der Compilter ist. Besser wäre es natürlich das shiften der ganzen daten ganz zu vermeiden. Das würde z.B. gehen indem man jeweils nur 6 Bits je Byte nutzt und dann einen Pointer auf das gerade aktuelle Byte nimmt. Das würde dann auch nur 8 bytes für die 48 datenbits brauchen.

    Zur not müßte man die ISR routine in Asseembler schreiben, dann sollte es wohl noch reichen, auch mit dem ganzen Geschiebe. So lag ist die ISR ja bisher noch nicht.

    Auch wenn der/die Anderen Interrupts nur selten vorkommen kann ein Aufruf einern langsamen Routine alles aufhalten. Da muß man mit worst case Zeiten rechnen.

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.02.2006
    Ort
    3. Planet eines kleinen Sonnensystems in einem Seitenarm der Milchstraße
    Alter
    63
    Beiträge
    622
    Hi,

    Zitat Zitat von Jaecko
    Die js_inbits ist zwar global, aber nicht volatile. Typ ist ui64, also unsigned long long; Platz für 64 Bits; ...
    OK, Du setzt also das ganze Datenwort schon in der ISR zusammen. Das sehe ich wie Besserwessi: das Schieben durch 8 Bytes ist schon ziemlich zeitaufwendig, mit Assembler könnte es gehen.

    Du verwendest js_inbits auch innerhalb Deiner "main" oder innerhalb von Funktionen? Dann würde ich js_inbits auf jeden Fall volatile machen!

    Welchen Compiler benutzt Du? Hast Du Dir schon mal den entstandenen Assembler-Code angesehen und verschiedene Optimierungsstufen versucht?

    Gruß

    Fred

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Also ich habs mal mit der Möglichkeit versucht, die emfpangenen 3 Bit in der ISR einfach in ein Byte-Array zu werfen; in jeder ISR wird der Index um 1 erhöht. Da reicht die Zeit dann.
    Die Auswertung erfolgt dann, wenn alle Daten vorhanden sind.

    Compiler wäre AVR Studio + WinAVR.

    Noch ne Frage: Da ich die empfangenen Daten der Übersichtlichkeit halber später noch in nem Struct ablegen will:
    Gibts irgend ne Möglichkeit, Variablen mit ner bestimmten Anzahl Bits zu casten, die jetzt kein ganzzahliges Vielfaches von 8 sind?

    Also so, dass man z.B. einem Struct-Element, das nur 2 Bit lang ist, die ersten beiden Bits eines Bytes zuweisen kann, ohne dass durch die restlichen 6 Bit andere Elemente des Structs überschrieben werden?
    So im Stil von "wordvariable = (ui8_t) bytevariable", nur eben
    "struct.element = (ui2_t) bytevariable;"

    Wie müsste da der Typedef für ui2_t aussehen?
    #ifndef MfG
    #define MfG

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.02.2006
    Ort
    3. Planet eines kleinen Sonnensystems in einem Seitenarm der Milchstraße
    Alter
    63
    Beiträge
    622
    Hallo,

    ich hoffe, ich habe Deine Frage richtig verstanden. Hier ein Code-Beispiel unter Verwendung von Bitfields:

    Code:
    typedef struct {
        union{
            uint8_t byte;
            unsigned lower2bits: 2;
        };
    } w2b;
    
    w2b mybyte;
    mybyte.byte=128;       //0x80
    mybyte.lower2bits=7;   //0x07, aber nur die 2 LSBits (0x03) werden verwendet!
    Du hast hier also eine Union aus 8 Bits (mybyte.byte) und den 2 LSBits (mybyte.lower2bits). Im Beispiel setze ich mybyte.byte zunächst auf 128, dann setze ich die niedrigsten 2 Bits auf 0x7 -- da aber nur Bits 0 und 1 verändert werden sollen, verschwindet das Bit 2. Im Endergebnis erhält man für mybyte.byte also 0x83=131 .

    Gruß

    Fred

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Thx, genau so war die Frage.
    Da ich bei dem bisherigen Versuch (nur ne einfache Struct) das Problem hatte, dass dort eben im Speicher nachfolgende Elemente überschrieben wurden.
    #ifndef MfG
    #define MfG

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.02.2006
    Ort
    3. Planet eines kleinen Sonnensystems in einem Seitenarm der Milchstraße
    Alter
    63
    Beiträge
    622
    Hi,

    ein paar Vorsichtshinweise muss ich noch anhängen: Wenn Du nur mit einem Compiler arbeitest und weißt, wie der mit Bitfields umgeht, ist alles kein Problem. Beim Wechsel zu einem anderen Compiler und einem anderen Prozessor (anderer Hersteller), hast Du alle Kompatibilität verloren.

    Zudem ist es durchaus möglich, dass der Compiler sehr ineffizienten (=langsamen!) Code für die Bitfields generiert.

    Übrigens: Am besten Bitfields immer "unsigned" machen!

    Viel Erfolg mit Deinem Projekt!

    Fred

  10. #10
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Thxle nochmal für die Hinweise.
    Das mit dem Code hab ich gerade mal ausprobiert.
    Also Versuch 1: Bitfelder nur so gross, wie benötigt; Versuch 2: Bitfelder aufgerundet auf ganze Bytes/Word.
    Die Codegrösse beim 2. Versuch ist um 1092 Bytes kleiner als beim ersten.

    Hab den bisherigen Joystick-Teil auch mal hier als Code mit angehängt; ist für nen Microsoft Sidewinder Force Feedback Pro; evtl kanns ja jemand brauchen um nen Roboter anzusteuern.
    Was später noch kommt, ist auch ne Rückmeldung per Force Feedback. Elektrisch kein Problem; lediglich ein Steuerprotokoll fehlt mir noch.

    mit JS_SWFFP_Init() einfach 1x initialisieren; JS_SWFFP_GetData() fragt den Joystick ab und befördert die ausgewerteten Daten in die Struct js_ffb.

    joystick.c:
    Code:
    #include "joystick.h"
    
    void JS_SWFFP_GetData(void)
    {
      js_rectripindex = 0;              // Reset triples index
      JS_SWFFP_Trigger();               // Trigger joystick measurement
      while(js_rectripindex < 17);      // Wait until data has been received
    
      js_ffb.buttons = 0;               // Reset variables
      js_ffb.axis0 = 0;
      js_ffb.axis1 = 0;
      js_ffb.axis2 = 0;
      js_ffb.axis3 = 0;
      js_ffb.hat = 0;
    
      js_ffb.buttons |= ((~js_rectriplets[0] & 0x0E) >> 1);      // mask out buttons
      js_ffb.buttons |= ((~js_rectriplets[1] & 0x0E) << 2);
      js_ffb.buttons |= ((~js_rectriplets[2] & 0x0E) << 5);
      
      js_ffb.axis0 |= ((js_rectriplets[3] & 0x0E) >> 1);         // mask out axis 0 (X)
      js_ffb.axis0 |= ((js_rectriplets[4] & 0x0E) << 2);
      js_ffb.axis0 |= ((js_rectriplets[5] & 0x0E) << 5);
      js_ffb.axis0 |= ((js_rectriplets[6] & 0x02) << 8);
      
      js_ffb.axis1 |= ((js_rectriplets[6] & 0x0C) >> 2);         // mask out axis 1 (Y)
      js_ffb.axis1 |= ((js_rectriplets[7] & 0x0E) << 1);
      js_ffb.axis1 |= ((js_rectriplets[8] & 0x0E) << 4);
      js_ffb.axis1 |= ((js_rectriplets[9] & 0x06) << 7);
      
      js_ffb.axis2 |= ((js_rectriplets[9] & 0x08) >> 3);         // mask out axis 2 (Throttle)
      js_ffb.axis2 |= ((js_rectriplets[10] & 0x0E) >> 0);
      js_ffb.axis2 |= ((js_rectriplets[11] & 0x0E) << 3);
      js_ffb.axis2 = 127 - js_ffb.axis2;                         // invert axis 2 (Throttle)
      
      js_ffb.axis3 |= ((js_rectriplets[12] & 0x0E) >> 1);        // mask out axis 3 (Rudder)
      js_ffb.axis3 |= ((js_rectriplets[13] & 0x0E) << 2);
      
      js_ffb.hat |= ((js_rectriplets[14] & 0x0E) >> 1);          // mask out hat
      js_ffb.hat |= ((js_rectriplets[15] & 0x02) << 2);
    }
    
    void JS_SWFFP_Init(void)
    {
      EIMSK |=  (1 << INT3);                     // Enable INT3 (Pin D.3)
      EICRA |= ((1 << ISC31) | (1 << ISC30));    // Trigger: Rising edge
      js_rectripindex = 0;
    }
    
    void JS_SWFFP_DeInit(void)
    {
      EIMSK &= ~(1 << INT3);                     // Disable INT3 (Pin D.3)
      EICRA &= ~((1 << ISC31) | (1 << ISC30));   // Trigger: Disabled
      js_rectripindex = 0;
    }
    
    
    void JS_SWFFP_Trigger(void)
    {
      // Trigger measurement by generating a short pulse
      JS_PORT_TRIGGER |= (1 << JS_PIN_TRIGGER);
      _delay_us(50);
      JS_PORT_TRIGGER &= ~(1 << JS_PIN_TRIGGER);
    }
    
    
    SIGNAL (SIG_INTERRUPT3)
    {
      // Get triplets
      js_rectriplets[js_rectripindex] = (PINA & 0x0E);
      js_rectripindex++;
    }
    joystick.h:
    Code:
    #ifndef _JOYSTICK_H_
    #define _JOYSTICK_H_
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <string.h>
    #include <util/delay.h>
    #include "glob_type.h"
    
    /* Ports & Pins, where the data input lines are connected */
    #define JS_PORT_BIT1  PINA
    #define JS_PORT_BIT2  PINA
    #define JS_PORT_BIT3  PINA
    #define JS_PIN_BIT1   1     // Button 1
    #define JS_PIN_BIT2   2     // Button 2
    #define JS_PIN_BIT3   3     // Button 3
    
    /* Measurement trigger output */
    #define JS_PORT_TRIGGER PORTA
    #define JS_PIN_TRIGGER  4
    
    /* MIDI Tx; Not used yet; for implementing Force Feedback functionalities later via UART*/
    #define JS_PORT_FFB PORTA
    #define JS_PIN_FFB  5
    
    volatile ui8_t js_rectriplets[16];    // Array for triplet reception
    volatile ui8_t js_rectripindex;       // Triplet array index
    
    void JS_SWFFP_GetData(void);
    void JS_SWFFP_Trigger(void);
    void JS_SWFFP_DeInit(void);
    void JS_SWFFP_Init(void);
    
    
    /*
      Microsoft Sidewinder Force Feedback Pro
      Triplets: 16 (= Total 48 bits)
    	[00 - 08]: Buttons            ( 9 bits)
    	[09 - 18]: Axis 0 (X)         (10 bits)
    	[19 - 28]: Axis 1 (Y)         (10 bits)
    	[29 - 35]: Axis 2 (Throttle)  ( 7 bits)
    	[36 - 41]: Axis 3 (Rudder)    ( 6 bits)
    	[42 - 45]: Hat			          ( 4 bits)
    	     [46]: Always 1           (ignored)
    	     [47]: Parity             (ignored)
    */
    
    
    /* 
      No bit 'cutting' used in this struct; using a whole byte/word instead of needed number of bits
      saves about 1k flash memory.
    */
    typedef struct {
      ui16_t  buttons;
      ui16_t  axis0;     
      ui16_t  axis1;
      ui8_t   axis2;
      ui8_t   axis3;
      ui8_t   hat;
    } stc_js_swffp;
    
    
    /*
    
    typedef struct {
      union {
        elemente typ : bit;
      };
    } stc_name;
    
    */
    
    
    volatile stc_js_swffp js_ffb;
    
    #endif
    glob_types.h
    Code:
    #ifndef _GLOB_TYPE_H_
    #define _GLOB_TYPE_H_
    
    /* This header file contains global types */
    
    // Standard 
    typedef signed char           i8_t;
    typedef unsigned char        ui8_t;
    typedef short                i16_t;
    typedef unsigned short      ui16_t;
    typedef long                 i32_t;
    typedef unsigned long       ui32_t;
    typedef long long            i64_t;
    typedef unsigned long long  ui64_t;
    
    // Precise time
    typedef struct{
      ui8_t hour;
      ui8_t min;
      ui8_t sec;
      ui8_t msec;
    } stc_timeprec;
    
    // Standard time
    typedef struct{
      ui8_t hour;
      ui8_t min;
      ui8_t sec;
    } stc_timestd;
    
    // Standard date
    typedef struct{
      ui16_t year;
      ui8_t  month;
      ui8_t  day;
    } stc_date;
    
    // Timestamp
    typedef struct{
      stc_date      date;
      stc_timeprec  time;
    } stc_timestamp;
    
    // Item for Menu State Machine
    typedef struct{
      ui16_t s_current;
      ui16_t s_keyfunc;
      ui16_t s_next;
    } stc_menuitem;
    
    
    #endif
    #ifndef MfG
    #define MfG

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •