- Labornetzteil AliExpress         
Ergebnis 1 bis 7 von 7

Thema: PWM vom ADXL im Atmega8 auswerten über ICP1 (PB0)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    16.02.2005
    Ort
    Berlin
    Alter
    43
    Beiträge
    17

    PWM vom ADXL im Atmega8 auswerten über ICP1 (PB0)

    Anzeige

    Powerstation Test
    Hi,
    probier hier jetzt schon seit einer Weile mit einem Atmega8 auf einem STK500 und einem ADXl202 Beschleunigungssensor rum.
    die Analogen Signale die aus dem ADXl kommen konnte ich shcon auswerten, jetzt woltl ich mal probieren die PWM Signale die der ADXL ausgibt mir gilfe des Atmega8 auszuwerten, aber irgendwie klappt das alles nicht.
    Wahrscheinlich habe ich nur irgendwelche Register falsch gesetzt.
    so wie ich es der Beschreibung entnhemen konnte habe ich folgende Register gesetzt:

    DDRB = 0xff;
    PORTB = 0xff;
    DDRD = 0xff; //für die Ausgabe über LEDs
    PORTD = 0xff;

    ACSR = (1<<ACIC);


    TCCR1B |= (1<<WGM13); // fallende Flanke
    //TCCR1B = (1<<ICES1); // steigende Flanke

    while(TIFR & (1<<ICF1)); //warten bis das ICF1 Flag gesetzt
    wurde
    result= ICR1L; //lesen der Werte
    result1= ICR1H;

    if(result>>0 & 0x01) //ausgabe der WErte über
    LEDs
    PORTD &= ~(1<<PD0);
    if(result>>1 & 0x01)
    PORTD &= ~(1<<PD1);
    if(result>>2 & 0x01)
    PORTD &= ~(1<<PD2);
    if(result>>3 & 0x01)
    PORTD &= ~(1<<PD3);
    if(result>>4 & 0x01)
    PORTD &= ~(1<<PD4);
    if(result>>5 & 0x01)
    PORTD &= ~(1<<PD5);
    if(result>>6 & 0x01)
    PORTD &= ~(1<<PD6);
    if(result>>7 & 0x01)
    PORTD &= ~(1<<PD7);

    bin über jede hilfe dankbar

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    29.01.2004
    Beiträge
    2.441
    In Bascom Basic reicht zum Auslesen des digitalen Signals eines ADX eigentlich eine einzige Zeile.
    Z.B:
    Pulsein Adxlwert , Pinc , 4 , 0

    Ich weiss allerdings nicht so genau welche Sprache dein Codeschnipsel ist - sieht mir mehr nach C aus und dann hilft der Bascom Befehl leider nicht soviel.

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802

    Re: PWM vom ADXL im Atmega8 auswerten über ICP1 (PB0)

    Zitat Zitat von Grave80
    [...] die PWM Signale die der ADXL ausgibt mir gilfe des Atmega8 auszuwerten, aber irgendwie klappt das alles nicht.
    Wahrscheinlich habe ich nur irgendwelche Register falsch gesetzt.
    So ist es.

    Zitat Zitat von Grave80
    ACSR = (1<<ACIC);
    Zitat Zitat von ATMega8:199
    ACIC: Analog Comparator Input Capture Enable
    When written logic one, this bit enables the Input Capture function in Timer/Counter1 to be triggered by the Analog Comparator. The comparator output is in this case directly connected to the Input Capture front-end logic, making the comparator utilize the noise canceler and edge select features of the Timer/Counter1 Input Capture interrupt. When written logic zero, no connection between the Analog Comparator and the Input Capture function exists. To make the comparator trigger the Timer/Counter1 Input Capture interrupt, the TICIE1 bit in the Timer Interrupt Mask Register (TIMSK) must be set.
    Das ist nicht was du willst. Ich vermute mal, du willst dem ICP1 (PB0) als Eingang verwenden, und nicht den AIN0/AIN1 (PD6/PD7), den du zudem als Ausgang geschaltet hast.
    Zitat Zitat von --bugfix--
    ACSR &= ~_BV(ACIC);
    Der ICP1 (PB0) muss als Eingang geschaltet werden, nicht als Ausgang. Sonst schmort's im Mega8 oder im ADXL -- oder in beiden.
    Zitat Zitat von --bugfix--
    // ICP1 ist Eingang ...
    DDRB &= ~_BV(0);
    // ... mit Pullup
    PORTB &= ~_BV(0);
    // ... oder ohne Pullup
    PORTB |= _BV(0);
    Vor du den InputCapture musst du noch
    Zitat Zitat von --bugfix--
    // Timer1 stoppen, InCapt-Flanke wählen und Timer1 Reset
    TCCR1B = _BV(ICES1); // oder = 0;
    TCNT1 = 0;
    Zitat Zitat von --bugfix--
    // ICF1-Flag Reset
    TIFR |= _BV(ICF1);
    Zitat Zitat von --bugfix--
    // Timer1 starten
    //Timer 1 in Mode 0, prescale = 1
    TCCR1B |= _BV(CS10);
    Das alleine reicht für eine PWM-Auswertung aber noch nicht, es sind nur ein paar Bausteine, die du brauchen wirst. Am besten geht so was in einer ISR:
    Code:
    #include <avr/signal.h>
    #include <avr/interrupt.h>
    ...
    volatile uint8_t icr1_update = 0;
    
    uint16_t _icr1_hi, _icr1_low;
    uint16_t icr1_hi, icr1_low;
    ...
    
    {
    	...
    	TIMSK = _BV (TICIE1);
    	sei();
    
    	while (1)
    	{
    		while (0 == icr1_update)
    			;
    		cli();
    		icr1_hi  = _icr1_hi;
    		icr1_low = _icr1_low;
    		icr1_update = 0;
    		sei();
    		PORTD = icr1_low & 0x00ff;
    	}
    }
    
    SIGNAL (SIG_INPUT_CAPTURE1)
    {
    	TCNT1 = 0;
    	uint8_t tccr1b = TCCR1B;
    	
    	if (tccr1b & _BV(ICES1))
    		_icr1_low = ICR1;
    	else
    		_icr1_hi = ICR1;
    		
    	TCCR1B = tccr1b ^ _BV(ICES1);
    	
    	TIFR |= _BV(ICF1);
    	icr1_update	= 1;
    }
    Das nur als Vorschlag. Das ist ein ad-hoc-Code und nicht getestet.
    Disclaimer: none. Sue me.

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    16.02.2005
    Ort
    Berlin
    Alter
    43
    Beiträge
    17
    Hi Sprinter,

    danke für deine Antwort, eine Antwort kommt so spät weil ich etwas arg im stress war die letzten Tage, doch jetzt hab ich mich damit mal wieder beschäftigt.
    Habs jetzt erstmal soweit geschafft das überhaupt schon mal was flakert, kann ja den Code hier mal posten, auf das ihr mir vielleicht noch etwas unter die arme greifen könn/würdet wie auch immer.
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>
    
     
    
    int main(void)
    {
    
    int T1,T2;
    
    
    	DDRB &= ~(1<<PB0);
    	PORTB &= ~(1<<PB0);
    	DDRD = 0xff; //für die Ausgabe über LEDs
    	PORTD = 0xff;
    
    	while(1) 
    	{
    				//ACSR &= ~(1<<ACIC);
    			    //Zähler starten ohne vorteiler
    				TCCR1B = 0;
    				TCCR1B |= (1<<CS10);  
    			    TCCR1B |= (1<<ICES1);
    				 
    				TCCR1B |= (1<<ICNC1);			   
    				sei();
    			    TIMSK = (1<<TICIE1);  //Interrupt für ICP
    			    sei();  //einschalten für erste messung
    			    //nach der ersten flanke wird der timer gestartet
    			    //nach der zweiten Flanke ist die Periodendauer
    			                //ermittelt
    			    //es wird der gespeicherte wert aus dem ICR1
    			                //register zur berechnung verwendet
      				
    			   	while(TIFR & (1<<ICF1));
    			    TCCR1B = 0;  //Zähler stoppen
    				TCNT1= 0;
    				
    				
    				T1=T2=0;
    				T1 =  ICR1;
    				T2 =  ICR1H;  
    			    
    				TIFR &= ~(1<<ICF1);//	oder das hier beides
    			    TIMSK = 0;			// nach unten
    		
    
    		if(T1>>0 & 0x01)
    			PORTD &=  ~(1<<PD0);
    		if(T1>>1 & 0x01)
    			PORTD &=  ~(1<<PD1);
    		if(T1>>2 & 0x01)
    			PORTD &=  ~(1<<PD2);
    		if(T1>>3 & 0x01)
    			PORTD &=  ~(1<<PD3);
    		if(T1>>4 & 0x01)
    			PORTD &=  ~(1<<PD4);
    		if(T1>>5 & 0x01)
    			PORTD &=  ~(1<<PD5);
    		if(T1>>6 & 0x01)
    			PORTD &=  ~(1<<PD6);
    		if(T1>>7 & 0x01)
    			PORTD &=  ~(1<<PD7);
    			
    		}
    }
    mfG der Grave

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Wenn du ohne ISR arbeitest, dann wird irgendwann eine IRQ ausgelöst und du landest im Nirvana, genauer bei __bad_interrupt, was auf einen Soft-Reset angebildet wird.
    Wenn du sei() benutzt, musst du ISRs für alle IRQs zur Verfügung stellen, die auftreten können (hier: SIG_INPUT_CAPTURE1).

    Offenbar willst du aber erst mal ohne Interrupts arbeiten.
    Dann wirf das sei() raus und lass erst mal die Finger von TIMSK

    Bevor du auf das ICF1-Flag wartest, musst du es erst mal rücksetzen auf 0. Des geht, indem man eine 1 hinschreibt wie oben gesagt. Die anderen Flags werden nicht angefasst durch das 0-Schreiben.

    TIFR = _BV(ICF1);

    Danach wartest du:

    while (!(TIFR & _BV(ICF1))) // Flag==0 --> *schnarch*
    ...

    Dann wirst du die Flanke umschalten wollen, falls du nicht auf beide Flanken konfiguriert hast.
    Nach dem Flanken-Umschalt und vor dem nächsten Warten: wieder ICF1 resetten.
    Disclaimer: none. Sue me.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    16.02.2005
    Ort
    Berlin
    Alter
    43
    Beiträge
    17
    so habs das wochenden endlich mal alles zum laufen gebracht und funktioniert jetzt prima, danke für deine Hilfe

    mfg der Grave

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    25.01.2006
    Beiträge
    33
    Hat das Auswerten von PMW-Signalen einen Vorteil gegenüber den Werten der Analogausgänge?

Berechtigungen

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

12V Akku bauen