- Akku Tests und Balkonkraftwerk Speicher         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 18 von 18

Thema: Problem bei 4 Kanal Servo PWM

  1. #11
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Danke für den Hinweis mit den Kondenastoren, wenn ich mich richtig erinerre, habe ich da 25k Potis drin.

    Wenn ich nach dem "in ADCH" noch ein ldi anhänge, läuft das ganze, aber ich werde dann noch die bereinigte Versiuon mit dem save hochladen.

  2. #12
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Mit 25 K Potis sollte es eigentlich kaum Probleme geben mit den AD eingängen. Hab mich oben mit dem Wert etwas vertan, kritisch wird es erst ab 50 kOhm und dann auch eher langsam.

    Eine ISR routine die das SREG verändert (so wie im code oben) führt fast immer zu unerwarten Fehlern im Rest des Programms. Diesen Punkt unbedingt beheben.

  3. #13
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    Ok, ich hab mal die üblichen ADC Maßnehmen ergriffen, also Induktivität und C an Aref und die Kondensatoren an den Eingängen gegen Masse.
    Trotzdem zappelt da alles weiter vor sich hin. Muss ein Fehler im Code sein.
    Ich hab auch mal ein Register zum sicher von SREG => save_sreg angelegt.
    Code:
    .include "m8def.inc"
    
    .def tmp = r16
    .def k0 = r17;Servo 0
    .def k1 = r18;Servo 1
    .def k2 = r19;Servo 2
    .def k3 = r20;Servo 3
    .def zyclus = r21
    .def kanal = r22 ;geht an ADMUX
    .def pause = r23 ;für die 1ms Offset und die zweite ms für 
    ; die Servoposition wird die selbe ISR benutzt. Ist Pause = 0
    ;wird über das LOW setzten weggesprungen, wenn Pause = 1 eben nicht.
    ;sinngemäß wird Pause nach der ms erhöht und nach dem Positionsstellen
    ;erniedrigt.
    .def save_sreg = r24 ;erklärt sich sicher von selbst
    .org 0x000
      rjmp reset
    
    .org OC2addr	; OCR2 Interrupt Vector Address
        rjmp hitvalue
    
    
      
    reset:
       ;Stack wird bei Interrupts benötigt! 
       ldi r16,HIGH(RAMEND) 
       out SPH,r16 
       ldi r16,LOW(RAMEND) 
       out SPL,r16
    ldi tmp,0b00000010
    out TCCR0,tmp
    
    ldi tmp,0b00100000
    out DDRC,tmp
    ldi tmp,0b01010101
    out DDRD,tmp
    ldi tmp,0b011000000
    out ADMUX,tmp
    ldi tmp,30
    out OCR2,tmp
    
    sei
    main:
    ;##################################################################
    ;##################################################################
    ;hier werden die ADC Werte für das jeweilige Servo erfasst
    
    ldi kanal,0b01100000  ;Hier wird für den Servo 0
    out ADMUX,kanal       ;die Position ermittelt
    ldi tmp,0b11000101    ;PRESCALER 32 - Singleconversion
    out ADCSRA,tmp
    kanal0:
    in tmp,ADCSRA
    sbrs tmp,4
    rjmp kanal0
    in k0,ADCH
    
    
    
    ldi kanal,0b01100001
    out ADMUX,kanal
    ldi tmp,0b11000101    ;PRESCALER 32
    out ADCSRA,tmp
    kanal1:
    in tmp,ADCSRA
    sbrs tmp,4
    rjmp kanal1
    in k1,ADCH
    
    
    
    ldi kanal,0b01100010
    out ADMUX,kanal
    ldi tmp,0b11000101    ;PRESCALER 32
    out ADCSRA,tmp
    kanal2:
    in tmp,ADCSRA
    sbrs tmp,4
    rjmp kanal2
    in k2,ADCH
    
    
    ldi kanal,0b01100011
    out ADMUX,kanal
    ldi tmp,0b11000101    ;PRESCALER 32
    out ADCSRA,tmp
    kanal3:
    in tmp,ADCSRA
    sbrs tmp,4
    rjmp kanal3
    in k3,ADCH
    ;#############################################################
    ;#############################################################
    
    ldi tmp,0
    out TCNT0,tmp
    
    ;_________________18ms Pause_____________-
    waita:
       in tmp,TCNT0
       cpi tmp,252
       brlo waita
       ldi tmp,0
       out TCNT0,tmp
       inc r26
       cpi r26,74
    brlo waita
    ;________________________________________-
    
    
    ldi tmp,0b00001001 ;RPESCALER 1
    out TCCR2,tmp
    
    ldi tmp,0
    out TCNT2,tmp
    
    
    
    ldi tmp,0b01010101 ;Pins für das Signal HIGH setzten
    out PORTD,tmp
    ldi tmp,0b10000000  
    out TIMSK,tmp
    ldi zyclus,0
    ldi r26,0
    
    ;*******************1ms Offset*****************
    warten1:
    cpi zyclus,250
    breq wigger
    
    rjmp warten1
    wigger:
    ;**********************************************
    
    sbi PORTC,5 ;wurde zur Kontrolle der Zeiten benutzt und mit Oszi gemessen
    ldi zyclus,0
    out TCNT2,zyclus
    ldi pause,1
    ;ab hier Stellungs kritische ms
    
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ;diese Schleife wird solange durchlaufen,
    ;bis der PORTD an dem die Servo angeschlossen sind
    ;komplett LOW ist
    pulse:
       
    in tmp,PORTD
       cpi tmp,0
    brne pulse
    ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    ;'''''''''''''''''''''''''''''''''
    ;diese Schleife macht die ms ggf. voll,um das PWM nicht zu verzerren
    warten:
    cpi zyclus,250
    brsh ende
    rjmp warten
    ende:
    ;'''''''''''''''''''''''''''''''''
    cbi PORTC,5
    
    ldi zyclus,0
    out TCCR2,zyclus
    ldi pause,0
    ldi kanal,0b01100000
    out ADMUX,kanal
    
    rjmp main
    
    
    
    
    hitvalue:
    in save_sreg,SREG
    cpi pause,0
    breq null
    
    cp zyclus,k0
    brne ka
    cbi PORTD,0
    ka:
    
    cp zyclus,k1
    brne kb
    cbi PORTD,2
    kb:
    
    cp zyclus,k2
    brne kc
    cbi PORTD,4
    kc:
    
    cp zyclus,k3
    brne kd
    cbi PORTD,6
    
    kd:
    
    null:
    inc zyclus
    out SREG,save_sreg
    reti
    Danke auch bis hier hin schon für die Mühen,
    The Man

  4. #14
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.232
    Ich bin der Meinung dein Programm hängt viel zu viel in der Timer 2 Interrupt Routine rum.
    Warum nimmst Du nicht den Timer 1 her und gibst dann ein Servo nach dem anderen aus ?
    Der Timer kann bei einer Quarzfrequenz von 8MHz mit einem Prescaler von 8 verwendet werden. Mit diesen Parametern entspricht der Comparematch Zählerstand dann auch der Servoimpulslänge in µs.
    Da der Timer 1 ein 16Bit Timer ist brauchst Du nicht mal ein Überlaufregister, weil ja 65ms in den Timer "reingehen".
    Dann lässt Du eine Pause von 12ms folgen und startest den Zyklus neu.

    Die Comparematch1A Routine würde dann in einem Zyklus 20ms nur 4mal durchlaufen und deine Servos kriegen genauso viele Impulse wie jetzt auch.

    Zur Register Sicherung:

    Meine Register Sicherung schaut immer folgendermassen aus:
    Code:
    PUSH temp    ; temp Register sichern
    IN temp,SREG; SREG ins temp Register
    PUSH temp    ; temp Register nochmal sichern
    PUSH temp1... ; weitere in der Interruptroutine verwendete Register sichern
    ; #### Dein Quellcode ####
    POP temp1    ; weitere Register zurückschreiben
    POP temp
    OUT SREG,temp ; SREG zurückschreiben
    POP temp          ; Werte des temp Registers zurückholen 
    RETI                 ; Raus aus dem Interrupt

  5. #15
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    Ich hab jetzt mal den Kanalwechsel im ADMUX wegkommentiert, damit alle Servo Register aus dem Selben Poti versorgt werden. laufen jetzt alle synchron. (Ich habe bei der ersten Version darauf geachtet, erst den Kanal zu ändern und dann die Wandlung zu starten) Das bedeutet ja, das das Program im Prinzip funktioniert. Ich verstehe nur nicht, warum er die Werte dann durch einander Würfelt, wenn ich die Kanäle weiterschalte

  6. #16
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    SOOOOOOOOOOOOO,

    ich hab das Problem gefunden! Ich lese an vier Stellen das ADCH ei´n (left adjusted). Das funktioniert ohne Interrupt über das ADC Flag Bit 4. Also in einer Schleife:

    kanal0:
    in tmp,ADCSRA
    sbrs tmp,4
    rjmp kanal0
    in k0,ADCH

    Der Gag ist, dass dieses Bit irgendwie nicht wie üblich automatisch gelöscht wird und das Program deshalb Sinnlos durchrennt. Das löscht sich nichtmal, wenn ich ADCSRA manuell mit NULL beschreibe.
    Kann es sein, dass ich hier einem Vista Problem aufsitzte? Im Dec C++ Compiler hatte ich das auch schon...
    Chuck Norris kann Windows Vista auf einem Atmel in Assembler implementieren!
    Chuck Norris coded mit 3 Tasten:"1","0" und "compile"

  7. #17
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Das kommt davon wenn man nur einfach 4 schraubt um ds ADIF bit auszuwählen. Besser statt der den Bitnahmen (ADIF) verwenden, dann wird der code besser portabel und man sieht besser welches Bit gemeint ist.

    Die Intteruptsflags werden gelöscht, indem eine 1 hineingeschrieben wird. Klingt unlogisch ist aber so.

  8. #18
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    12.06.2006
    Beiträge
    478
    for (applaus=0;applaus<1001;applaus++){
    printf("=D> =D> =D> =D> =D> =D> DANKE!\n");
    }

    Jetzt läuft das Ding.
    Chuck Norris kann Windows Vista auf einem Atmel in Assembler implementieren!
    Chuck Norris coded mit 3 Tasten:"1","0" und "compile"

Seite 2 von 2 ErsteErste 12

Berechtigungen

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

Labornetzteil AliExpress