- 3D-Druck Einstieg und Tipps         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: Empfängersignal mit ATtiny13A erkennen

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    23

    Empfängersignal mit ATtiny13A erkennen

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen!

    Bin neu hier in diesem Forum und auch Neuling auf dem Gebiet der AVR-Programmierung.

    Hoffe das ich hier mit meinem Anliegen richtig bin.

    Habe die Suche schon benutzt aber keine Antwort auf meine Frage gefunden mit der ich etwas anfangen konnte.

    So nun zu meinem Anliegen.

    Ich möchte das von einem RC-Empfänger ausgegebene PWM-Signal mit einem ATtiny13A (später auch mit dem ATtiny2313A) auswerten und bei entsprechendem Wert >= LED einschalten bzw. wenn der Wert einen bestimmten Schwellenwert wieder unterschreitet ausschalten. Das ganze möchte ich im AVR-Studio in C Programmieren.

    Wenn ich alles, was ich bisher finden konnte, richtig verstanden habe muss ich den Timer mit einem Prescaler von 8 laufen lassen und die steigende flanke messen, die fallende messen und dann den Wert der fallenden Flanke minus den Wert der steigenden Flanke rechnen. Soweit habe ich das auch verstanden, nur an der Umsetzung hapert es dann. Bitte berichtigt mich wenn das nicht stimmt!

    Über eure Hilfe bin ich sehr dankbar.

    Gruß Lichti01

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Willkommen im Forum,
    Ich würde einen PCINT (Pin Change Interrupt) verwenden. In der ISR prüfst du ob der Pegel high oder low ist und je nachdem setzt du den timer auf 0 oder ließt den Zählerstand aus.

    Als Pseudocode:

    Code:
    ISR (PCINT)
    {
    Wenn PIN == high
    {
    TCNT = 0
    }
    Sonst
    {
    Zähler = TCNT
    }
    Im main wertest du die Variable Zähler aus und reagierst dementsprechend. Zum Thema Timer, je nach Genauigkeit, die du haben willst, nimmst du einen 8 oder 16 bit Timer, der 8 bit zählt von 0 bis 255 und fängt wieder bei 0 an, der 16 bit Timer zählt bis 65535. Wie er zählt hangt von der Taktquelle und dem Prescaler ab. Die Frequenz mit der der Zähler um 1 weitererzählt ist Takt/Prescaler. Bei 8MHz und Prescaler von 1024 ergibt sich eine Frequenz f von ca. 7813Hz, mit der der Zähler weitererzählt (ca. Alle 128us). Du musst jetzt beachten das der Timer nicht überläuft bzw darauf achten und reagieren, aber auch das ein sinnvoller Zähler wert herauskommt

    Mfg Hannes

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    23
    Hi Hannes!

    Vielen Dank für deine schnelle Antwort!

    Werde versuchen das ganze umzusetzen und mich dann nochmal melden!

    MfG
    Lichti01

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    23
    So habe nun den ganzen Tag getüftelt hänge aber immer noch fest.

    Hier mal mein bisheriger Code:

    Code:
    #define F_CPU 1200000UL			//Taktfrequenz CPU 1,2MHz
    #include <avr/io.h>				
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    
    //LED-Ports
    #define LED1 1
    #define LED2 2
    #define LED3 3
    #define LED4 4
    
    #define C 0			//Variable für Zählerstand
    
    int main(void)
    {
    	
    	DDRB = 0b00011110;			//Eingänge und Ausgänge definieren
    	PORTB = 0b00000001;			//Pullups setzen
    	
    	//Einstellungen für PCINT	
    	MCUCR = (1<<ISC00);				//Jede logische Änderung an INT0 erzeugt eine Interrupt-Anforderung
    	GIMSK = (1<<PCIE);				//PCINT aktivieren
    	PCMSK = (1<<PCINT0);			//PCINT0 Eingang wird genutzt
    	
    	//Einstellungen Timer / PWM
    	TCCR0A = ((1<<WGM00) | (1<<WGM01));		//FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX)
    	TCCR0B = ((1<<CS00) | (1<<CS01));		        //Prescaler clk/64 (zählt in ca. 0,002s bis 219)
    
    	
    	sei();			//globale Interrupts aktivieren
    	
    	
    	while(1)
    		{
    
    		if(C >= 100)
    			{
    			PORTB |= ((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
    			}
    		else if (C <=100)
    			{
    			PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
    			}
    
    		}
    			
    }
    
    ISR(PCINT0_vect)
    
    {
    	if(PINB & (1<<PB0))		//erkennung steigender Flanke
    	{
    		TCNT0 = 0;
    	}
    	else					//sonst
    	{	
    		C = TCNT0;		//Zählerstand auslesen und in variable schreiben
    	}
    }
    Leider bekomme ich bei der Zeile "//Zählerstand auslesen und in Variable schreiben" noch den Fehler angezeigt: "lvalue required as left operand of assignment".

    Über Hilfe wäre ich wieder dankbar.
    Was natürlich auch gut zu wissen wäre ist, ob der Code ansonsten für mein Vorhaben richtig umgesetzt ist.

    LG
    Lichti01

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Du hast glaube ich C nicht richtig verstanden. Ein define ist dafür da bestimmte Werte einem Namen zu geben, als Beispiel z.b. Pi, das ist immer 3,1415. Jetzt kannst du in dem Programm jedes mal 3,1415 hinschreiben oder zuerst mit define definieren und anschließend nur mehr mit dem definierten Label (Pi) arbeiten. Bei den Leds hast du es richtig verwendet, bei der Zählervariable allerdings falsch, dort musst du schreiben wie groß der wert sein kann (signed bzw unsigned, char, int float,...). https://www.mikrocontroller.net/arti...R-GCC-Tutorial dort bei ganzzahlige datentypen (integer). Zuerst musst du wissen wie weit der TCNT zählen kann (beim längsten Impuls, also 2ms) und dementsprechend den Typ wählen (vermutlich unsigned char bzw unsigned int).

    MfG Hannes

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    23
    Ja da habe ich wohl etwas falsch verstanden!

    Habe nun meinen Code geändert. Im Testlauf habe ich mit einem Zweiten µC die PWM vom Empfänger simuliert und es funktioniert auch soweit.
    Die Tage geht es dann an den Test mit einem RC-Empfänger. Hoffe das das dann auch so reibungslos funktioniert wie mit dem zweiten µC.

    An dieser Stelle möchte ich mich bei dir auch noch für deine Hilfe bedanken! Finde es klasse, dass du mir nicht einfach den Code präsentiert hast. Somit habe ich doch einiges gelernt!

    Gruß
    Lichti01

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    23
    so nun habe ich den code mit verschiedenen Empfängern erfolglos getestet.

    Was ist falsch?

    Code:
    #define F_CPU 1200000UL     //Taktfrequenz CPU 1,2MHz
    #include <avr/io.h>				
    #include <util/delay.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    
    //LED-Ports
    #define LED1 1
    #define LED2 2
    #define LED3 3
    #define LED4 4
    
    uint16_t C;     //Integer einfügen und Variable für Zählerstand festlegen
    
    int main(void)
    {
    	
    	DDRB = 0b00011110;      //Eingänge und Ausgänge definieren
    	PORTB = 0b00000000;     //Pullups setzen
    	
    	//Einstellungen für PCINT	
    	MCUCR = (1<<ISC00);      //Jede logische Änderung an INT0 erzeugt eine Interrupt-Anforderung
    	GIMSK = (1<<PCIE);         //PCINT aktivieren
    	PCMSK = (1<<PCINT0);     //PCINT0 Eingang wird genutzt
    	
    	//Einstellungen Timer / PWM
    	TCCR0A = ((1<<WGM00) | (1<<WGM01));     //FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX)
    	TCCR0B = (1<<CS01);			//Prescaler clk/8
    
    	
    	sei();     //globale Interrupts aktivieren
    	
    	
    	while(1)
    		{
    
    		if (C < 80)
    			{
    				PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
    				sei();
    			}
    		
    		
    		else if((C > 80) & (C < 190))
    			{
    				PORTB &= ~((1<<LED2) | (1<<LED4));
    				PORTB |= (1<<LED1);
    				PORTB &= ~(1<<LED3);
    				_delay_ms(500);
    				PORTB |= (1<<LED3);
    				PORTB &= ~(1<<LED1);
    				sei();
    				_delay_ms(500);
    			}
    		
    
    		else if (C > 190)
    		
    			{
    				PORTB |= ((1<<LED2) | (1<<LED4));
    				PORTB |= (1<<LED1);
    				PORTB &= ~(1<<LED3);
    				_delay_ms(500);
    				PORTB |= (1<<LED3);
    				PORTB &= ~(1<<LED1);
    				sei();
    				_delay_ms(500);
    			}
    
    
    		}
    			
    }
    
    ISR(PCINT0_vect)
    
    {
    	if(PINB & (1<<PB0))     //erkennung steigender Flanke
    	{
    		TCNT0 = 0;
    	}
    	else     //ansonsten
    	{	
    		C = TCNT0;     //Zählerstand auslesen und in variable schreiben
    		cli();
    	}
    }
    Habe schon mit den Einstellungen am Sender gespielt hab verschiedene Prescaler / Integer ausprobiert. Was kann ich noch machen?

    Gruß
    Lichti01

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von vohopri
    Registriert seit
    11.09.2004
    Ort
    südlich der Alpen
    Beiträge
    1.708
    Servus,

    du hast die PWM simuliert, und es hat funktioniert. Da würde ich das Simulierte Signal und das Signal vom RC Empfänger vergleichen. Entweder mit einem Oszilloskop, oder als ich das noch nicht hatte, ging das mit einem Freeware Softwareoszi für den PC sehr gut.

    IMHO ist es sinnlos, im Code herum zu rühren, wenn man nicht weiss, was die Hardware macht. Auf Dauer ist das fürchterlich ineffizient.

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Warum schreibst du PORTB = 0b00000000; ? Portb ist beim einschalten automatisch 0x00 (steht im DB).

    Warum konfigurierst du 2 Interrupts, das ist vermutlich auch der Fehler. Du konfigurierst einmal INT0 und PCINT0, INT0 ist PB1 und PCINT0 ist PB0. Du reagierst aber nur auf den PCINT, ich vermute das du den Empfänger auf PB1 (INT0) angeschlossen hast. Eigentlich sollte es aber Warnungen geben wenn du es kompilierst. Warum schaltest du eigentlich die Interruptfreigabe aus?

    MfG Hannes

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    okay ich werf fragen hinterher, wozu einen WaveForm Modus?
    Code:
    //Einstellungen Timer / PWM
        TCCR0A = ((1<<WGM00) | (1<<WGM01));     //FastPWM (Top=0xFF Update of OCRx at = TOP TOV Flag Set on = MAX)
        TCCR0B = (1<<CS01);            //Prescaler clk/8
    lass TCCR0A einfach auf initial Zustand! Normaler Zählmodus, kein PWM das ist nutzlos!

    1.2MHz / 8 = 150kHz -> 8bit = 265 counts -> 1/150kHz * 256 = 1.70666 mS
    sollte alos für den maximal möglichen 1.5mS Puls reichen

    du initialisierst den Timer OHNE clockselect, du lässt CS einfach komtplett weg! Damit steht dein Timer!

    in der ISR, bei steigender Flanke, startest du den timer indem du die CS01 setzt

    bei fallender Flanke stoppst du den timer, indem du die CS Bits weider auf 0 setzt, prüfst du zuerst das TIFR Register ob das Overflow Bit gesetzt ist, löschst es (eine 1 auf das bit schreiben, keine 0) und verwirfst die Messung (Die High Phase war offensichtlich länger als 1.7mS)
    wenn das OVF Flag nicht gesetzt ist schreibst du den TCNT wert auf und verarbeitest die gemessenen zeit und setzt TCNT wieder auf 0

    so sparst du sogar in den low phasen noch strom weil dein timer nciht die ganze zeit sinnlos mitrennt
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. ATTiny13A Schalter abfragen/entprellung mit Variablen
    Von Denn Is im Forum C - Programmierung (GCC u.a.)
    Antworten: 19
    Letzter Beitrag: 01.07.2014, 12:21
  2. Attiny13a RS232
    Von flecralf im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 09.10.2013, 19:27
  3. Empfängersignal auswerten. (Modellbauempfänger PWM )
    Von hunni im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 13
    Letzter Beitrag: 16.10.2008, 01:04
  4. gcc erkennen?
    Von bluebrother im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 09.11.2005, 13:10
  5. Empfängersignal digitalisieren
    Von srem im Forum Elektronik
    Antworten: 5
    Letzter Beitrag: 14.02.2005, 21:31

Stichworte

Berechtigungen

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

12V Akku bauen