- 3D-Druck Einstieg und Tipps         
Seite 3 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 21 bis 30 von 36

Thema: Drehimpulsgeber

  1. #21
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Anzeige

    E-Bike
    Ja ok gern.
    Aber nicht lachen, der Code funktioniert bei beliebigen Geschwindigkeiten.

    Kurz zur Vorgeschichte: Dieser Code ist Teil eines Steuergerätes, das eine Unmenge an LEDs als Zimmerbeleuchtung steuern kann. Und zwar frei dimmbar von 0% auf 100%. Zudem gibt es zwei LED-Stromkreise, einen blauen und einen weißen. (Für romantisches und helles Licht) - Edit: Ich sehe gerade, den weißen Codeteil habe ich gestrichen, da ich für jemanden anderes nur die romantische Variante gebaut habe.

    Wenn man die Encoder drückt, dimmt er das Licht an oder aus. Und nur, wenn das Licht an ist, kann man mittels drehen die Helligkeit steuern. Dreht man über 100% oder 0% hinaus, so ertönt ein Geräusch.


    Achtung, unvollständig - Das Programm ist im kompletten sehr groß.

    Code:
    #define PIN_ENCODER  PINB
    
    // Blauer Encoder linker Kanal, rechter Kanal, Masse
    #define PIN_ENCODER_B_L 1
    #define PIN_ENCODER_B_GND 2
    #define PIN_ENCODER_B_R 3
    
    // Blauer Encoder Button
    #define PIN_ENCODER_B_BTN 0
    #define PIN_ENCODER_B_BTN_GND 4
    
    // Ausgang für den blauen Stromkreis
    #define PIN_PWM_B 3
    
    // Sind beide Kanäle auf '1'?
    #define ENC_B_BOTH (_BV(PIN_ENCODER_B_L) | _BV(PIN_ENCODER_B_R))
    // Ist der linke Kanäle auf '1'?
    #define ENC_B_LEFT  _BV(PIN_ENCODER_B_R)
    // Ist der rechte Kanäle auf '1'?
    #define ENC_B_RIGHT _BV(PIN_ENCODER_B_L)
    
    // Hilfsmakro
    #define FILTER_ENC_B (PIN_ENCODER & ENC_B_BOTH)
    
    #define PWM_CHANGE_VALUE 25
    
    // Aktueller Programmzustand
    #define MODE_OFF 0
    #define MODE_FADE_IN 1
    #define MODE_ON 3
    #define MODE_FADE_OUT 4
    
    SIGNAL (SIG_PCINT)
    { // BTN blue pressed
    	if (PIN_ENCODER & PIN_ENCODER_B_BTN)  // Nur bei LOW!
    		return;
    
    	if (blue_pwm_mode == MODE_FADE_IN || blue_pwm_mode == MODE_FADE_OUT)
    		return;
    
    	if (blue_pwm_mode == MODE_OFF)
    	{
    		blue_pwm_mode = MODE_FADE_IN;
    		pwm_fadewert_blue = 0;
    	}else{
    		blue_pwm_mode = MODE_FADE_OUT;
    		pwm_fadewert_blue = pwm_wert_blue;
    	}
    
    	pin_changed = 1;
    }
    
    
    int main(void) 
    {
    	uint8_t oldB;
    	uint8_t newB;
    	uint8_t peep_no;
    
    
    	unsigned int* rot;
    	rot = &OCR1A;
    
    	pins_init();
    	timer1_init();
    	sei();
    
    	_delay_ms(250);
    
    	peep_ack();
    	peep_ack();
    
    
    	oldB = FILTER_ENC_B;
    
    	while (1)
    	{
    
    		if (pin_changed)
    		{
    			pin_changed = 0;
    			peep_ack();
    		}
    
    		// MODE_ON heißt, die Lampen sind an
    		if (blue_pwm_mode == MODE_ON)
    		if (FILTER_ENC_B != oldB)
    		{
    			newB  = FILTER_ENC_B;
    			peep_no = 0;
    
    			if ((newB == ENC_B_BOTH) && (oldB == ENC_B_LEFT))
    			{
    				if (pwm_wert_blue >= PWM_CHANGE_VALUE+1)
    					pwm_wert_blue -= PWM_CHANGE_VALUE;
    				else
    					peep_no = 1;
    
    			}else if ((newB == ENC_B_BOTH) && (oldB == ENC_B_RIGHT)){
    				if (pwm_wert_blue < 255-PWM_CHANGE_VALUE+1)
    					pwm_wert_blue += PWM_CHANGE_VALUE;
    				else
    					peep_no = 1;
    
    			}else if ((newB == 0) && (oldB == ENC_B_RIGHT)){
    				if (pwm_wert_blue >= PWM_CHANGE_VALUE+1)
    					pwm_wert_blue -= PWM_CHANGE_VALUE;
    				else
    					peep_no = 1;
    
    			}else if ((newB == 0) && (oldB == ENC_B_LEFT)){
    				if (pwm_wert_blue < 255-PWM_CHANGE_VALUE+1)
    					pwm_wert_blue += PWM_CHANGE_VALUE;
    				else
    					peep_no = 1;
    			}
    
    			if (peep_no == 1)
    				peep_ack();
    
    			oldB = FILTER_ENC_B;
    		}
    
    	}
    }



    Falls es jemanden interessiert, hier ist der Part für die Software-PWM
    Code:
    SIGNAL (SIG_OUTPUT_COMPARE0A)
    {
    	static uint8_t pwm_counter;
    
    	pwm_counter++;
    	if (blue_pwm_mode == MODE_ON && pwm_wert_blue >= pwm_counter)
    	{
    		PORT_PWM |= _BV(PIN_PWM_B);
    	}else
    		if (blue_pwm_mode != MODE_OFF && blue_pwm_mode != MODE_ON && pwm_fadewert_blue >= pwm_counter)
    		{
    			PORT_PWM |= _BV(PIN_PWM_B);
    		}else
    			PORT_PWM &= ~_BV(PIN_PWM_B);
    
    
    	if (pwm_counter == 255)
    	{
    		if (blue_pwm_mode == MODE_FADE_IN)
    		{
    			pwm_fadewert_blue ++;	
    			if (pwm_fadewert_blue >= pwm_wert_blue)
    				blue_pwm_mode = MODE_ON;
    		} else if (blue_pwm_mode == MODE_FADE_OUT)
    		{
    			pwm_fadewert_blue --;	
    			if (pwm_fadewert_blue <= 1)
    				blue_pwm_mode = MODE_OFF;
    		}
    	}
    }

  2. #22
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Hallo thewulf00,

    ich bin jetzt zwar nicht ganz durch deinen Code durchgestiegen, aber ich glaube im Pirnzip ist der große Kern es das gleiche wie der Code von Nic.

    Kann es sein, das dein Code nur jede zweite Stellung des Encoders erkennt? (Ich kann es gerade mal wieder nicht testen)

    Viele Grüße
    Andreas

  3. #23
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Mein Code erkennt jede Stellung, deshalb ist er ja so "kompliziert".
    Der Code ist nicht so schwer.
    Im untersten Teil werden 4 Fälle abgebildet. Es fallen bei einem Drehimpuls immer zwei Kanaländerungen an. Nur die Reihenfolge dieser beiden Änderungen gibt Aufschluss über die Richtung. Deshalb frage ich auch nur einen der beiden Zustände ab. Aber ich vergleiche natürlich mit dem alten Zustand vor der Drehung, so dass ich auf jeden Fall quasi durch vergleichen alle acht Fälle abbilde.

  4. #24
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Ok, dann ist es wirklich das gleiche wie der Code von Nic. Ich bin aber heute wieder nicht zum probieren gekommen.

    Übrigens mein erster Code macht ja im Endeffekt auch was ähnliches, nur noch vieeeeel komplizierter wie deiner.

  5. #25
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    09.04.2008
    Beiträge
    384
    Warum wirden die INT0 und INT1 nicht verwendet ? Dafur ist doch eine ISR gedacht, um solche schnelle signalen zu verarbeiten. In meinen robby hang der drehgeber an INT0. In der ISR von INT0 wird dan der zweite kanal geprueft. Zaehlt 100% richtig. Der frequenz ist bei mir max 2000 Hz. Der INT0 wird activiert bei jede positive flanke.

  6. #26
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Hallo RP6conrad,

    ich stimme dir voll zu, normalerweise sind dafür die INT-Eingänge perfekt.

    Aber da ich mit diesen Drehimpulsgebern schon so oft auf die Schnauze gefallen bin, wollte ich dieses Thema endlich mal seperat behandeln und eine funktionierende Lösung erarbeiten, bei der ich auch sehe woran es liegen kann, wenn die Auswertung nicht geht. Und zwar ohne das ganze "außenrum", dass vielleicht wieder störenden Einfluß haben könnte.

    Ich finde das ist mir hier mit Hilfe der Leute im Forum perfekt gelungen. Der beste Lerneffekt ist doch, wenn man Fehler macht, diese ausbessert und auch noch weiß, warum der Fehler so aufgetreten ist. Genauso ist es hier passiert.

    Viele Grüße
    Andreas

  7. #27
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Ich habe bewusst auf Interrupts verzichtet, weil dann die Auswertung schwieriger ist. Du musst ja zwei Kanäle betrachten. Und allein der Zeitpunkt des Eintreffens entscheidet über die Wirkung. Sowas ist für mich eine typische "Hauptprogramm-Aufgabe" mit Schleifen.

  8. #28
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Aber das ist doch gerade der Vorteil von IRQ's. Die werden genau dann ausgeführt, wenn das Ereignis auftritt. In diesem Fall, wenn sich der Eingang ändert. Man verzichtet dann einfach auf die Schleife im Hauptprogramm und prüft in der IRQ-Routine am Start gleich den Status der beiden Spuren und kann damit seine Auswertung machen.

    Bei mics erstem Code könnte man dann quasi auf folgendes Verzichten:

    Code:
     while (1) 
          { 
    
             do // warten bis Bitwechsel erkannt wird 
             { 
                SpurA_akt = SpurA; 
                SpurB_akt = SpurB; 
    
             if (count > 0) 
             { 
                count--; 
                if (count == 0) 
                { 
                   Rechts0; 
                    Links0; 
                } 
             } 
             } 
            while ((SpurA_akt == SpurA_old) && (SpurB_akt == SpurB_old));
    und statt dessen in die IRQ-Routine nur folgendes schreiben:

    Code:
    		
             if (SpurA_akt == SpurA_old)   // Bitwechsel war bei Spur B 
             { 
                if (SpurA_akt) 
                { 
                   if (SpurB_akt) 
                   Links1; 
                else 
                   Rechts1; 
                } 
                else 
                { 
                   if (SpurB_akt) 
                   Rechts1; 
                else 
                   Links1; 
                } 
             } 
             else                     // Bitwechsel war bei Spur A 
             { 
                if (SpurB_akt) 
                { 
                   if (SpurA_akt) 
                   Rechts1; 
                else 
                   Links1; 
                } 
                else 
                { 
                   if (SpurA_akt) 
                   Links1; 
                else 
                   Rechts1; 
                } 
             } 
    
             SpurA_old = SpurA_akt; 
             SpurB_old = SpurB_akt;

  9. #29
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    08.07.2004
    Ort
    Südhessen
    Beiträge
    1.312
    Versuchs mal umzusetzen, dann reden wir weiter ;p

  10. #30
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Praktischerweise habe ich bei meinem Tiny ja die beiden INT Eingänge belegt. Ich werde es also mal versuchen.

Seite 3 von 4 ErsteErste 1234 LetzteLetzte

Berechtigungen

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

12V Akku bauen