- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: Wer hilft mir bei einem Programm für den AT-Mega 8?

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    19.04.2005
    Ort
    Blender
    Beiträge
    36

    Wer hilft mir bei einem Programm für den AT-Mega 8?

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hi, ich habe hier momentan ein Programmier Problem, und ich hoffe ein Erfahrener Programmierer oder einer der sich mit Timern auskennt kann mir helfen:

    Ich habe eine Karte auf der ein At-Mega 8 drauf ist, an ihm sind 2 Schrittmotoren angeschlossen und weiterhin 2 Poties (Ein alter Joystick).
    Mein Plan war jetzt, dass wenn der Joystick neutral ist, sich kein Motor dreht.
    Wenn die X Achse (ADC 1) einen Ausschlag nach links bekommt sich der Motor1 nach Links dreht und nach rechts, dann natürlich auch der Motor1 nach rechts.
    Bei Vollausschlag links soll er sehr schnell laufen, bei kleinem Ausschlag entsprechend langsam. Die Übergänge möglichst mit seeeeeeeehr vielen Stufen.
    Das gleiche gilt natürlich für die Y Achse und den anderen Motor.

    Mein Problem ist jetzt aber, dass ich die Motoren Ansteuerung nicht parallel laufen lassen kann. Was bedeutet, dass die einzelnen Motoren nicht unabhängig voneinander ihre Geschwindigkeit verändern können.
    (Ich hoffe jemand kennt das Problem, ich kann es nämlich sehr schlecht erklären…)
    Jetzt hoffe ich das mir jemand mit sehr geschickter Programmierung helfen kann, oder mir jemand sagen kann ob und wie ich das Problem mit Timern umgehen kann.

    Meine Idee wäre in den Timer 1 den Moter1 Code zu packen und in den Timer 2 den Code für den Motor 2, dann müsste ich in der Hauptsub „nur noch“ je nach Potiestellung das Timerintervall verändern.
    Ist die Idee richtig und umsetzbar?

    Eine „Lösung“ habe ich schon „fertig“, aber die hat nur 5 Unterschiedliche Geschwindigkeiten und das reicht bei weitem nicht… und sie belegt schon fast den gesamten Speicherplatz des Chips und ist von daher nicht erweiterbar.

    Bin für jede Idee, ICQ-Nummer, etc. dankbar

    Gruß
    Hagen

    *hier noch ein paar daten...:
    Schaltplan (das rote könnt ihr ignorieren)
    http://www.bildfaenger-film.de/extern/plan.jpg

    Motor B / 1
    Code:
    Sub Motorb
          If Bdire = 1 Then
          Btime = Btime + 1
          Elseif Bdire = 2 Then
          Btime = Btime - 1
          End If
    
          If Btime = 9 Then
             Btime = 1
          Elseif Btime = 0 Then
             Btime = 8
          End If
    
          If Btime = 1 Then
          B = B + 1
          Portb.0 = 1
          Portb.1 = 0
          Portb.2 = 0
          Portb.3 = 1
          Elseif Btime = 2 Then
          Portb.0 = 1
          Portb.1 = 0
          Portb.2 = 0
          Portb.3 = 0
          Elseif Btime = 3 Then
          Portb.0 = 1
          Portb.1 = 1
          Portb.2 = 0
          Portb.3 = 0
          Elseif Btime = 4 Then
          Portb.0 = 0
          Portb.1 = 1
          Portb.2 = 0
          Portb.3 = 0
          Elseif Btime = 5 Then
          Portb.0 = 0
          Portb.1 = 1
          Portb.2 = 1
          Portb.3 = 0
          Elseif Btime = 6 Then
          Portb.0 = 0
          Portb.1 = 0
          Portb.2 = 1
          Portb.3 = 0
          Elseif Btime = 7 Then
          Portb.0 = 0
          Portb.1 = 0
          Portb.2 = 1
          Portb.3 = 1
          Elseif Btime = 8 Then
          Portb.0 = 0
          Portb.1 = 0
          Portb.2 = 0
          Portb.3 = 1
          End If
    End Sub
    Motor D / 2
    Code:
    Sub Motord
          If Ddire = 1 Then
          Dtime = Dtime + 1
          Elseif Ddire = 2 Then
          Dtime = Dtime - 1
          End If
    
          If Dtime = 9 Then
             Dtime = 1
          Elseif Dtime = 0 Then
             Dtime = 8
          End If
    
          If Dtime = 1 Then
          Portd.0 = 1
          Portd.1 = 0
          Portd.2 = 0
          Portd.3 = 1
          Elseif Dtime = 2 Then
          Portd.0 = 1
          Portd.1 = 0
          Portd.2 = 0
          Portd.3 = 0
          Elseif Dtime = 3 Then
          Portd.0 = 1
          Portd.1 = 1
          Portd.2 = 0
          Portd.3 = 0
          Elseif Dtime = 4 Then
          Portd.0 = 0
          Portd.1 = 1
          Portd.2 = 0
          Portd.3 = 0
          Elseif Dtime = 5 Then
          Portd.0 = 0
          Portd.1 = 1
          Portd.2 = 1
          Portd.3 = 0
          Elseif Dtime = 6 Then
          Portd.0 = 0
          Portd.1 = 0
          Portd.2 = 1
          Portd.3 = 0
          Elseif Dtime = 7 Then
          Portd.0 = 0
          Portd.1 = 0
          Portd.2 = 1
          Portd.3 = 1
          Elseif Dtime = 8 Then
          Portd.0 = 0
          Portd.1 = 0
          Portd.2 = 0
          Portd.3 = 1
          End If
    End Sub

  2. #2
    2 Timer, für jeden Motor einer, müsste klappen.

    Was ich nicht ganz erkennen kann ist, ob du die Potis an einen ADC angeschlossen hast oder nicht. Wenn Ja, dann kannst du ja den ADC-Wert für die Timer gleich mehr oder weniger übernehmen. 255 = Max, 0 = min oder so... Wie die Werte dann umgesetzt werden ist dann dein Ding.

    Logik für deine Ansteuerung dann:

    Code:
    if  (X_Value > 128) {  //rechts lenken
    power_Motor_links = (....)*(Y_Value);
    power_Motor_rechts = (....)*(Y_Value-faktor); 
    } 
    
    if  (X_Value <= 128) {  //links lenken
    power_Motor_links = (....)*(Y_Value-faktor);
    power_Motor_rechts = (....)*(Y_Value); 
    }
    Mal ein Ansatz... Denk dran, dass der Faktor nicht zu groß werden darf... am besten so wählne, dass bei Volllenkung genau in die Räder sich gleich schnell aber in unterschiedliche Richtungen drehn. (Faktor auch von X abhängig, nicht nur Y!!)

    Du brauchst außerdem eine Motorroutine, die abhängig von den errechneten Werte die Motoren vorwärts oder rückwärts lenkt.

    Code:
    Motor_A(int power) { //power 0-255
      if (power>128) { //vorwärts
         dir = 1;
         TimerA_value = (...)*((power-128)*k+d);
      }
      if (power<128) { //rückwärts
         dir = 0;
         TimerA_value = (...)*(-power*k+d);
      }
    
      //Hier die Timer Füttern!!
    
    }
    Ich weis, es ist C-Style und nicht basic, aber du müstest es lesen können

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    19.04.2005
    Ort
    Blender
    Beiträge
    36
    Ja X und Y Achse sind jeweils GetADC
    von 400 bis 549 links
    550 bis 589 stop
    590 bis 1000 rechts

    Timer0 ist nun so eingestellt, dass die Frequenz vom Quarz, durch den Prescaler, durch 8 geteilt wird.
    (Beim Prescaler kann man Teilungen von 1 , 8 , 64, 256, oder 1024 einstellen).
    Das würde doch heißen, das ich nur 5 stufen habe, oder?

  4. #4
    Hm ich bin ein PICler und hab k.a. was die ATMEL für prescaler haben, oder wie die timer gefüttert werden drum hab ich ja die "(...)" - klammern im code eingefügt. damit "bastelst" du dir dann deine Wunschtimerwerte wie du sie brauchst. beim 0-Punkt würd ich noch den timer stoppen fällt mir grad ein. (Enable weg)

    Ich ging von 255 und nicht 1000 als maximalwert deines Potis aus - du musst noch die abfragen anpassen wenns wirklich so hoch ist!

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    09.01.2006
    Ort
    Hamburg
    Alter
    40
    Beiträge
    40
    hey!

    ich versteh noch nicht warum du nur einen so kleinen bereich hast beim ADC eingang hast du den spannungsteiler richtig berechnet referenzspannung eingestellt oder nicht ? normaler weise müßtest du dann den vollen bereich bekommen.

    oder verstehe ich dein problem falsch?
    Wer Rechtschreibfehler findet, darf sie behalten.

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    19.04.2005
    Ort
    Blender
    Beiträge
    36
    also ich hab keine ahnung lanic...
    aber aufjedenfall ist der wert vom adc wenn der potie ganz links ist 400; mitte 560 bis 580 (variert); und rechts 1000

    Ich habe mal mein Wusch Programm in VisualBasic programmiert und versucht euch das mal gut darzustellen...
    hier der download
    http://www.bildfaenger-film.de/extern/BAS_VB.zip
    bitte guckt euch das mal an!

    Ich komme mit Bascom sowas nicht zurecht... DANKE!

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    19.04.2005
    Ort
    Blender
    Beiträge
    36
    hat es sich denn mal wer angeguckt?
    bitte tut das mal, wenn ihr es noch nicht habt...
    ich bräuchte ne lösung bis ende diesen monats

    sonst muss ich mir noch ne karte bauen, die ich mit vb übern rechner ansteuern kann

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    19.04.2005
    Ort
    Blender
    Beiträge
    36
    50€ für ein wenig programmieren!
    fairer deal?
    ICQ: 94-587-861

  9. #9
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.07.2005
    Beiträge
    569
    Mal so als Denkansatz:

    In Interupt Routinen gehört mit sicherheit nix längeres ...
    Also definitiv nich der "Code für Moror X"

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    01.02.2006
    Beiträge
    16
    Hi gRaf-eny,

    Hanni hat recht. ISR's immer so kurz wie möglich.
    Nebenbei sind 2 Timer ganz schlecht bei so Zeitkritischen Aufgaben, da die sich immer in die Quere kommen.

    Leider gibst Du sehr wenig Infos zu Deinem Projekt (Proz, Quarz, was soll das Prog sonst noch machen, wie sieht der jetzige Quellcode aus (nicht nur Schnipsel),usw.).

    Nach dem Schaltplan siehts nach einem ATMega8 aus ... Quarz wohl 16 MHz.
    Meines erachtens musst Du das anders anpacken. Vergiss als erstes mal VB auf dem PC. Der Atmel kann kein Multitasking (na, ok .. Windows auch nicht wirklich ), also machen wir das einfach ganz schnell hintereinander.

    Ich würde einfach erstmal die ISR entschlacken, indem die Halbschritte des Motors im Hauptprogramm schonmal in ein Array hinterlegt werden.
    Außerdem würde ich in diesem speziellen Fall einen Timer immer zu festen Zeiten über die ISR laufen lassen.

    Code:
    ' Hier die einzelnen Pins für die Motoren. Ein Array pro Pin reicht für beide Motoren
    ' Bit-Arrays gehen leider nicht. Würde mit Tricks gehen .. aber ist schon zu spät für mich (Uhrzeit) ;)
    '******** Initialisierung *************
    
    Dim Motorflag As Byte ' Welcher Motor ist gerade dran (1=Motor 1 ; 2=Motor 2)?
    Dim Pause(2) As Word ' Pausenzähler (Geschwindigkeit Mot 1+2). Max. Wert 65535 !
    Dim Hschritt(2) as Byte ' Halbschrittzähler
    Din Direction(2) as Byte
    Dim ISRZaehler(2) As Word
    Dim MotorA(8) As Byte  
    Dim MotorB(8) As Byte
    Dim MotorC(8) As Byte
    Dim MotorD(8) As Byte
    Dim I as Byte
    
    ' Da ich nicht weiß, was Schrittmotoren für eine Frequenz verkraften, gehe ich 
    ' hier jetzt mal von 50 Hz aus. Da beide Motoren abwechselnd bedient werden,
    ' also eine Frequenz der ISR von 100 Hz
    ' Da reicht Timer0 (bei 16 MHz)
    Config Timer0 = Timer, Prescale = 1024
    Const Timervorgabe = 100
    On Timer0 Timer_irq
    
    Restore Halbschritt
    For I=1 to 8
    	Read MotorA(I)
    	Read MotorB(I)
    	Read MotorC(I)
    	Read MotorD(I)
    Next I
    Motorflag = 1
    Timer0 = Timervorgabe
    Enable Timer0
    Enable Interrupts
    
    ' *************************************
    ' ******** Hauptprogramm **************
    Do
    '(
    Hier lesen wir irgendwie die ADC-Werte ein und wandeln sie in ein "verträgliches" Format
    von mir aus von 400-1000 .. musst Du wissen
    Der Timer springt also 100 mal pro Sekunde in die ISR .. jedes 2. mal kommt der gleiche Motor dran
    In die ISR schreiben wir für jeden Motor eine "Pausenvariable", die bei jedem Einsprung hochgezählt wird.
    Erreicht die Variable den Wert, den Du hier vorgibst (Geschwindigkeit), kriegt der jeweilige Motor seinen Halbschritt. Bei 1 in jedem ISR-Sprung, bei 65535 halt erst nach dem 65535zigsten Sprung. Ist das zu langsam, dann einfach den Timer schneller machen. Reicht der Endwert nicht, dann halt noch eine Zweite Variable einführen und beide hochzählen
    Halbschritt
    Am besten einfach rumprobieren. "ADC-Wert*irgendwas" .. keine Ahnung
    Werte stehen dann in Pause(x). Richtung muss in Direction(x)
    ')
    Loop
    ' ******** Hauptprogramm Ende **************
    ' Hier kommen die Daten für die Halbschritte
    Halbschritt:
    Data 1,0,0,1
    Data 1,0,0,0
    Data 1,1,0,0
    Data 0,1,0,0
    Data 0,1,1,0
    Data 0,0,1,0
    Data 0,0,1,1
    Data 0,0,0,1
    
    ' Hier kommt die ISR
    Timer_irq:
                   
    	Timer0 = Timervorgabe ' Timer neu "laden"
    	If Motorflag = 1 Then    ' Bitoperation wäre schöner aber geht nicht, da Bit 0/1 und Array ab 1 zählt
    		Motorflag = 2    ' müsste man dann in eine neue Variabel auslagern .. wollte ich nicht
    	Else
    		Motorflag = 1
    	End If
    	Incr ISRZaehler(Motorflag)
    	If ISRZaehler(Motorflag) >= Pause(Motorflag) Then
    		ISRZaehler(Motorflag) = 0
          		If Direction(Motorflag) = 1 Then 
          			Incr Hschritt(Motorflag) 
          		Elseif Direction(Motorflag) = 2 Then 
          			Decr Hschritt(Motorflag) 
          		End If
          		If Hschritt(Motorflag) = 9 Then
             		Hschritt(Motorflag) = 1 
          		Elseif Hschritt(Motorflag) = 0 Then 
             		Hschritt(Motorflag) = 8 
          		End If 
    
    		If Motorflag = 1 Then
    			Portb.0 = MotorA(Hschritt(1)) '<---- keine Ahnung, ob der Konstrukt so genommen wird
    			Portb.1 = MotorB(Hschritt(1)) ' Wenn nicht, musst Du ihn erst "aufdröseln"
    			Portb.2 = MotorC(Hschritt(1))
    			Portb.3 = MotorD(Hschritt(1))
    		Else
    			Portd.0 = MotorA(Hschritt(2))
    			Portd.1 = MotorB(Hschritt(2))
    			Portd.2 = MotorC(Hschritt(2))
    			Portd.3 = MotorD(Hschritt(2))
    		End If      
    	End If
    Return
    Nur mal so als Denkanstoß. Ist jetzt zu spät .. können 1000 Fehler drin sein und vieles vll. einfacher zu machen sein. Vielleicht kannst Du ja ein paar Anregungen davon benutzen,
    Tu mich aber langsam schwer mit denken

    Gruß.
    Rainer

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

LiFePO4 Speicher Test