PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pan & Tilt Videoschiene. Mein erstes Projekt. Wie fange ich an?



AtomicIX
28.10.2014, 18:56
Moin,
wie beginne ich am besten ein Programm?
Ich habe viel vor. Wenn ich fertig bin, sollen es eigentlich 3 Programme werden, zwischen denen ich wählen kann.
-> komplett Manuell
-> komplett Automatisch
-> nur ein Teil Automatisch
Dann möchte ich div. Parameter über Potis regeln.
-> Schritttempo der Schrittmotoren
-> Wartezeit zwischen gewissen Aktionen
Am liebsten noch mit Codierschalter, so dass ich z.B. vorgeben kann, der Motor soll 10x 20 Schritte machen,

Ein ähnliches Projekt habe ich letzten Winter mit nur einem Motor gemacht, das ganze nur in TTL Technik, mit Transystoren und NE555 Timer. Das das ist zu groß, zu ungenau und schwer zu erweitern.

Ist sowas überhaupt möglich?
Wo könnte ich Programmschnipsel finden, die ich verwenden kann? Bin hier noch nicht wirklich fündig geworden

Peter(TOO)
28.10.2014, 19:44
Hallo,

Zuerst solltest du dir ein Pflichtenheft zurecht legen, also wie die Bedienung sein soll und wie das Teil reagieren muss.
Zudem wie das ganze aufgebaut wird, damit man auch weiss wie viel und was für Ein/Ausgänge man benötigt.

Dann brauchst du auch noch die passende Hardware, den Schrittmotor kannst du nicht direkt am µC anschliessen, da brauchst du noch Hardware dazu.
Da stellt sich zunächst due Frage ob du die Hardware- und dann auch die Software-Treiber selbst erstellen willst oder etwas fertiges nehmen willst.

Wenn du z.B. einen der Arduinos nimmst, hast du schon mal einen fertigen Computer. Dazu gibt's dann Shields, also zusätzliche Platinen, welche verschiedene Interfaces enthalten.

Nun gibt's aber unterschiedliche Modelle bei den Arduinos und nicht alle Shields passen zu jedem Modell. Hinzu kommt noch, dass sich nicht alle Shields miteinander kombinieren lassen und auch nicht immer mehrere identische Shields gleichzeitig betrieben werden können.

Du musst also zuerst die Hardware zusammenstellen, was du brauchst hast du im Pflichtenheft festgehalten.
Zu den Shields gibt es dann auch passende Bibliotheken und dazu wiederum passende Code-Beispiele.

Zusätzlich musst du dich noch für eine Programmiersprache entscheiden und diese evtl. erst mal erlernen.
Dies beeinflusst allerdings wiederum die Auswahl der Shields, die Bibliotheken müssen auch für deine Programmiersprache vorhanden sein.

Wenn du das alles zusammen hast, kannst du erst mit dem Programmieren anfangen.

Laut Theorie gibt es zwei Techniken, wie man ein Programm erstellt:
Top Down oder Bottom Up

Bei Top Down fängt man mit der abstrahierten Programm-Logik an, z.B. der Bedienerführung und verfeinert dann die ganzen Prozeduren bis man direkt die Hardware ansteuert.
Bei Bottom Up fängt man bei der Hardware an und fasst dann die einzelnen einfachen Funktionen zu komplexeren immer Aktionen zusammen.

Praktisch wird aber meistens Middle Out oder Outside In angewendet.

Bei Outside In schreibt man zuerst ein paar einfache Hardware-Funktionen und eine Bedienoberfläche um diese zu testen. Also z.B. die Funktion um den Schrittmotor einen Schritt nach rechts zu drehen und verknüpft diese mit einer Taste, welche bei jedem Tastendruck die Funktion einmal aufruft. Dann baust du das aus, dass z.B. bei jedem Tastendruck 20 Schritte gemacht werden. Als nächstes liest du dann die Schrittzahl von deinen Codierschalter ein.

MfG Peter(TOO)

AtomicIX
28.10.2014, 21:26
Danke für deinen tollen Bereicht/Anleitung.
Ich hätte vielleicht erwähnen sollen, das ich schon Hardware habe.

Roboternetz RNFRA-Board mit Mega32 Bausatz
RN-Stepp297 Schrittmotoransteuerung

Programieren wollte ich mit BASECOM, erst mal die gratis Variante, wenn alles klappen sollte, die Pro Version. 2Kb Code ist nicht so riesig viel.

Dann werde ich mir jetzt erst mal eine grobe Übersicht aufschreiben, und die ganzen Ports ect von dem Board raus suchen.

AtomicIX
29.10.2014, 12:18
Irgendwie fehlt mir der Faden.
Ich möchte nun mit dem ersten Schritt beginnen.
Mir fehlen aber Programmschnipsel und Beispiele, wie ich das machen kann.

Ich möchte auf dem Roboternetz RNFRA-Board mit Mega32 die beiden Schrittmotoren, Analog über einen Joystick "2 Achsen über 10kOhm Poti" in der Geschwindigkeit und Richtung steuern.
Wenn ich jetzt davon ausgehe, das das Joypad in Mittelstellung ca. 2,5 Volt hat, möchte ich gern das als Nullpunkt haben.
Nun rechne ich die Werte A/D um.

Volt=Bit
0=0
0,5=113
1,0=226
1,5=339
2,5=452
3,0=565
3,5=678
4,0=791
4,5=904
5,0=1017

Ich möchte also zwischen ca. Bit 340-560 Null Impulse auf den Schrittmotor
Rechtslauf:
Bit=Impulse/Sek
1=1000
2=998
3=996
..
339=1
340-560= Stop
Linkslauf
561=1
....
1023=1000

Ich hoffe das ist verständlich. Wie kann ich das umsetzten?
Ich habe jetzt schon über 10h das Forum hier durchsucht, aber nichts in der Art gefunden.

Geistesblitz
29.10.2014, 12:47
Da würde ich mit einer if-Verzweigung rangehen.
Kannst sie ja mit elseif aufteilen, dann die Bereiche ADC-Wert<340, ADC-Wert>560 und alles andere (also der Bereich dazwischen)
Die Umwandlung von ADC-Wert in Pulsfrequenz in eine Formel verpacken und in den Teilen, wo der Motor laufen soll, jeweils ein anderes Richtungs-Bit setzen. Die Formeln kannst dir selber aufstellen, wahrscheinlich soll die Frequenz von 1 linear ansteigen, je weiter der ADC-Wert vom Mittelbereich abweicht. Also wirds dann irgendwas sein in der Form Pulsfrequenz=1018-3*ADC_Wert (würde in diesem Fall an den beiden Enden die Frequenzen 1018 und 1 ergeben). Im anderen Bereich dann sowas wie Pulsfrequenz=1018-3*(1023-ADC-Wert) oder so. Wie gesgt, ist eher als Skizze zu verstehen und müsste noch überprüft werden. Wär wahrscheinlich sinnvoll, den mittleren Bereich symmetrisch zu machen, so wie es jetzt ist hast du auf einer seite 23 Werte mehr als auf der anderen (so ein ADC-Wert kann Werte bis 1023 annehmen, eben volle 10 Bit). Um die Formeln in Bascom zu realisieren musst du wahrscheinlich ein paar Hilfsvariablen einführen, da du immer nur eine Rechenoperation pro Zeile ausführen kannst. Würde dann so aussehen:

Dim ADC_Wert as Integer
Dim Pulsfrequenz as Integer
Dim Temp as Integer

Temp = 3*ADC_Wert
Pulsfrequenz = 1018-Temp


Ist jetzt auch nur ein Codeschnipsel als Beispiel, hoffe es hilft dir.

AtomicIX
29.10.2014, 13:55
Danke. Ja den Grundgedanken habe ich verstanden, die Werte die ich erhalten mit if und elseif .. zu filtern.
Mir fehlt gerade der komplette Einstieg in das Ganze.
Wie frage ich die Eingänge ab? Ich nutze die Eingänge 1/2 und sind nach Standard 7E/7F gejumpert.
Ich sollte vielleicht erst mal anfangen, einfach nur einen Taster zu nehmen, der bei "1" den Motor mit Takt xy laufen lässt und mit "0" wieder stoppt.
Mir fehlen irgendwie Quellcodes die ich zum verstehen und begreifen an das RNFRA-Board anwenden kann.

Geistesblitz
29.10.2014, 14:45
Mit dem Board kenn ich mich leider auch nicht aus, aber mit ATmega32 und Bascom hab ich schon ein bisschen was gemacht. Eingänge abfragen geht eigentlich recht einfach:
Erstmal den entsprechenden Pin als Eingang definieren mit beispielsweise
Config PinA.0=Input
und zum Abfragen einfach den Bezeichner wie eine Variable verwenden.
Die digitalen Eingänge können dabei aber eben nur 0 oder 1 annehmen.
Zum Abfragen eines Tasters wäre zB. so ein Konstrukt möglich:

if PinA.0=0 then
<Anweisungen für gedrückten Taster>
else
<Anweisungen für Loslassen des Tasters>
end if


Wobei da die jeweilige Aktion immer auslöst, wenn die Hauptschleife ausgeführt wird. Besser ist es da, noch eine Variable für den Tasterstatus zu definieren, zB. so:


Dim status as boolean
status=0 '0=nicht gedrückt, 1=gedrückt

if PinA.0=0 and status=0 then
<Anweisungen für gedrückten Taster>
status=1
elseif PinA.0=1 and status=1 then
<Anweisungen für Loslassen des Tasters>
status=0
end if


Somit geht das Ganze beim Drücken nur einmal in den oberen Teil und beim Loslassen einmal in den unteren Teil. In den Malen dazwischen geht das Programm zwar auch in die Verzweigung, allerdings sind dann beide Bedingungen nicht erfüllt, wodurch dann eben gar nix passiert. Das Else kann in dem Fall einfach weggelassen werden. Sowas ist dann wichtig, wenn bei einem Tastendruck eine Variable nur einmal hochgezählt werden soll und nicht konstant hochzählt solange man drückt (da kann in wenigen ms schon einiges zusammenkommen). Braucht man häufiger mal sowas. Oder einfach, um einen Ausgang umzuschalten. Würde man das nicht so machen, würde der Ausgang dauernd umschalten und welchen Zustand der Ausgang beim Loslassen dann hat ist eher zufällig.

Ansonsten würde ich mich an deiner Stelle mal ein bisschen nach Grundkursen für Bascom umsehen. Ist an sich kein großes Hexenwerk, wenn man erstmal ein bisschen drin ist. Ich kann das hier empfehlen:
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/

AtomicIX
29.10.2014, 15:36
Nun wollte ich gerade ein Testprogramm übertragen und bekomme immer die Fehlermeldung:
Detected Micro ATMEGA32 does not match the selected Micro AT90CAN32

Was habe ich denn jetzt schon wieder kaputt gemacht. ?:(

EDIT: Sorry, habs gefunden, habe den Falschen Chip ausgewählt.

- - - Aktualisiert - - -

Ok, danke schön. Dann werde ich mal damit die Nacht verbringen.
Vielleicht habe ich ja morgen schon, mein erstes Programm. ( Motor An / Motor Aus)

AtomicIX
30.10.2014, 15:33
So, nun bin ich ne ecke schlauer geworden.
Habe über den Joystick die Richtung des Schrittmotors ändern können und einen 2 Stufen Filter gebaut.

Joystick in Mittelstellung: Stop
Stufe 1 vorwärts : linkslauf
Stufe 2 vorwärts: Stop
Stufe 1 rückwärts: rechtslauf
Stufe 2 rückwärts: Stop

Das Funktioniert auch soweit, jetzt weis ich nur nicht, wie ich da noch einen Tacktgeber/Timer rein bekomme.
Der Timer ist schon drinn, aber kann ich den Timer verändern mit meinem ADC oder muss ich mehrer Timer nehmen?




'################################################# ##
'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
'Config Adc.1 = Single , Prescaler = Auto , Reference = Internal
Start Adc
Dim W1 As Word , Channel As Byte

'Ocr1a = 10000
'Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1 , Compare A = Disconnect
'On Oc1a Timer1serv
'Enable Oc1a
'Enable Interrupts
Do

'############ Linker Schrittmotor

W1 = Getadc(2)
Print "Channel 0 " ; " value " ; W1
'Incr Channel

If W1 = 0 Then
Portd.6 = 1 'Schritmotor Ein
End If
If W1 => 1 Then
Portd.6 = 0 'Schrittmotor aus

End If



W1 = Getadc(1)
Print "Channel 0 " ; " value " ; W1
'Incr Channel
If W1 =< 1 Or W1 => 100 Then 'schnell
Portc.5 = 0 'Rechtslauf
Portc.3 = 0

End If
If W1 =< 101 Or W1 => 480 Then 'langsam
Portc.5 = 0 'Rechtslauf
Portc.3 = 1

End If


If W1 => 481 Or W1 =< 539 Then 'Stop
Portc.3 = 0
Else
End If


If W1 =< 540 Or W1 => 950 Then 'langsam
Portc.5 = 1 'linkslauf
Portc.3 = 1


End If
If W1 =< 951 Or W1 => 1022 Then 'schnell
Portc.5 = 1 'linkslauf
Portc.3 = 0

End If

Loop
End
'Timer1serv:
'Statt Eine Led Zum Blinken Zu Bringen Kann Hier
'Regelmässig Etwas Wichtiges Getan Werden
'Toggle Portc.3



'Return

Geistesblitz
30.10.2014, 17:19
Hmm, wie lässt du denn jetzt die Schrittsignale generieren? Normalerweise würde man da einen Timer nehmen und dem dann mittels einer Variablen die Zeit vorgeben, bis er wieder ausgelöst wird. Variable wird kleiner -> Timer löst häufiger aus, Variable wird größer -> Timer löst weniger häufig aus. In der ISR dann nur den Step-Ausgang kurz an- und wieder ausschalten. So kannst du dann die Geschwindigkeit des Steppers steuern.
Hier mal, wie es in einem meiner Codes steht:


Isr1:
Load Timer1 , Zeit
Porta.1 = 1
Porta.3 = 1
Porta.5 = 1
Waitus 10
Porta.1 = 0
Porta.3 = 0
Porta.5 = 0
Return

Wobei bei mir drei Schrittmotoren gleich angesteuert werden, die Step-Ausgänge befinden sich auf Porta.1, Porta.3 und Porta.5. Zeit hab ich bei mir einfach die Variable genannt, die für die ISR zuständig ist. Durch Load wird das gleich so verrechnet, dass die ISR erst in Zeit*Prescale Taktzyklen ausgelöst wird. Wenn beide Motoren unterschiedlich eingestellt werden sollen, wirst du wohl zwei Timer brauchen. Lies dir am besten mal den Abschnitt zu Timern im Tutorial durch, das wird da alles gut erklärt.

Ansonsten sehen deine If-Verzweigungen noch ein wenig wirr aus. Mach am besten mal die Einrückungen ordentlich, der Übersicht zuliebe. Und wenn hinter dem else nix steht, kannst du es auch weglassen. Und elseif verwenden, das ist günstiger als zwei ähnliche ifs hintereinander.
Der erste Teil in der Hauptschleife lässt sich beispielsweise so zusammenfassen:


if W1=0 then
Portd.6 = 1
else
Portd.6 = 0
end if

Wenn du eine Variable mehrfach abfragst, kannst du auch eine Case-Struktur verwenden, macht sich besser als zig ifs hintereinander.

AtomicIX
30.10.2014, 23:29
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.

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.





$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


&#39;TimerRelaod Werte mit "AVR Timer.exe" berechnet

Const Akku_leer = 63193 ****** ca. 0,3 Sekunden
Const Akku_halb_voll = 60849 &#39;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

Geistesblitz
31.10.2014, 10:49
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.

AtomicIX
31.10.2014, 12:01
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.




'################################################# ##
'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.


...
Timer0reload = Rechts_s1
Portc.4 = 0
Start Timer0
Case 439 To 584
Timer0reload = Stop_s0
Stop Timer0
...

Geistesblitz
31.10.2014, 13:07
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.

AtomicIX
31.10.2014, 16:01
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 :



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 :)

Peter(TOO)
31.10.2014, 18:45
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)

AtomicIX
31.10.2014, 23:20
'################################################# ##
'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


' 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.

Peter(TOO)
01.11.2014, 00:02
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)

AtomicIX
05.11.2014, 14:37
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.




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.

AtomicIX
07.11.2014, 11:42
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?




'************************************************* *****************************

$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

AtomicIX
28.11.2014, 13:42
Ich bin da jetzt noch mal einige Stunden dran gewesen, aber ich bekomme es einfach nicht hin.
Somit ist das Projekt gestorben.

Rabenauge
28.11.2014, 18:47
Nun gib doch nicht gleich auf....würde ich das tun, würd _gar_ nix fertig.
Was sind denn nen paar Stunden-die brauche ich andauernd mal für "Kleinigkeiten".
Legs nen paar Tage auf die Seite, beschäftige dich mit was anderem, oder üb nen paar Nummern kleiner, und dann mit frischem Mut wieder ans Werk.
Als Motivation: ich hab vorhin ne dreiviertle Stunde einen Fehler gesucht- der sich dann als ein lausiges Semikolon an der falschen Stelle herausstellte.:)