-
Also erst mal muss ich einen ganz großen Danke aussprechen, das du dir die Zeit nimmst für mich.
Dann zu dem Takt. Ich weis auch nicht, wo er aktuell her kommt, ich denke durch die Schleife, die immer wieder abgearbeitet wird. Aktuell dreht sich der Motor mit ca. 30-40Hz.
Zum testen für die Richtung und die Stufen, war das ok, aber das muss noch irgendwie weg.
Mehr Probleme habe ich mit den Timern und die Einbindung in die Schaltung.
Gehen wir erst mal von einem Motor mit 2 Richtungen und 2 Geschwindigkeiten aus.
Das mit der Richtung läuft ja schon ganz gut. Nun kommt aber die Geschwindigkeit.
Wie kann ich:
A. Sagen, das der Timer seine Geschwindigkeit/Takt ändern soll?
oder
B. einen bzw dann 2 Timer in die Schaltung mit z.B. einer AND Anweisung einbinden.
Code:
If W1 =< 1 Or W1 => 100 AND Timer1 = 1 Then
Portc.3 = 1
Darüber habe ich nichts gefunden.
Aus der SPS Programierung kenne ich noch die Merker. Damit konnte man schön solche zusammenhänge realisieren.
Zur Struktur. Sorry, ich Kopiere/Schiebe/Lösche/Klammer,.. so viel rum. Da fällt das echt schwer. Aber ich werde mir mühe geben, das ordentlicher zu halten.
Nachtrag. Ich glaube ich habe da was gefunden. Das gucke ich mir morgen mal in Ruhe an.
Code:
$regfile = "m8def.dat"
$framesize = 24
$swstack = 32
$hwstack = 32
$crystal = 1000000
Config Pinb.1 = Output
Dim Timer1reload As Word
Timer1reload = 1
Config Timer1 = Timer , Prescale = 64
Timer1 = Timer1reload
Enable Timer1
On Timer1 Timer1_isr
Enable Interrupts
'TimerRelaod Werte mit "AVR Timer.exe" berechnet
Const Akku_leer = 63193 ****** ca. 0,3 Sekunden
Const Akku_halb_voll = 60849 'ca. 0,6 Sekunden
Const Akku_voll = 49911 ****** ca. 1 Sek
Dim Adc_wert As Word
Do
ADC_wert = Getadc(3) ****** Beispiel
Select Case ADC_wert
Case 800 to 1024
Timer1reload = Akku_voll
Case 700 to 799
Timer1reload = Akku_halb_voll
Case 0 to 699
Timer1reload = Akku_leer
End select
Loop
End
Timer1_isr:
Timer1 = Timer1reload
Toggle Pinb.1 ****** PIN anpassen
Return
-
Nein, so funktioniert das nicht, du fragst den Timer nicht ab, sondern der Timer selber löst eine kleine Unterfunktion (ISR, Interrupt Service Routine) aus, in der du dann deine Pins umschalten kannst. Du musst dir das so vorstellen, dass du einmal deine Hauptschleife hast, in der allgemeine Sachen drin stehen und die sich immer wiederholt, wenn sie abgearbeitet wurde -> Abarbeitungszeit ist nicht konsistent, da durch abweichende Abläufe die Zeit verändert werden kann (zB. in einer If-Verzweigung wird nur ein Pin abgefragt und im Else-Zweig kommen eine komplexe berechnung und Ausgabe auf einem Display -> dauert viel länger). Die Timer sind nun so, dass man ihnen eine Zahl vorgeben kann, welche die Anzahl an Taktzyklen ist, die der Timer zählt, bis er sich wieder zurücksetzt und die ISR auslöst. Dadurch wird das, was in der ISR ist, in einem festen Intervall ausgeführt. In der ISR lässt sich dann der der Zählwert wiederrum verändern, wodurch man auch Einfluss auf das Intervall hat. Die ISR an sich sollte eher kurz gehalten werden, alles, was länger braucht, gehört in die Hauptschleife. So bekommt man mit den Timern eine ziemlich gute zeitliche Kontrolle und kann so recht präzise zeitliche Abläufe koordinieren. Und guck dir wirklich mal den Artikel im Tutoril zu den Timern an, anscheinend hast du das nicht gemacht, sonst wär dir das mittlerweile klar.
-
Danke, ja ich habe die Nacht noch vorm Rechner verbracht und mir heute Vormittag der Quellcode dieser AkkuAnzeige angeschaut.
Jetzt klappt das alles fast.
Ich kann rechts/links und Hoch/Runter . Auch jeweils 3 Geschwindingskeitsstufen. Leider sind die Timer nur auf 3 Begrenzt. Ich habe jetzt Timer 0 und 2 genutzt. Den Timer1 brauche ich noch für den Hauptantrieb.
Alle anderen Seiten die noch kommen, muss ich dann wohl mit "Wait" machen, oder so.
Das Problem, dass ich jetzt noch habe ist, wenn ich die Motoren Starte, aber noch keine Geschwindigkeit habe, laufen beide Timer schon. Irgendwie muss ich Timer jetzt noch Starten/Stoppen können, Wenn der Joystick auf Neutral ist.
Code:
'###################################################
'Testprogramm
'für
'RoboterNetz Standard-Roboter Board RBNFRA 1.2
'
'Aufgabe:
'###################################################
Const Writepowerport_adr = &H72 'I2C Adr PCF 2
Const Readpowerport_adr = &H73 'I2C Adr PCF 2
Const Writeeingabeport_adr = &H7E
Const Readeingabeport_adr = &H7F
Dim I2cdaten As Byte 'Datenbyte aus PCF8574
Dim I As Word
$crystal = 8000000 'Quarzfrequenz
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit
I2cstart
I2cwbyte &H74 'Schreibbefehl an PCF3 schicken
I2cwbyte &B00000010 'Datenbyte an PCF3
I2cstop
'*********
Config Pind.6 = Output 'Schrittmotoren Ein/Aus
Config Pinc.5 = Output 'Schrittmotor Links Richtung
Config Pinc.3 = Output 'Schrittmotor Links Step
Config Pinc.4 = Output 'Schrittmotor Rechts Richtung
Config Pinc.2 = Output 'Schrittmotor Rechts Step
Config Adc = Single , Prescaler = Auto , Reference = Internal
Start Adc
Dim W1 As Word , Channel As Byte
'### Timer2 Hoch / Runter
Dim Timer2reload As Word
Timer2reload = 1
Config Timer2 = Timer , Prescale = 1024
Timer2 = Timer2reload
Enable Timer2
On Timer2 Timer2_isr
Enable Interrupts
Const Hoch_s3 = 150 'Hoch Stufe 3
Const Hoch_s2 = 80 'Hoch Stufe 2
Const Hoch_s1 = 1 'Hoch Stufe 1
Const Stop_s2 = 0 'STOP
Const Runter_s1 = 1 'Runter Stufe 1
Const Runter_s2 = 80 'Runter Stufe 2
Const Runter_s3 = 150 'Runter Stufe 3
Dim Adc_wert As Word
'### Timer0 Rechts / Links
Dim Timer0reload As Word
Timer0reload = 1
Config Timer0 = Timer , Prescale = 1024
Timer0 = Timer0reload
Enable Timer0
On Timer0 Timer0_isr
Enable Interrupts
Const Rechts_s3 = 150 'Rechts Stufe 3
Const Rechts_s2 = 80 'Rechts Stufe 2
Const Rechts_s1 = 1 'Rechts Stufe 1
Const Stop_s0 = 0 'Stop
Const Links_s1 = 1 'Links Stufe 1
Const Links_s2 = 80 'Links Stufe 2
Const Links_s3 = 150 'Links Stufe 3
Do
'############ Start / Stop
W1 = Getadc(2)
Print "Channel 0 " ; " value " ; W1
Incr Channel
If W1 = 0 Then
Portd.6 = 1 'Schrittmotor ein
Else
Portd.6 = 0 'Schrittmotor aus
End If
'################### Rechts / Links Motor
Adc_wert = Getadc(0)
Select Case Adc_wert
Case 1022 To 1024
Timer0reload = Rechts_s3
Portc.4 = 0
Case 731 To 1021
Timer0reload = Rechts_s2
Portc.4 = 0
Case 585 To 730
Timer0reload = Rechts_s1
Portc.4 = 0
Case 439 To 584
Timer0reload = Stop_s0
Case 293 To 438
Timer0reload = Links_s1
Portc.4 = 1
Case 4 To 292
Timer0reload = Links_s2
Portc.4 = 1
Case 1 To 3
Timer0reload = Links_s3
Portc.4 = 1
End select
'################### Hoch / Runter Motor
Adc_wert = Getadc(1)
Select Case Adc_wert
Case 1022 To 1024
Timer2reload = Hoch_s3
Portc.5 = 0
Case 731 To 1021
Timer2reload = Hoch_s2
Portc.5 = 0
Case 585 To 730
Timer2reload = Hoch_s1
Portc.5 = 0
Case 439 To 584
Timer2reload = Stop_s2
Case 293 To 438
Timer2reload = Runter_s1
Portc.5 = 1
Case 4 To 292
Timer2reload = Runter_s2
Portc.5 = 1
Case 1 To 3
Timer2reload = Runter_s3
Portc.5 = 1
End Select
Loop
End
'################### Hoch / Runter Motor
Timer2_isr:
Timer2 = Timer2reload
Toggle Portc.3
Return
'################### Rechts / Links Motor
Timer0_isr:
Timer0 = Timer0reload
Toggle Portc.2
Return
- - - Aktualisiert - - -
Ich sollte erst mal zu ende überlegen, bevor ich was schreibe, sorry.
Also das mit den Timern habe ich jetzt auch gelöst.
Hier der kurze Ausschnitt.
Code:
...
Timer0reload = Rechts_s1
Portc.4 = 0
Start Timer0
Case 439 To 584
Timer0reload = Stop_s0
Stop Timer0
...
-
Super :)
Mach in den ISRs am besten noch einen Toggle rein und dazwischen paar µs warten, sonst macht der Schrittmotor nur alle zwei ISRs einen Schritt.
als nächstes kannst ja vesuchen, die Geschwindigkeit feiner abzustufen. Hier mal ein Beispiel, wie man sowas machen kann:
Angenommen, der ADC-Wert geht von 0 bis 1023 (also 10 Bit) und du möchtest, dass der Schrittmotor sich von 0-411 Rückwärts dreht und von 612-1023 vorwärts, wobei dann zu dan äußeren Bereichen die Geschwindigkeit zunimmt. Um die Geschwindigkeit zu ändern, musst du die Zeit ändern, die den Timer stellt. Bis jetzt hast du alles über Verzweigungen gelöst, wie wäre es aber mit einer Formel? Dazu müsstest dann aus dem ADC-Wert die entsprechende Zeit erzeugen. Wenn du dann sagst, dass die Zeit maximal 300 sein soll (ich hab das schonmal angepasst, wegen dem doppelten Toggle in der ISR), wäre zum Beispiel für das Rückwärtsdrehen die Geschwindigkeit adc_wert*300/411 und für das Vorwärtsdrehen (1023-adc_wert)*300/411. Hoffe, du siehst da ein wenig durch, sonst erklär ich das vielleicht nochmal. Jedenfalls ist es wichtig, auf die Datentypen zu achten. Integer würde hier mit seinen 16 Bit zB. nicht reichen, da wäre Long mit 32 Bit schon notwendig. Außerdem ist hier die Reihenfolge der Rechenoperationen wichtig, erst multiplizieren, dann dividieren, da die beim Dividieren entstehenden Kommastellen einfach abgeschnitten werden.
-
Ja okay, danke.
Ich werde mal gucken. Ich habe gehofft das ich diese Woche weiter komme damit. Hatte Zeit.
Mal sehen, wie ich das begreife.
Aktuell habe ich mal getestet :
Code:
Pulsfrequenz = Adc_wert / 4
Das klappt schon mal. Also ich kann den Motor "Stufenlos" in der Geschwindigkeit steuern.
Aber das Prinzip mit der Formel für die Richtungserkennung ist soweit klar.
Ich glaube, ich denke einfach zu kompliziert. Dazu kommt noch ein Stapel Unsicherheit, und ein Berg Unwissenheit :)
-
Hallo,
Also, dein ADC geht eigentlich von 0 bis 1023. Die Mitte ist bei 511.
Kleinere Werte al 511 sind Linkslauf, grössere Rechtslauf.
Temp = ADC_Wert - 512
If Temp > 0 Then
' Rechtsrum
Else
' Linksrum
End If
Temp = ABS(Temp) ' Temp ist nun immer Positiv und im Bereich 0...511
Temp = Temp - 49 ' 50 = Totbereich um Mittelstellung
If Temp < 1 Then
' Motor stoppen
Else
' Temp ist jetzt im Bereich im Bereich 1... 461 und dies soll zu 1...922 werden
' Motor_Richtung = Linksrum/Rechtsrum
' Motor_Speed = Temp * 2
' Motor = Ein.
Else If
MfG Peter(TOO)
-
Code:
'###################################################
'Testprogramm
'für
'RoboterNetz Standard-Roboter Board RBNFRA 1.2
'
'Aufgabe:
'###################################################
Const Writepowerport_adr = &H72 'I2C Adr PCF 2
Const Readpowerport_adr = &H73 'I2C Adr PCF 2
Const Writeeingabeport_adr = &H7E
Const Readeingabeport_adr = &H7F
Dim I2cdaten As Byte 'Datenbyte aus PCF8574
Dim I As Word
$crystal = 8000000 'Quarzfrequenz
Config Scl = Portc.0 'Ports fuer IIC-Bus
Config Sda = Portc.1
I2cinit
I2cstart
I2cwbyte &H74 'Schreibbefehl an PCF3 schicken
I2cwbyte &B00000010 'Datenbyte an PCF3
I2cstop
'*********
Config Pind.6 = Output 'Schrittmotoren Ein/Aus
Config Pinc.5 = Output 'Schrittmotor Links Richtung
Config Pinc.3 = Output 'Schrittmotor Links Step
Config Pinc.4 = Output 'Schrittmotor Rechts Richtung
Config Pinc.2 = Output 'Schrittmotor Rechts Step
Config Adc = Single , Prescaler = Auto , Reference = Internal
Start Adc
Dim W1 As Word , Channel As Byte
'### Timer2 Hoch / Runter
Dim Timer2reload As Word
Timer2reload = 1
Config Timer2 = Timer , Prescale = 1024
Timer2 = Timer2reload
Enable Timer2
On Timer2 Timer2_isr
Enable Interrupts
Dim Adc_wert As Word
'### Timer0 Rechts / Links
Dim Timer0reload As Word
Timer0reload = 1
Config Timer0 = Timer , Prescale = 1024
Timer0 = Timer0reload
Enable Timer0
On Timer0 Timer0_isr
Enable Interrupts
Do
'############ Start / Stop
W1 = Getadc(2)
Print "Channel 0 " ; " value " ; W1
Incr Channel
If W1 = 0 Then
Portd.6 = 1 'Schrittmotor ein
Else
Portd.6 = 0 'Schrittmotor aus
End If
'################### Hoch / Runter Motor
Adc_wert = Getadc(1)
Dim Temp1 As Integer
Temp1 = Adc_wert - 512
If Temp1 > 0 Then
Portc.5 = 0 ' Rechtsrum
Else
Portc.5 = 1 ' Linksrum
End If
Temp1 = Abs(temp1) ' Temp ist nun immer Positiv und im Bereich 0...511
Temp1 = Temp1 - 49 ' 50 = Totbereich um Mittelstellung
If Temp1 < 1 Then
Stop Timer2 ' Motor stoppen
Else
' Temp ist jetzt im Bereich im Bereich 1... 461 und dies soll zu 1...922 werden
' Motor_Richtung = Linksrum/Rechtsrum
Timer2reload = Temp1 / 3 ' Motor_Speed = Temp * 2
Start Timer2 ' Motor = Ein.
End If
'################### Rechts / Links Motor
Adc_wert = Getadc(0)
Dim Temp As Integer
Temp = Adc_wert - 512
If Temp > 0 Then
Portc.4 = 0 ' Rechtsrum
Else
Portc.4 = 1 ' Linksrum
End If
Temp = ABS(Temp) ' Temp ist nun immer Positiv und im Bereich 0...511
Temp = Temp - 49 ' 50 = Totbereich um Mittelstellung
If Temp < 1 Then
Stop Timer0 ' Motor stoppen
Else
' Temp ist jetzt im Bereich im Bereich 1... 461 und dies soll zu 1...922 werden
' Motor_Richtung = Linksrum/Rechtsrum
Timer0reload = Temp / 3 ' Motor_Speed = Temp * 2
Start Timer0 ' Motor = Ein.
End If
Loop
End
'################### Hoch / Runter Motor
Timer2_isr:
Waitms 5
Timer2 = Timer2reload
Toggle Portc.3
Return
'################### Rechts / Links Motor
Timer0_isr:
Waitms 5
Timer0 = Timer0reload
Toggle Portc.2
Return
Danke, jetzt läuft das alles. :)
Ich musste nur noch etwas mit dem Takt für die geschwindukkeiten spielen, aber so ist jetzt gut.
Was hätte ich bei
Code:
' Temp ist jetzt im Bereich im Bereich 1... 461 und dies soll zu 1...922 werden
' Motor_Richtung = Linksrum/Rechtsrum
oder sollte das nur als Hinweis dienen?
Ich werde das dann morgen abend mal alles schön schick machen und beschriften.
-
Hallo,
Das Letzte da, war nur als Hinweis gedacht.
Links/Rechts setzt du schon vorher.
Speed = 0...1'000 war mal dein Vorschlag weiter oben.
Auch den Totbereich mit +/- 49 Habe ich in aus deiner Auflistung entnommen und etwas gerundet.
Wenn du die 49 änderst, dann ändert sich aber auch das Resultat (1...461) für Speed entsprechend.
Es ging nur darum, dir prinzipiell zu zeigen wie du das lösen kannst.
Die Werte als solche sind dein Problem ;-)
Das Problem wird dir noch öfters begegnen, du hast ein Signal, welches im Bereich 0..n ist und daraus soll m...0...-m werden.
Das kann man mit vielen If's lösen oder mit ein bisschen Mathematik ;-)
MfG Peter(TOO)
-
Danke schön.
Jetzt stehe ich aber irgendwie aufm Schlauch.
Ich weis nicht, wie ich auf meinem RNBFRA Board die Ein/Ausgänge abfrage.
Ich habe bis jetzt mit den Analogen gearbeitet, das habe ich auch verstanden. Die internen Ausgangsports klappt auch.
Aber das Board hat noch weitere 8 Ein und 8 Ausgänge + 5 I/O .
Ich komme nicht damit klar, die Abzufragen, bzw. Anzusprechen.
Wenn ich jetzt Sage, am Pin.1 =1 dann APort.1 =1.
Aber ist das jetzt PinC.0 -> PortC.0 Ich ahbe schon einiges probiert, klappt aber nicht.
Ich habe jetzt auch keine Schaltungen gefunden, wo diese verwendet wurden.
Code:
Eingangsport
I2C Slave
Empfohlen
wird 7E/7F
Bascom-Beispiel:
Const Writeeingabeport_adr = &H7E
Const Readeingabeport_adr = &H7F
Do
I2cstart
I2cwbyte Readeingabeport_adr
I2crbyte I2cdaten , Nack
I2cstop
Waitms 400
Print I ; " Eingangsport Wert" ; I2cdaten
Incr I
Loop
Ich muss doch da, irgendwo eine Pin/Port beschreibung haben, welchen ich lesen/schreiben möchte.
-
Ich habe jetzt einen Programmcode gefunden, der genau das macht, wonach ich gefragt habe.
Habe ich auch verstanden, was da passiert. Leider passiert da nichts. Kann es sein, das bei mir auf dem Board was kaputt ist?
Code:
'******************************************************************************
$regfile = "m32def.dat"
$baud = 9600
$crystal = 8000000 'Quarzfrequenz
Config Scl = Portc.0 'Ports fuer I2C-Bus
Config Sda = Portc.1
Config Pind.6 = Output 'Schrittmotoren Ein/Aus
Config Pinc.5 = Output 'Schrittmotor Links Richtung
Config Pinc.3 = Output 'Schrittmotor Links Step
Config Pinc.4 = Output 'Schrittmotor Rechts Richtung
Config Pinc.2 = Output 'Schrittmotor Rechts Step
Config Pinb.2 = Input 'Interrupt Int2
Config Portb.2 = 0
Config Portd.3 = 1
Config Int2 = Falling
Enable Int2
Enable Interrupts
On Int2 Int2_isr
Const Writeeingabeport_adr = &H7E 'I2C Adr PCF 2
Const Readeingabeport_adr = &H7F 'I2C Adr PCF 2
Dim I2cdaten As Byte 'Datenbyte aus PCF8574
Dim Taste1 As Word
Dim Taste2 As Word
Dim I As Word
Dim Flag As Bit
I2cinit
I2cstart
I2cwbyte &H74 'Schreibbefehl an PCF3 schicken
'Led´s ein ,Motorendstufen ein, Port-Peripherie ein, RBN-Bus Sleep Modus aus (also Peripherie aktiv)
I2cwbyte &B00000010 'Datenbyte an PCF3
I2cstop
Portd.6 = 0 'Schrittmotoren erst mal ausschalten
I2cdaten = 0
Flag = 0
Taste1 = 247 'Taste 1 (Eingangsport-Port3)
Taste2 = 251 'Taste 2 (Eingangsport-Port4)
I = 0
'******************** Hauptprogramm ********************************************
Do
If Flag = 1 Then Gosub Motor1_2
If Flag = 0 Then Gosub Motoren_aus
Loop
'********************* Unterprogramme ******************************************
Motor1_2:
Portc.5 = 0 'Richtung Motor 1
Portc.4 = 1 'Richtung Motor 2
Portd.6 = 1 'Motoren einschalten
Portc.2 = 0 'Step rechts
Portc.3 = 0 'Step links
Waitms 1
Portc.2 = 1 'Step rechts
Portc.3 = 1 'Step links
Waitms 1
Portd.6 = 0 'Motoren ausschalten
Return
Read_data:
Return
Motoren_aus:
Portd.6 = 0 'Motoren ausschalten
Return
Int2_isr:
I2cstart
I2cwbyte Readeingabeport_adr 'Lesebefehl an PCF schicken
I2crbyte I2cdaten , Nack 'Datenbyte von PCF lesen
I2cstop
Waitms 50
Print I ; " Eingangsport Wert " ; I2cdaten ; " war beim Int2"
Incr I
If I2cdaten = Taste1 Then Flag = 1
If I2cdaten = Taste2 Then Flag = 0
Return