- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 60

Thema: Mehrere Servo-Signale einlesen, ggf. manipulieren, ausgeben

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    18.05.2007
    Ort
    Berlin
    Alter
    53
    Beiträge
    765
    Gibt es da irgendwo eine zuverlässige Übersicht?
    Wenn das Herz involviert ist, steht die Logik außen vor! \/

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    25.10.2010
    Beiträge
    26
    Euch allen erst mal Frohe Weihnachten.

    Hab nun endtlich das AVR Studio 4.19 zum laufen gebracht das 6er Atmel Studio ist mir einfach viel zu überladen.
    Ich denke über die Feiertage habe ich dann auch etwas Zeit mich näher damit zu befassen.
    Die letzten Tage waren Arbeits-Technisch etwas stressiger....

    Gruß Basti

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    25.10.2010
    Beiträge
    26
    In C spuckt er mir leider die selben Mist Werte wie im Bascom Prog aus. Also scheint irgendwas an meinem Prinzip völlig daneben zu gehen.

    main.c
    Code:
    #include <avr/io.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <avr/interrupt.h>
    #include <avr/pgmspace.h>
    #include <util/delay.h>
    
    #include "uart.h"
    #include "input.h"
    
    /* define CPU frequency in Mhz here if not defined in Makefile */
    #ifndef F_CPU
    #define F_CPU 16000000UL
    #endif
    
    /* 9600 baud */
    #define UART_BAUD_RATE      9600      
    
    
    int main(void)
    {
    
    
        //Uart initialisieren
        uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); 
    
    
        //Eingänge INT0 und INT1 initialisieren
        init_inputs();
    
    
        while(1)
        {
            char tmp[5];
            itoa(input_channel[3], tmp, 10); 
            uart_puts(tmp);
            uart_puts("\n");
            _delay_ms(50);
        }; //Endlosschleife
        
    }
    input.c
    Code:
    #include <avr/io.h>
    #include <stdint.h>
    #include <avr/interrupt.h>
    
    #include "input.h"
    
    // **************************
    //         Prototypen
    // **************************
    void init_inputs(void);//Initialisiert INT0 und INT1
    
    // **************************
    //         Deklarationen
    // **************************
    uint16_t (input_channel)[7]; //Array für die einzelnen Kanäle
    uint8_t (fail_flag); //Flag für Fail Safe Modus
    
    uint8_t (ch_cnt); //Counter für aktuellen Kanal
    
    
    void init_inputs(void)
    {
    
    
        //INT0 und INT1 als Eingang
        //DDRD = 0b11111001;
        DDRD &= ~((1 << DDD1) | (1 << DDD2));
    
        //INT0 und INT1 aktivieren
        GICR |= ((1 << INT0) | (1 << INT1));
    
        //Beide INT auf steigene Flanke konfigurieren
        MCUCR |= ((1 << ISC01) | (1 << ISC00)); //INT0
        MCUCR |= ((1 << ISC11) | (1 << ISC10)); //INT1
    
        //Timer1 Prescaler auf 1 stellen
        TCCR1B |= (1 << CS10);
    
        //Timer1 Overflow INT aktivieren
        TIMSK |= (1 << TOIE1);
    
        //Interrupts anschalten
        sei();
    };
    
    
    //ISR von INT0
    ISR(INT0_vect)
    {     
        //Wenn der CH != 0 dann speichere Zählerstand
        if(ch_cnt != 0){input_channel[ch_cnt] = TCNT1;}
    
        //Ch Zähler erhöhen
        ch_cnt++;
    
        //Zähler zurücksetzen
        TCNT1 = 0;
    
        //INT0 auf fallende Flanke
        if(ch_cnt == 6){MCUCR &= ~(1 << ISC00);}
    }
    
    
    //ISR von INT1
    ISR(INT1_vect)
    {
        //Wenn der CH != 0 dann speichere Zählerstand
        if(ch_cnt != 0){input_channel[ch_cnt] = TCNT1;}
    
        //Ch Zähler erhöhen
        ch_cnt++;
    
        //Zähler zurücksetzen
        TCNT1 = 0;
    
        //INT1 auf fallende Flanke
        if(ch_cnt == 6){MCUCR &= ~(1 << ISC10);}
    }
    
    
    //Timerüberlauf nach ~4ms, wenn nicht manuell zurückgesetzt wird
    ISR(TIMER1_OVF_vect)
    {
        //Kanalzähler zurücksetzen
        ch_cnt = 0; 
    
        //Beide INT auf steigene Flanke konfigurieren
        MCUCR |= ((1 << ISC01) | (1 << ISC00)); //INT0
        MCUCR |= ((1 << ISC11) | (1 << ISC10)); //INT1
    }
    Aus hTerm
    Code:
    ...
    ...
    ...
    9618<\n>
    9618<\n>
    9618<\n>
    9618<\n>
    9618<\n>
    9618<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    8837<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    6762<\n>
    -2320<\n>
    -2320<\n>
    -2320<\n>
    -2320<\n>
    -2320<\n>
    -2320<\n>
    -2320<\n>
    ...
    ...
    ...
    Ich versteh nur langsam nicht mehr so ganz wieso dieses Prinzip nicht funktioniert.
    Bei jedem INT den Zähler speichern und zurücksetzen.
    Beim letzten auf fallende Flanke, damit das Ende des letzten Puls erfasst wird.

    Die Pause nach den Pulsen ist dann größer als 4ms, sodass der Timer überläuft.
    Der setzt dann alles auf Anfang zurück. Die 4ms Pause ist quasi das Syncronistations Signal.

    Jemand ne Idee was ich falsch mache?

    Gruß Basti
    PS.: Schönen Feiertag noch

    EDIT:
    gerade festgestellt, für Ch1 passt es eigentlich. Da bringt er mir einen Wert zwischen etwa 18000 und 30000 Ticks des Timers.
    Nur die weiteren Ch haben dann falsche oder sogar negative Werte. Wie kann der Timer negativ Zählen?

    Das sind die 6Ch Daten die er mir ausspuckt....
    Code:
    23925 | -239 | 2331 | -14653 | 0 | 0<\n>
    Nur Ch1 verhält sich wie gewollt, äquivalent zum Knüpel der Fernbedienung, alle anderen springen ab und zu mal wild umher, aber nicht unbedingt auf Knüpelbewegungen.

    EDIT2:
    Weitere Erkenntnis, wenn ich beide Oszi Kanäle an die INTS halte und mir die Signale anschauen will, kommen die auch auf einmal korrekt an :-D scheinbar hängt der ganze scheiß irgendwie in der Luft und fängt sich Müll ein, sobal ich das aber - wenn auch nur minimal - mit dem Oszi belaste, haut's hin. Mal überlegen was ich da nun mache....

    EDIT3:
    Tatsache, die Ausgänge des Empfängers hingen bei Low Pegel völlig in der Luft. 10k gegen Masse und die Nummer läuft wie geschmiert.
    Is ja klar, das der mir nur Müll auswertet, wenn die INTs sich alles einfangen, nur nicht das richtige Signal :-D

    Aber aus lauter Trotz bleibe ich jetzt bei C, dann lern ich das auch endlich mal - bis dato noch NIE angefasst.
    Alles was oben steht habe ich mir in etwa 48h angelesen
    Geändert von Bomberpilot (27.12.2014 um 08:24 Uhr)

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.237
    Aber aus lauter Trotz bleibe ich jetzt bei C
    Ich denk mal, da machst Du sicher keinen Fehler.
    Eine der wichtigsten Erkenntnisse von C ist, das der Compiler von oben nach unten arbeitet.
    Nur das was oben definiert ist kann dein Programm darunter auch nutzen.
    Deshalb steht da auch die main Routine ganz unten.
    Wenn er mal ne Routine nicht findet, obwohl sie vorhanden ist, denk mal wie der Compiler und guck, ob die Routine vor der aufrufenden steht.
    Damit hatte ich Anfangs die meisten Probleme.

    Was mich persönlich bei C auch etwas nervt ist, das man für "Sonderfunktionen" immer erst die entsprechenden Includes im Programm machen muss.
    Also für Mathematische Funktionen, String Verarbeitung usw. müssen immer die entsprechenden Includes eingefügt werden.
    Aber C ist halt ein Baukasten, aus dem man sich halt nur nimmt, was man auch für seine Anwedung braucht.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    25.10.2010
    Beiträge
    26
    Zitat Zitat von wkrug Beitrag anzeigen
    Eine der wichtigsten Erkenntnisse von C ist, das der Compiler von oben nach unten arbeitet.
    Hat mich 8 Std gekostet bis ich das im Zusammenhang mit den Header Dateien komplett verstanden habe. Jetzt ist es Logisch und ich finde die Herangehensweise, jede C Datei als "eigenständig" kompilierbares Programm zu generieren auch nicht mal schlecht.

    Zitat Zitat von wkrug Beitrag anzeigen
    Deshalb steht da auch die main Routine ganz unten.
    Wenn ich das Richtig verstanden habe ist es egal, wo die main() steht, solange ich oben bzw. in der Header Datei die Funktionen als Prototyp definiert habe, oder nicht?

    Zitat Zitat von wkrug Beitrag anzeigen
    Was mich persönlich bei C auch etwas nervt ist, das man für "Sonderfunktionen" immer erst die entsprechenden Includes im Programm machen muss.
    Also für Mathematische Funktionen, String Verarbeitung usw. müssen immer die entsprechenden Includes eingefügt werden.
    Genau das schätze ich an C Kein byte zu viel Schrott im Code, sondern nur was auch Sinn macht.

    BTT:
    Also die Eingänge laufen jetzt, Jitter werde ich mir mal ansehen, denke aber das ein gleitender Mittelwert über 3 Werte da schon einiges rausholen kann.
    Die Frage ist, was ich nun mit den Ausgängen mache. Timer1 ist ja nun blockiert :-/

    Gruß Basti

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.237
    Die Frage ist, was ich nun mit den Ausgängen mache. Timer1 ist ja nun blockiert :-/
    Wenn Du den Timer nicht im CTC ( Clear Timer at Comparematch ) Mode laufen lässt, kannst Du problemlos auch die Impulsgenerierung darüber machen.
    Du gibst den Comparematch Interrupt frei und stellst Ihn auf das nächste Ereignis ein.
    Wie weit Du bei der Impulsgenerierung schon bist, kannst Du mit einer Zählvariable abspeichern.
    Guck mal den Code ein paar Post's weiter vorne von mir an und zwar den Abschnitt
    Code:
    // Timer 1 output compare A interrupt service routine 
    interrupt [TIM1_COMPA] void timer1_compa_isr(void)........
    Der Code ist für CodeVision, sollte aber auch mit ein paar Änderungen auf AVR GCC laufen.
    Elementar ist, das das TCNT1 Register nicht manipuliert werden darf, also keine Werte reinschreiben und kein CTC.
    Dann kannst Du, wenn Du lustig bist, sogar noch den Comparematch B für die Generierung einer weiteren Impulskette benutzen.
    Wenn Du die Variablen unsigned machst, sind auch Timer Überläufe kein Problem.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    25.10.2010
    Beiträge
    26
    Zitat Zitat von wkrug Beitrag anzeigen
    Dann kannst Du, wenn Du lustig bist, sogar noch den Comparematch B für die Generierung einer weiteren Impulskette benutzen..
    Danke, schau ich mir nochmal genauer an. Aber ich brauch keine Impulskette sondern wieder die 8 einzelnen Servo Signale sollen ja dann direkt die Servos dran.

    EDIT:
    Ich versteh das jetzt so:

    Also der Timer läuft einfach vor sich hin, kein Eingriff durch mich.
    Ich speicher die zeit beim beginn des Puls und beim Ende. Differenz ist dann die Dauer (aktuell Messe ich ja immer von 0 ab).
    Durch unsigned ist der Überlauf irrelevant.

    Wenn ich den Timer jetzt mit den ~4ms Überlauf so lasse, könnte ich bei jedem Überlauf einfach den Wert des nächsten Kanals in das Compare Register schreiben und den Ausgang high setzen. Und durch den Compare INT dann wieder auf LOW. Beim nächsten Timerüberlauf das gleich für den nächsten Kanal.

    Dann komme ich bei 6 Kanälen mit 4ms Paketdauer auf 24ms Dauer eines Signals für einen einzelnen Servo, statt der 20ms, denke das ist noch im vertretbaren Rahmen?

    Nur wie mache ich dann die Synchronistation auf CH1?
    Geändert von Bomberpilot (27.12.2014 um 09:48 Uhr)

Ähnliche Themen

  1. Mehrere RC Signale einlesen und mehrere Servos ausgeben
    Von R2D2 Bastler im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 74
    Letzter Beitrag: 10.01.2022, 08:35
  2. RC-Signal einlesen verändern und wieder ausgeben.
    Von DanielSan im Forum Arduino -Plattform
    Antworten: 1
    Letzter Beitrag: 21.03.2013, 11:58
  3. Atmel128 Spannungen einlesen und Ausgeben (Display3000)
    Von Gantenbein im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 31.08.2007, 21:41
  4. Mehrere Signale umschalten
    Von flexxo im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 25.02.2007, 13:56
  5. Servoimpulse einlesen und ausgeben
    Von moelski im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 21.08.2006, 07:24

Berechtigungen

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

LiFePO4 Speicher Test