- Labornetzteil AliExpress         
Ergebnis 1 bis 10 von 25

Thema: Immer wieder Servos...

Baum-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Neuer Benutzer Öfters hier Avatar von Radom
    Registriert seit
    18.12.2016
    Ort
    Raisting
    Beiträge
    11

    Immer wieder Servos...

    Hi an alle!

    Zur Zeit versuche ich eine Weichensteuerung für die Lego Eisenbahn meines Sohnes zu realisieren.

    Zur mir:
    - bin recht neu in Arduino/Microcontroller
    - lese gerade das AVR Lehrbuch von Roland Walter
    - hab mir das meiste Programmieren selbst beigebracht (ca. 8 Jahre beruflich VBA, 2x C++ Kurs)
    - Elektronik-Kenntnisse auch selbst beigebracht (Anfängerkenntnisse würde ich sagen)
    - mit dem Projekt und den Bauteilen beschäftige ich mich jetzt ca. seit 5 Monaten, immer mal wieder am Wochenende, oder wenn es sich Abends ausgeht

    Folgende Bauteile verwende ich:
    - Arduino UNO
    - MUX-Shield (1. Generation)
    - umgebautes PC-Netzteil als ext. Stromquelle (so ähnlich wie das hier http://www.kondensatorschaden.de/201...ntiernetzteil/ )
    - Servos "Tower Pro SG90" (also die http://www.micropik.com/PDF/SG90Servo.pdf)
    - Taster mit RC-Glied (10 k & 100nF)
    - Shift-Register 74HC595

    Jede Weiche hat einen Taster, dieser toggelt die Weiche. Für die Gerade Fahrt auf der Weiche brauche ich den Servo auf 45°, für die Abzweigung ganz links (0°).

    Das Programm ist ungefähr so aufgebaut (Code am Ende):
    # herzlichen Dank an Oberallgeier für die Lösung mit dem Timer PWM ! https://www.roboternetz.de/community...l=1#post577715
    (hoffentlich hab ich es richtig verstanden )

    - Timer 1 CompA
    → Prescaler 1:64
    → 4999 Ticks / n Servos um das 20ms Intervall für jeden Servo zu starten
    → setzt den Ausgang des Registers des aktuellen Servos auf 1
    → prüft auf Tastendruck
    →→ wenn gedrückt, führe Funktion aus und setzt die Shift-Register der LEDs neu
    (so gelöst damit die LEDs nicht flackern und dass TIMER 1 so wenig wie möglich gestört wird)
    → setzt den Wert für Timer 1 CompB

    - Timer 1 CompB
    → sendet eine 0 an die Register und schaltet so das Servosignal ab


    Im Grunde funktioniert es, ABER
    - anders als im Datenblatt des Servos fahren die Servos nur auf die
    → linkeste Position, wenn die Pulsweite ~ 0,6 ms ist
    → 45° Position, wenn die Pulsweite ~ 1 ms ist
    - manche Servos fahren spiegelverkehrt ( 0 = 180 und die Bewegung ist auch gespiegelt )
    - der Puls ab dem 2. Schieberegister zappelt am Ende
    → Register 1: schönes Rechteck-Signal
    → Register 2: steigende Flanke sauber, das Zappeln beginnt ab dem eigentlichen Ende des Signals (z.B. 1ms) und verlängert das Signal um ca. 0,75 ms

    Edit: irgendwo habe ich gelesen dass ein Servo ca. 1 A Strom braucht, wenn 12 Servos am Netzteil hängen, zeigt das Multimeter aber nur ~350 mA an - ist da was falsch ?

    Und mir gehen jetzt die Ideen und Suchbegriffe aus um eine Lösung zu finden...


    Hat jemand Lust sich das anzusehen und mir vielleicht Tipps zu geben?


    PS: im Code habe ich 18 Weichen eingestellt, da ja (aktuell) die Pulsweite für die benötigten 45° nur 1ms sein muss (die Bahn hat auch 18 Weichen, das passt halt auch zu gut )
    In den Versuchen macht es keinen Unterschied ob ich max. 18 oder max 10 einstelle.



    Code:
    //  Define *********************************************************************************************************************
    #define CONTROL0  6   // 5    //MUX control pin 0 (S3 is connected to Arduino pin 2)
    #define CONTROL1  5   //4
    #define CONTROL2  4   //3
    #define CONTROL3  3   //2
    /*  --> das Shield wurde um einen Pin nach oben verschoben, um den Pin 2 fuer die Interrupt der Taster zu
     *      verwenden !!   
     *      
     *      !! ALT !! -> Interrupt mit Taster sind nicht empfohlen, wegen Prellen
     *                -> meine Schaltungs-/Softwareversuche haben das bestaetigt...
     */
    
    #define MUX0   14     //^= Analog 0
    #define MUX1   15     //^= Analog 1
    #define MUX2   16     //^= Analog 2
    
    
    //  Variablen / Konstanten *****************************************************************************************************
    //  1. konstante Vorgaben
    const int PIN_TMR_INI_OK      = 1;    //Kontroll-LED für erfolgreiche Timer-Initialisierung
    const int PIN_TMR_INI_NOK     = 13;   //Kontroll-LED für fehlgeschlagene Timer-Initialisierung -> wenn ocr1a < ocr1b ist !!
    
    const int PIN_TAKT_SRV       = 7;     //Takteingang              ( SH_CP )
    const int PIN_SPEICHER_SRV   = 8;     //Speicher-Sendung         ( ST_CP )
    const int PIN_DATEN_SRV      = 9;     //Pin für den Binär-Wert   ( DS )
    
    const int PIN_TAKT_LED      = 10;     //Takteingang              ( SH_CP )
    const int PIN_SPEICHER_LED  = 11;     //Speicher-Sendung         ( ST_CP )
    const int PIN_DATEN_LED     = 12;     //Pin für den Binär-Wert   ( DS )
    
    const int TICKS_ABZW       = 150;     //Weiche abzweigend - 0.60 ms = 150 Ticks bei Prescaler 1 : 64
    const int TICKS_GERADE     = 250;     //Weiche gerade     - 1.00 ms = 250 Ticks bei Prescaler 1 : 64
    
    const int nSRV_MAX         = 18;         //max Anzahl an Servos  -> es sind max 18 Servos moeglich !
    //  -> ocr1a > ocr1b ist Pflicht
    //  -> 4999 / 250 = 19.9 -->> 18 fuer Puffer
    //  -> NUR wenn max Stell-Signal = 250 ist !!
    
    const int FLAG_LED_GERADE = 0;          //Offset um die LED des n-ten Servos fuer gerade Fahrt zu setzen
    const int FLAG_LED_ABZW   = 1;          //Offset um die LED des n-ten Servos fuer abzweigende Fahrt zu setzen
    
    const int IX_SRV_POS        = 0;          //Index der Positionen im Array
    const int IX_RTG_LED        = 1;          //Index der LED-Flags im Array
    
    //  2. variable Werte
    int srv = -1;                                     //der aktuelle Servo als Zähler - für OCR1A
    int srvPositionen[ nSRV_MAX ][ 2 ];     //Array für die Servo-Positionen und den Pin fuer die Richtungs LED
    int tasterStatus[ nSRV_MAX ];            //Logische Schaltung zur Erfassung der Taster-Status-Wechsel
    
    int ocr1b;                                 //variabler Wert für das, je Servo verschiedene, Steuersignal
    
    int srvByte = 0;                         //1 Byte = 8 Bit, also ein Paket von 8 Servos
    int srvZaehler = 0;                     //Zaehler zur Ermittlung in welchem Byte = Register sich der aktuelle Servo befindet
    
    int ledByte = 0;                         //1 Byte = 8 Bit, also ein Paket von 4 Servos, da 1 Servo = 2 LED
    int ledZaehler = 0;                     //Zaehler zur Ermittlung in welchem Byte = Register sich die LEDs befinden
    
    int nShiftRegisterSrv;                 //Anzahl der vorhandenen/noetigen Register fuer die Servos
    int nShiftRegisterLEDs;               //Anzahl der vorhandenen/noetigen Register fuer die Richtungs-LEDs
    
    //  3. Berechnete Werte
    int ocr1a = 4999 / nSRV_MAX;     //Intervall für OCR1A um für jeden Servo ein 20 ms Intervall zu erhalten  ( 1 : 64 )
    
    
    
    //  Setup **********************************************************************************************************************
    void setup (  ) {
      //  Serial Monitor
    //  Serial.begin ( 115200 );
    
      //  MUX Pins setzen
      pinMode(CONTROL0, OUTPUT);
      pinMode(CONTROL1, OUTPUT);
      pinMode(CONTROL2, OUTPUT);
      pinMode(CONTROL3, OUTPUT);
    
      pinMode( MUX0, INPUT);   //Multiplexer 0 zu input setzen  - empfaengt die Taster-Eingaben
      pinMode( MUX1, INPUT);   //Multiplexer 1 zu input setzen  - empfaengt die Taster-Eingaben
      pinMode( MUX2, INPUT);   //Multiplexer 2 unbenutzt
    
      //  Ausgaenge festlegen
      pinMode ( PIN_TAKT_SRV, OUTPUT );
      pinMode ( PIN_SPEICHER_SRV, OUTPUT );
      pinMode ( PIN_DATEN_SRV, OUTPUT );
    
      pinMode ( PIN_TAKT_LED, OUTPUT );
      pinMode ( PIN_SPEICHER_LED, OUTPUT );
      pinMode ( PIN_DATEN_LED, OUTPUT );
    
      pinMode ( PIN_TMR_INI_OK, OUTPUT );
      pinMode ( PIN_TMR_INI_NOK, OUTPUT );
    
      //Es muss zwingend ocr1a > ocr1b sein! -> fuer ocr1b muss das laengste Servo-Signal angenommen werden (nServMax x laen. SrvSig)
      if ( ocr1a < TICKS_GERADE ) {
        digitalWrite ( PIN_TMR_INI_NOK, HIGH );
      }
      else {
        //  nShiftRegisterSrv bestimmen und Ueberlauf abfangen
        nShiftRegisterSrv = nSRV_MAX / 8 + 1;          //Register je aktueller Servo Nr., bzw. Anzahl Register bei nServMax
    
        if ( nShiftRegisterSrv * 8 == nSRV_MAX )       //Korrektur bei einer Oktave ( 16 / 8 + 1 = 3, es sind aber nur 2 Byte ! )
          nShiftRegisterSrv--;
    
        //  nShiftRegisterLEDs bestimmen und Ueberlauf abfangen
        nShiftRegisterLEDs = ( nSRV_MAX ) / 4 + 1;     //Teiler = 4 da es pro Servo 2 LEDs gibt (gerade Fahrt && abzweigende Fahrt)
    
        if ( nShiftRegisterLEDs * 4 == nSRV_MAX )      //Korrektur bei einer Oktave ( 16 / 4 + 1 = 5, es sind aber nur 4 Byte ! )
          nShiftRegisterLEDs--;
    
        //  Definiere Timer
        cli (  );                                                     //Interrupts abschalten
    
        //  Interrupt - Timer 1
        TCCR1A = 0;                                              //reset Register A
        TCCR1B = 0;                                              //reset Register B
        TCNT1 = 0;                                               //Zaehler nullen
    
        OCR1A = ocr1a;                                         //setze Intervall A
        TCCR1B |=  ( 1 << CS11 ) |  ( 1 << CS10 );   //Prescaler Timer 1 auf 1 : 64 einstellen
        TCCR1B |=  ( 1 << WGM12 );                       //Timer auf CTC mode stellen
        TIMSK1 |=  ( 1 << OCIE1A );                       //Timer 1 aktivieren
    
        sei (  );                                                    //Interrupts einschalten
    
        digitalWrite ( PIN_TMR_INI_OK, HIGH );
    
        //  Alle Positionen initialisieren
        for ( int serv = 0; serv < nSRV_MAX; serv++ ) {
          srvPositionen[ serv ][ IX_SRV_POS ] = TICKS_ABZW;
          srvPositionen[ serv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
          tasterStatus[ serv ] = 0;
        }
      }
    
      //  Register der Servos loeschen
      digitalWrite ( PIN_SPEICHER_SRV, LOW );
      for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- )
        shiftOut (  PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
      digitalWrite ( PIN_SPEICHER_SRV, HIGH );
    
      //  Register der LEDS setzen
      setLEDs();
    }
    //  //  ************************************************************************************************************************
    
    
    
    //  ISR TIMER 1 COMP A *********************************************************************************************************
    ISR (  TIMER1_COMPA_vect ) {
      const int muxMax = 16;                        //max Anzahl Pins je MUX-Register   (Anzahl, NICHT hoechste Pin-Nr !!)
      const int mux0 = 14;                            //Pin des 1. MUX-Registers
      
      int offsetMUXRegister;                          //Offset um das aktuelle MUX-Register aus dem aktuellen Servo zu errechnen
      int muxReg;                                        //MUX-Register des Servo-Tasters
    
      
      int muxPin;                                         //Pin des akt. Servos je MUX-Regisert
      
      
      //  Auf naechsten Servo zeigen
      srv++;
      if ( srv > nSRV_MAX - 1 ) {                   //Ueberlauf abfangen
        srv = 0;
        srvZaehler = 0;
        srvByte = 0;
      }
    
      //  Den n-ten Servo dem richtigen Register zuordnen
      int servRegister =  srv / 8 + 1;
    
      //  Dem n-ten Servo ueber das entsprechende Register das Steuersignal senden
      digitalWrite ( PIN_SPEICHER_SRV, LOW );
    
      for ( int shiftToRegister = nShiftRegisterSrv; shiftToRegister > 0; shiftToRegister-- ) {
        if ( shiftToRegister == servRegister ) {
          //  sende an Shift-Register
          //  -> der Binaer-Wert ist 2^( srv - srvByte * 8 )
          shiftOut (  PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 1 << ( srv - ( srvByte * 8 ) ) );  
            
          //  Taster des aktuellen Servos auf Veraenderung pruefen
          offsetMUXRegister = srv / 16;
          muxReg = mux0 + offsetMUXRegister;
          muxPin = srv - offsetMUXRegister * muxMax;
    
          digitalWrite ( CONTROL0, ( muxPin & 15 ) >> 3 );
          digitalWrite ( CONTROL1, ( muxPin & 7 ) >> 2 );
          digitalWrite ( CONTROL2, ( muxPin & 3 ) >> 1 );
          digitalWrite ( CONTROL3, ( muxPin & 1 ) );
    
          if ( digitalRead ( muxReg ) && digitalRead ( muxReg ) != tasterStatus[ srv ] ) {
            if ( srvPositionen[ srv ][ IX_SRV_POS ] == TICKS_ABZW ) {
              srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_GERADE;
              srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_GERADE;
            }
            else {
              srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_ABZW;
              srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
            }
    
            //  bei Tastendruck die LEDs neu schalten
            setLEDs();
          }
    
          tasterStatus[ srv ] = digitalRead ( muxReg );
        }
        else {
          //  sende an Shift-Register
          shiftOut (  PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
        }
      }
    
      digitalWrite ( PIN_SPEICHER_SRV, HIGH );
    
        //  Das Byte des naechsten Servos ermitteln
      srvZaehler++;
    
      if (  srvZaehler == 8 ) {
        srvZaehler = 0;
        srvByte++;
      }
    
      ocr1b = srvPositionen[ srv ][ IX_SRV_POS ];           //Länge des Steuersignals aus dem Array lesen
      OCR1B = ocr1b;                                      //Timer B setzen
      TIFR1  |= ( 1 << OCF1B );                           // ??? Klappt immer wenn das gesetzt wird
      TIMSK1 |= ( 1 << OCIE1B );                          //Timer B aktivieren
    }
    //  //  ************************************************************************************************************************
    
    
    
    //  ISR TIMER 1 COMP B *********************************************************************************************************
    ISR (  TIMER1_COMPB_vect ) {
      TIMSK1 &= ~ ( 1 << OCIE1B );                                  //CompB Match interrupt disabled
    
      digitalWrite ( PIN_SPEICHER_SRV, LOW );
      for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- )    //das Steuersignal abschalten             --> Shift-Ausgang = OFF
        shiftOut (  PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
      digitalWrite ( PIN_SPEICHER_SRV, HIGH );
    }
    //  //  ************************************************************************************************************************
    
    
    
    //  setLEDs ********************************************************************************************************************
    void setLEDs() {
      //Reset
      shiftOut (  PIN_DATEN_LED, PIN_TAKT_LED, MSBFIRST, 0 );
    
      //Senden der 0/1 Zustaende der LEDs an die Register
      //  -> festes setzen aller LEDs um Flackern zu verhindern
      
      digitalWrite ( PIN_SPEICHER_LED, LOW );
      
      for ( int srvLEDs = nSRV_MAX; srvLEDs >= 0; srvLEDs-- ) {
        if ( srvPositionen [ srvLEDs ][ IX_RTG_LED ] == FLAG_LED_GERADE ) {
          digitalWrite ( PIN_TAKT_LED, HIGH );   //"abzweigendes" Bit auf 0 setzen
          digitalWrite ( PIN_TAKT_LED, LOW );    //Takt wieder abschalten
          
          digitalWrite ( PIN_DATEN_LED, HIGH );  //"gerades" Bit auf 1 setzen
          digitalWrite ( PIN_TAKT_LED, HIGH );   //"gerades" Bit uebertragen
          digitalWrite ( PIN_DATEN_LED, LOW );   //Daten abschalten
          digitalWrite ( PIN_TAKT_LED, LOW );    //Takt abschalten
        }
        else {
          digitalWrite ( PIN_DATEN_LED, HIGH );  //"abzweigendes" Bit auf 1 setzen
          digitalWrite ( PIN_TAKT_LED, HIGH );   //"abzweigendes" Bit uebertragen
          digitalWrite ( PIN_DATEN_LED, LOW );   //Daten abschalten
          digitalWrite ( PIN_TAKT_LED, LOW );    //Takt abschalten
          
          digitalWrite ( PIN_TAKT_LED, HIGH );   //"gerades" Bit auf 0 setzen
          digitalWrite ( PIN_TAKT_LED, LOW );    //Takt abschalten
        }
      }
    
      Serial.println();
      digitalWrite ( PIN_SPEICHER_LED, HIGH );
    }
    //  //  ************************************************************************************************************************
    
    
    
    //  loop ***********************************************************************************************************************
    void loop ( ) { }
    //  //  ************************************************************************************************************************
    Geändert von Radom (25.03.2017 um 11:08 Uhr)

Ähnliche Themen

  1. Immer wieder dieses VISTA
    Von Naturp im Forum PC-, Pocket PC, Tablet PC, Smartphone oder Notebook
    Antworten: 12
    Letzter Beitrag: 16.03.2010, 20:28
  2. immer wieder pwm tiny45
    Von meldano im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 23.04.2007, 03:23
  3. Immer wieder - Labornetzteil...
    Von Vaterssohn im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 15.11.2006, 22:47
  4. Immer wieder....I2C Bus
    Von JensB im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 16.09.2004, 17:26
  5. [ERLEDIGT] Immer wieder LCD Probleme
    Von Bruce im Forum Robby CCRP5
    Antworten: 7
    Letzter Beitrag: 03.08.2004, 13:26

Stichworte

Berechtigungen

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

Labornetzteil AliExpress