PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Pro-Bot 128 mit Bascom



Martinius11
29.08.2010, 15:23
Liebes Forum,

einige Wissen ja bereits das ich mit der Entwicklungsumgebung der C-Control 128 Pro nicht viel am Hut haben wolte und habe deshalb den Pro-Bot nach ISP umgerüstet und habe nun vor eine Bascom-Lib zuschreiben
ich bin auch schon ziemlich voran gekommen Leds, Odometrie und den
Bruzzer ich werde auch hier die Lib dann zum download zur Verfügung
stellen und hoffe auch auf viel Kritik da ich noch nicht Lange in Bascom programmiere also weißt mich auch jeden Fehler und Platz verschwendung hin den die 4-KB-Marke schramme ich immer wieder.

Lade bald den ersten Teil hoch.

bnitram
29.08.2010, 17:57
Dann noch viel Spaß!! :)

PS:
machst du das nur so oder hasst du nich die Original Lib in Basic??

Martinius11
29.08.2010, 21:44
Hier mal der erste Code:



$regfile = "m128def.dat"
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600

Encoderled Alias Portb.0
Config Encoderled = Output

Frontled Alias Portc.4
Config Frontled = Output

Frontlled Alias Portc.3
Config Frontlled = Output

Frontrled Alias Portc.2
Config Frontrled = Output

Backlled Alias Portc.1
Config Backlled = Output

Backrled Alias Portc.0
Config Backrled = Output

Buzzer Alias Portb.4
Config Buzzer = Output

Taster Alias Pine.4
Config Taster = Input
Porte.4 = 1




Frontled = 1
Frontlled = 1
Frontrled = 1
Backlled = 1
Backrled = 1
Encoderled = 0

Declare Sub Lineled(byval Status As Byte)
Declare Sub Flled(byval Status As Byte)
Declare Sub Frled(byval Status As Byte)
Declare Sub Blled(byval Status As Byte)
Declare Sub Brled(byval Status As Byte)
Declare Sub Encled(byval Status As Byte)
Declare Sub Bruzzer(byval Ton As Byte , Byval Laenge As Byte)
Declare Sub Intodometrie()
Declare Function Getmicro() As Word
Declare Function Getlsl() As Word
Declare Function Getlsr() As Word
Declare Function Getlinel() As Word
Declare Function Getliner() As Word
Declare Function Getakku() As Word
Dim Encleft As Integer
Dim Encright As Integer



Do

Call Bruzzer(0 , 120)

Loop




End









Sub Lineled(byval Status As Byte)


If Status = 1 Then

Frontled = 0

Elseif Status = 0 Then

Frontled = 1
End If

End Sub




Sub Flled(byval Status As Byte)

If Status = 1 Then

Frontlled = 0

Elseif Status = 0 Then

Frontlled = 1

End If

End Sub





Sub Frled(byval Status As Byte)

If Status = 1 Then

Frontrled = 0

Elseif Status = 0 Then

Frontrled = 1

End If

End Sub




Sub Blled(byval Status As Byte)
If Status = 1 Then
Backlled = 0
Elseif Status = 0 Then
Backlled = 1
End If

End Sub




Sub Brled(byval Status As Byte)

If Status = 1 Then
Backrled = 0
Elseif Status = 0 Then
Backrled = 1
End If
End Sub

Sub Encled(byval Status As Byte)
If Status = 1 Then
Encoderled = 1
Elseif Status = 0 Then
Encoderled = 1
End If

End Sub



Sub Intodometrie()

Encleft = 0
Encright = 0
Call Encled(1)
On Int7 Encoleft
On Int6 Encoright
Config Int7 = Falling
Config Int6 = Falling
Enable Int7
Enable Int6
Enable Interrupts
End Sub

Sub Bruzzer(byval Ton As Byte , Laenge As Byte)
Dim Count As Byte
For Count = 1 To Laenge
Config Timer0 = Timer , Prescale = 8
Timer0 = Ton
On Ovf0 On_ovf0
Enable Ovf0
Enable Interrupts
Waitms 5
Next Laenge
End Sub



Function Getmicro()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getmicro = Getadc(3)
End Function

Function Getlsl()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlsl = Getadc(4)
End Function

Function Getlsr()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlsr = Getadc(5)
End Function

Function Getlinel()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlinel = Getadc(1)
End Function

Function Getliner()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getliner = Getadc(2)
End Function

Function Getakku()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getakku = Getadc(0)
End Function

Encoleft:
Encleft = Encleft + 1
Return

Encoright:
Encright = Encright + 1
Return


On_ovf0:
Toggle Buzzer
Return


@bitram nein mich nerft einfach die IDE

bnitram
30.08.2010, 11:37
Nich shclecht deine Arbeit bis jetz :)

Mfg
bnitram

Martinius11
30.08.2010, 12:41
@bitram ich würde dir und allen anderen Pro-Bot 128 besitzern raten die Unit
via ISP zuprogrammieren dafür muss man zwar ein bischen löten und man muss eine C-Control 128 Pro Unit opfern aber es lohnt sich den Bot in anderen Sprachen programmieren zu können! Im Notfall kann man sich ja ne neue Unit kaufen. Und mit Umbaukosten von ca. 27€ ist das auch leicht machbar (Programmer und 10-Poliger Wannenstecker).

radbruch
30.08.2010, 14:00
Hallo

Ohne die C-Control zu opfern sollte es mit CCPro-Loader möglich sein, die mit Bascom erzeugten Hex-Dateien zu übertragen:

http://www.mikrocontroller.net/topic/134655
https://www.roboternetz.de/phpBB2/viewtopic.php?t=47484

Gruß

mic

Martinius11
11.09.2010, 22:11
Hier mal eine etwas neuere Version mit ADC und Motoransteuerrung:



$regfile = "m128def.dat"
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600
$baud = 19200


Encoderled Alias Portb.0
Config Encoderled = Output

Frontled Alias Portc.4
Config Frontled = Output

Frontlled Alias Portc.3
Config Frontlled = Output

Frontrled Alias Portc.2
Config Frontrled = Output

Backlled Alias Portc.1
Config Backlled = Output

Backrled Alias Portc.0
Config Backrled = Output

Buzzer Alias Portb.4
Config Buzzer = Output

Taster Alias Pine.4
Config Taster = Input
Porte.4 = 1




Frontled = 1
Frontlled = 1
Frontrled = 1
Backlled = 1
Backrled = 1
Encoderled = 0
Declare Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte)
Declare Sub Lineled(byval Status As Byte)
Declare Sub Flled(byval Status As Byte)
Declare Sub Frled(byval Status As Byte)
Declare Sub Blled(byval Status As Byte)
Declare Sub Brled(byval Status As Byte)
Declare Sub Encled(byval Status As Byte)
Declare Sub Bruzzer(byval Ton As Byte , Byval Laenge As Byte)

Declare Sub Intodometrie()
Declare Sub Motorstop()
Declare Function Getmicro() As Word
Declare Function Getlsl() As Word
Declare Function Getlsr() As Word
Declare Function Getlinel() As Word
Declare Function Getliner() As Word
Declare Function Getakku() As Word
Dim Encleft As Integer
Dim Encright As Integer





Do


Call Moveatspeed(220 , 220)


Loop

End


Sub Lineled(byval Status As Byte)


If Status = 1 Then

Frontled = 0

Elseif Status = 0 Then

Frontled = 1
End If

End Sub




Sub Flled(byval Status As Byte)

If Status = 1 Then

Frontlled = 0

Elseif Status = 0 Then

Frontlled = 1

End If

End Sub





Sub Frled(byval Status As Byte)

If Status = 1 Then

Frontrled = 0

Elseif Status = 0 Then

Frontrled = 1

End If

End Sub




Sub Blled(byval Status As Byte)
If Status = 1 Then
Backlled = 0
Elseif Status = 0 Then
Backlled = 1
End If

End Sub




Sub Brled(byval Status As Byte)

If Status = 1 Then
Backrled = 0
Elseif Status = 0 Then
Backrled = 1
End If
End Sub

Sub Encled(byval Status As Byte)
If Status = 1 Then
Encoderled = 1
Elseif Status = 0 Then
Encoderled = 1
End If

End Sub

Sub Motorstop()
Call Moveatspeed(220 , 220)
End Sub

Sub Intodometrie()

Encleft = 0
Encright = 0
Call Encled(1)
On Int7 Encoleft
On Int6 Encoright
Config Int7 = Falling
Config Int6 = Falling
Enable Int7
Enable Int6
Enable Interrupts
End Sub

Sub Bruzzer(byval Ton As Byte , Laenge As Byte)
Dim Count As Byte
For Count = 1 To Laenge
Config Timer0 = Timer , Prescale = 8
Timer0 = Ton
On Ovf0 On_ovf0
Enable Ovf0
Enable Interrupts
Waitms 1
Next Laenge
End Sub

Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte)

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1

Config Portb.7 = Output
Portb.7 = 1

Compare1a = Sleft
Compare1b = Sright

End Sub






Function Getmicro()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getmicro = Getadc(3)
End Function

Function Getlsl()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlsl = Getadc(4)
End Function

Function Getlsr()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlsr = Getadc(5)
End Function

Function Getlinel()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getlinel = Getadc(1)
End Function

Function Getliner()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getliner = Getadc(2)
End Function

Function Getakku()
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Getakku = Getadc(0)
End Function

Encoleft:
Encleft = Encleft + 1
Return

Encoright:
Encright = Encright + 1
Return


On_ovf0:
Toggle Buzzer
Return


Nun möcht ich aber noch eine Funktion(Sub) schreiben die den Roboter mittels Odometrie gerade ausfahren lässt. Leider haben meine bisherigen Versuche nur Misserfolg kann mir jemand sagen wie man das in Bascom am besten umsetzt.(Der Pro-bot 128 benutzt Int7 Int6 um die 6 weißen und 6 schwarzen Segmente über Fotodioden einzulesen)

Danke

Martinius11
12.09.2010, 20:57
Kann mir den keiner sagen wie man das am besten umsetzt ?

RP6conrad
13.09.2010, 20:17
Ein bischen Regeltechnic ist hier angewesen. Du kannst der Geschwindigkeit von beiden Motoren messen. Jeden 100 ms hat jeden Motor sofiel Pulsen weiter gelaufen. Jetzt muss du einfach das Unterschied zwischen beide Motoren aufaddieren. Das gibt dan ein Integral term. Diesen Term gibt ihr dan das Unterschied von Anfang an zwischen Linker und Rechter motor. Diesen Term kannst du wieder in die PWM Wert von jeden Antrieb verrrechnen. Sag mal Links 50 Pulsen hoher dan Rechts, dan geben wir die Linkse Antrieb 5%Weniger PWM, den Rechtse Antrieb 5% Mehr PWM. Jetzt hast du eine Verstarkungsfactor von 0.1 (50*0.1 = 5%). Die Kunst ist dan diese Factor so einzustellen das du eine Schnelle, aber stabile Regelung bekommst.
Das gleiche Spiel kann auch mit das reine Geschwindigkeitsunterschied, das ist dan das Proportional Anteil.
Stichwort : PID Regelung

Martinius11
14.09.2010, 18:14
Ja gut aber wie kann ich das alle 100ms abfragen ohne das der programmablauf andauernt unterbrochen wird?

Martinius11
21.09.2010, 17:18
Gut die Odometrie ist jetzt fertig ich hab aber noch ein Frage zum Acs, wie stark darf man da die Frequenz für die reichweite verändern ?

Martinius11
23.09.2010, 16:14
Nun ich hab mal ein Programm geschrieben natürlich klapt es nicht kann mir bitte jemand helfen ? danke



$regfile = "m128def.dat"
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600
$baud = 19200

Tsop Alias Portd.2
Config Tsop = Input

Ir Alias Porte.3
Config Ir = Output

Irledleft Alias Portd.3
Config Irledleft = Output

Irledright Alias Portd.5
Config Irledright = Output


Irledleft = 1
Irledright = 1

Declare Sub Acslow()
Declare Sub Acsmid()
Declare Sub Acshigh()
Declare Sub Acsoff()

Declare Function Acsleft() As Byte
Declare Function Acsright() As Byte

Config Timer2 = Timer , Prescale = 8
Timer2 = Acspwm
On Ovf2 On_ovf2
Enable Ovf2
Enable Interrupts

Call Acshigh()

Do

If Acsright() = 1 Then
Print 1
End If





Loop

End

Sub Acslow()
Acspwm = 225
End Sub

Sub Acsmid()
Acspwm = 228
End Sub

Sub Acshigh()
Acspwm = 231
End Sub

Sub Acsoff()
Irledleft = 1
Irledright = 1
End Sub


Function Acsleft()
Irledleft = 0
Irledright = 1

If Tsop = 1 Then
If Tsop = 1 Then
Acsleft = 1
End If
End If
Irledleft = 1
Irledright = 1
End Function

Function Acsright()
Irledleft = 1
Irledright = 0
If Tsop = 1 Then
If Tsop = 1 Then
Acsright = 1
End If
End If
Irledleft = 1
Irledright = 1
End Function

On_ovf2:
Timer2 = Acspwm
Toggle Ir
Return

radbruch
23.09.2010, 17:44
Hallo

Der TSOP benötigt ca. 6-10 Pegelwechsel der Trägerfrequenz bevor er seinen Eingang umschaltet. Wenn ich mich recht erinnere wird sein Ausgang Low wenn das Trägersignal erkannt wird. Hier wird vermutlich nicht viel Unterschied zwischen den Lesungen entstehen können:

If Tsop = 1 Then
If Tsop = 1 Then

Ich löse das meist mit einer Hilfsvariablen die in der ACS-Funktion auf die Anzahl der zu wartenden Schwingungen gesetzt und in der ISR runtergezählt wird:


$regfile = "m128def.dat"
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600
$baud = 19200

Tsop Alias Portd.2
Config Tsop = Input

Ir Alias Porte.3
Config Ir = Output

Irledleft Alias Portd.3
Config Irledleft = Output

Irledright Alias Portd.5
Config Irledright = Output


Irledleft = 1
Irledright = 1

Declare Sub Acslow()
Declare Sub Acsmid()
Declare Sub Acshigh()
Declare Sub Acsoff()

Declare Function Acsleft() As Byte
Declare Function Acsright() As Byte

Dim Acspwm As Byte
Dim Pulsanzahl As Byte

Config Timer2 = Timer , Prescale = 8
Acspwm = 225
Timer2 = Acspwm
On Ovf2 On_ovf2
Enable Ovf2
Enable Interrupts

Call Acshigh()

Do

If Acsright() = 0 Then
Print 0
End If

Loop

End

Sub Acslow()
Acspwm = 225
End Sub

Sub Acsmid()
Acspwm = 228
End Sub

Sub Acshigh()
Acspwm = 231
End Sub

Sub Acsoff()
Irledleft = 1
Irledright = 1
End Sub


Function Acsleft()
Irledleft = 0
Irledright = 1
Pulsanzahl = 20
While Pulsanzahl > 0
Wend
Acsleft = Tsop
Irledleft = 1
Irledright = 1
End Function

Function Acsright()
Irledleft = 1
Irledright = 0
Pulsanzahl = 20
While Pulsanzahl > 0
Wend
Acsright = Tsop
Irledleft = 1
Irledright = 1
End Function

On_ovf2:
Timer2 = Acspwm
Toggle Ir
If Pulsanzahl > 0 Then Pulsanzahl = Pulsanzahl -1
Return

Das ist allerdings ungetestet. Ob der TSOP mehr Impulse benötigt, wenn die Frequenz nicht genau passt, kann ich nicht sagen. Wenn ich mich nicht verrechnet habe sollten ca. 25 Timertakte zwischen den ISR-Aufrufen etwa 36kHz ergeben.

Gruß

mic

Martinius11
23.09.2010, 20:35
Leider Funktioniert es immer noch nicht es wird dauernt 0 gesendet.
Hast du noch irgenteine Idee ?

radbruch
23.09.2010, 21:23
...es wird dauernt 0 gesendet.Das muss nicht unbedingt ein Fehler sein. Wird auch eine 0 angezeigt, wenn sich gar keine Trägerfrequenz im Raum befindet, weil z.B. das "Toggle Ir" in der ISR auskommentiert ist?

Martinius11
23.09.2010, 21:27
ja aber wie kann man es dann machen soll ich das ganze neu angehen ?
wie würdest du es angehn ?

radbruch
23.09.2010, 22:35
Hallo

Ich bin das schon mal angegangen. Als Basis diente mir die allseits bekannte IR-Abstandsmessung beim asuro:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=473142#473142

Aufgebohrt auf zwei gepulste Kanäle mit einem probot als Hardware:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=459661#459661

Weiterentwickelt mit der bee:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=52115

Und letzlich die Bascom-Variante mit der bee:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=480966#480966
http://www.youtube.com/watch?v=upszgUzs69g

Die bee läuft mit 15MHz. Für einen schnellen Test kannst du vermutlich mein Timersetup verwenden.

Gruß

mic

Martinius11
07.10.2010, 22:17
Gut jetzt ist das auch gelöst aber das nächste Problem ist schon da die lib ist so gut wie fertig aber ich habe einen Fehler in der Go-Sub mit dem Weg
kann mir da einer Helfen? Bascom Schreibt das es anscheinend die eigentlich viel kleinere Variable nicht in die Große passt.

Sub Go(byval Speed As Byte , Byval Dis As Byte)
Call Moveatspeed(speed , Speed)
Encleft = 0
Encright = 0
Local Relweg As Long
Local Strecke As Integer
Relweg = Encleft + Encright
Relweg = Relweg / 2
Strecke = Dis / 12


Do
Call Geradefahren
Loop Until Relweg > Strecke

Call Moveatspeed(0 , 0)
Waitms 10
End Sub

Danke

Martinius11
25.10.2010, 18:27
Ich hab jetzt eigentlich alles fertig ausser die Funktionen zur regullierten Fahrt. Mir macht die funktion zum Feradefahren zu schaffen. Er will einfach nicht gerade fahren. Kann irgendtjemand einen Fehler finden. danke.





$regfile = "m128def.dat" 'es handelt sich um einen ATmega128
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600 'Systemtakt 14.7456 MHZ
$baud = 19200 'UART Übertragungsgeschwindigkeit

Encoderled Alias Portb.0 'es wird auf beide Encoder der Radencoder
Config Encoderled = Output 'zugegriffen

Motorleft Alias Portb.6 'Motor-PWM-Leitung-Links
Config Motorleft = Output

Motorright Alias Portb.5 'Motor-PWM-Leitung-Rechts
Config Motorright = Output

Motorenable Alias Portb.7 'Motorenable
Config Motorenable = Output

Encoderled = 0 'Die Encoder-Leds sind wieder über Ground Angeschlossen
Motorenable = 0 'Motoren sind aus

Declare Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte) 'Stelt die Motor-PWM ein

Declare Sub Encled(byval Status As Byte) 'schaltet die Encoder-Led bei 1 ein

Declare Sub Intodometrie() 'konfiguriert die Encoder der Odmetrie und setzt Encleft und encright auf null

Declare Sub Geradefahren() 'vergleicht die Odometriewerte und regelt nach

Dim Encleft As Word 'der Zwischenspeicher für die Werte des linken Odometrie Encoders
Dim Encright As Word 'der Zwischenspeicher für die Werte des rechten Odmetrie Encoders

Dim Encoderenable As Byte 'nur wenn diese Varriable 1 werden die Odometrie-Encoder-Impulse gezählt

Dim Sw0ys As Long 'Stopwatch 0 wird für die Sub Gerdefahren benötigt
Dim Sw0ms As Long

Config Timer3 = Timer , Prescale = 8 'Timer 3 (Stopwatches) wird als Timer eingestellt und mit den Prescaler 8 versehen
Timer3 = 63693 'Timer 3 wird auf 63693 eingestellt dies passiert auch nach jedem Interrupt
On Ovf3 On_ovf3 'wenn Timer 3 überläuft springt das Programm zu On_ovf3
Enable Ovf3 'der Overflow von Timer 3 wird aktiviert
Enable Interrupts 'Interrups werden eingeschaltet
Start Timer3 'Timer 3 wird gestartet

Call Intodometrie()
Do

Call Moveatspeed(240 , 240)
Call Geradefahren()

Loop

End

Sub Encled(byval Status As Byte) 'Eigentlich unnötig aber der Vollständigkeit halber
If Status = 1 Then
Encoderled = 1
Elseif Status = 0 Then
Encoderled = 1
End If

Sub Intodometrie() 'Konfiguriert die Odometrie

Encleft = 0 'Encleft wird zurückgesetzt
Encright = 0 'Encright wird zurückgesetzt
Encoderenable = 1 'die Odometrie-Encoder-Impulse können nun gezählt werden
Call Encled(1) 'die Encoder-Leds werden eingeschaltet
On Int7 Encoleft 'wenn ein Impuls vom linken Encoder kommt zu Encoleft springen
On Int6 Encoright 'wenn ein Impuls vom rechten Encoder kommt zu Encoright springen
Config Int7 = Falling 'springen wenn ein Impuls abgeschlossen ist
Config Int6 = Falling 'springen wenn ein Impuls abgeschlossen ist
Enable Int7 'Int7 freischalten
Enable Int6 'Int6 freischalten
Enable Interrupts 'Interrups aktivieren
End Sub

Sub Geradefahren() 'Sub für die Gerade Fahrt des Roboters
Local Encdif As Integer 'Lokale Varriable für den Unterschied von Encleft und Encright
Local Encregler As Integer 'Lokale Varriable für das nachregeln der Geschwindigkeit
Sw0ms = Sw0ys / 10 'die ys von Stopwatch 0 werden in ms umgewandelt
If Sw0ms = 10 Then 'sind 10ms vergangen ?
Sw0ys = 0 'Stopwatch 0 zurück setzen
If Encleft > Encright Then 'werden mehr Odometrie-Encoder-Impulse links gezählt ?
Encdif = Encleft. - Encright 'Encoder Differenz berechnen
Encregler = Encdif * 0.1 'Nachregelungsvarriable berechnen, diese berechnet sich aus 10% der Encoder Differenz
Compare1a = Compare1a + Encregler 'PWM-Links um Nachregelungsvarriable erhöhen
Compare1b = Compare1b - Encregler 'PWM-Rechts um Nachregelungsvarriable verringern
Encleft = 0
Encright = 0
Elseif Encleft < Encright Then 'werden mehr Odometrie-Encoder-Impulse rechts gezählt?
Encdif = Encright - Encleft 'Encoder Differenz berechnen
Encregler = Encdif * 0.1 'Nachregelungsvarriable berechnen
Compare1a = Compare1a - Encregler 'PWM-Links um Nachregelungsvarriable verringern
Compare1b = Compare1b + Encregler 'PWM-Rechts um Nachregelungsvarriable erhöhen
Encleft = 0
Encright = 0
End If
End If
End Sub

Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte) 'Sub zur Regelung der Motorgeschwindikeiten

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 'Timer 1 wird als zwei 8-Bit PWM Leitungen mit dem Prescaler 1 konfiguriert
Start Timer1 'Timer 1 wird gestartet
Motorenable = 1 'Motoren werden entsperrt

Compare1a = Sright 'PMW-A entspricht der linken Geschwindikeit
Compare1b = Sleft 'PWM-B entspricht der rechten Geschwindikeit

End Sub

Encoleft: 'Interrupt-Rotine die ausgelöst wird wenn links ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encleft = Encleft + 1
End If
Return

Encoright: 'Interrupt-Rotine die ausgelöst wird wenn rechts ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encright = Encright + 1
End If
Return

On_ovf3: 'Hierher wird wenn Timer 3 überläuft
Timer3 = 63693
Sw0ys = Sw0ys + 1
If Sw1enable = 1 Then
Sw1ys = Sw1ys + 1
End If
Return

radbruch
25.10.2010, 20:45
Hallo

Was zählst du denn da?


Encoleft: 'Interrupt-Rotine die ausgelöst wird wenn links ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encleft = Encleft + 1
End If
Return

Encoright: 'Interrupt-Rotine die ausgelöst wird wenn rechts ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encright = Encright + 1
End If
Return

Viele Funktionsgruppen des probot sind nahezu identisch vom asuro abgekupfert. Einen direkten Vergleich hatte ich hier mal gemacht:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=49556

So ist, neben dem Aufbau der Antriebe (beim asuro ist Stellung der Ritzen zueinander besser), auch die Odometry fast völlig identisch. Deshalb gelten alle Odo-Beschreibungen für den asuro auch uneingeschränkt für den Probot!

Wesentlich ist, dass die Odometry keine "Impulse" erkennt, sondern die Helligkeit vor den Odo-Sensoren misst. In Abhängigkeit von der Stellung der Codescheibe, und dem zusätzlichen Fremdlicht, schwanken die gemessenen Werte zwischen einem minimalen und einem maximalen Wert. Der Trick ist nun, aus diesen Werten einen Segmentwechsel der Codescheibe zu erkennen und diese Wechsel in Radumdrehungen umzurechnen.

Um das Umzusetzen gibt es verschiedene Ansätze und viele Beispiele in C. In Bascom könntest du das als Startpunkt für deine probot-Odometry verwenden:
http://med.hro.nl/kemjt/Asuro/Asuro_Bascom.htm
(Link aus http://www.arexx.com/forum/viewtopic.php?f=9&t=468)

Zum Geradeausfahren reicht es allerdings nicht, nur die Raddrehung genau zu erfassen. Aber das wirst du selbst noch bemerken.

Weiterhin viel Spass und Erfolg.

Gruß

mic

Martinius11
25.10.2010, 22:43
Nun ich dachte mir es wäre praktisch das zählen der Encoder auszschalten
für das fahren bestimmter Strecken und so zählt er nur wenn Encoderenable 1 ist. Encleft und Encright zählen die einzeilnen impulse. das mit dem asuro muss ich mir genauer ansehen aber vielen dank

radbruch
25.10.2010, 23:29
Hallo

In der Beschreibung des asuro wird es so erklärt:

9.2.11. void OdometrieData(unsigned int *data)
Die Refl exlichtschranke wird ausgewertet. Die Leuchtdioden (D13, D14) werden aktiviert und die
A/D-Wandler-Werte der Fototransistoren (T11, T12) zurückgegeben. Wie in der Funktion LineData
() muss ein Speicherbereich mit zwei Integerwerten übergeben werden, der dann von der
Funktion gefüllt wird. Der erste Integerwert enthält den Wandler-Wert des linken (T11), der zweite
Integerwert den des rechten Fototransistors (T12). Maximale Helligkeit entspricht einem Wert von
’0’ dunkel entspricht einem Wert von ’1023’ 5 . Die beiden Extremwerte werden normalerweise nicht
erreicht, der Messwert bewegt sich irgendwo dazwischen.
Beispiel:
Auslesen der Refl exlichtschranke
unsigned int data[2]; //Speicher bereitstellen
.
.
OdometrieData(data);
data[0] enthält den Wert vom linken Fototransistor (T11)
data[1] enthält den Wert vom rechten Fototransistor (T12)
Um Missverständnissen vorzubeugen: OdomertieData() liest nicht die Drehzahl direkt aus,
sondern nur die aktuelle Helligkeit der Geberscheibe an der Lichtschranke. Eine Auswertung der
Helligkeitswerte, ein Zählen der Hell-Dunkel-Übergänge und die Bestimmung der Drehzahl des
Rades daraus bleibt dem Programmierer überlassen!

Wie das beim probot und seinem CC-Pro umgesetzt wurde weiß ich nicht.

Gruß

mic

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=428214

Martinius11
26.10.2010, 10:04
das heißt also wenn ein signal über die interrupt leitung kommt muss ich das erst mit dem adc auswerten und dann speichern?

radbruch
26.10.2010, 15:52
Hallo

Es wird überhaupt kein Interrupt ausgelöst werden, weil die Spannungspegel an den Eingängen nicht sicher auf low runtergehen. Wenn einer ausgelöst werden würde, müstest du nicht mehr den Spannungswert ermitteln ;)

Normalerweise pollt man den ADC-Eingang und wartet, bis ein unterer Schwellwert unterschritten oder ein oberer Schwellwert überschritten wird. Dann erhöht man den Zähler und wartet auf den nächsten Schwellwertübergang.

Wichtig ist eine gute Abschirmung und Ausrichtung der Sensoren, kein axiales Spiel am Codescheibenzahnrad, saubere (eventuell nachgeschwärzte) Codescheiben und nichteiernde Räder.

Gruß

mic

Martinius11
26.10.2010, 16:27
Ich sehe grade das ich garkeine adc-Pins an die Encoder angeschlossen sind
Int 6 und Int 7 hab keine zusatz funktion als ADC man muss also die Interrups zählen. So steht es auch im Buch:

"Unsere Rad-encoder (Odometer, ähnlich wie der Kilometerzähler im Auto) arbeitet wie eine Reflexlichtschranke. die dioden D3 und D2(sender)
leuchten die Taktscheiben des Antriebs an und die beiden Fototransitoren T3 und T4 (Empfänger) empfangen das reflektierete Signal imer dann, wenn ein weißes Feld auftaucht, und schalten dann auf masse durch. Die Fototransistoren arbeiten somit wie ein Schalter, der bei Licht geschlossen wird." Zitat Ende


Hab ich jetzt dann mit meiner Grundsatzt idee recht gehabt oder hab ich da
was ganz falsch mit gegrigt ?

radbruch
26.10.2010, 16:45
Hallo

Du hast vollkommen recht, die Signale gehen gar nicht auf den ADC. Erstaunlich.

Auf die Idee war ich zwar auch gekommen und hatte auch schon versucht die Pegel nur digital als high oder low zu erfassen. Beim asuro und meinem probot hatte es nicht funktioniert. Deshalb gehe ich davon aus, dass es auch mit dem Mega128 nicht funktionieren wird. Da hilft nur eins: Ausprobieren.

Dass die Entwickler des asuro diese einfache Auswertung der Codescheiben nicht erkannt haben sollen scheint mir sehr unwahrscheinlich.

Gruß

mic

Martinius11
27.10.2010, 22:29
Also ich hab jetzt mal ein Paar Änderungen am Programm getätigt:



Encoderleft Alias Pine.7
Config Encoderleft = Input
Encoderleft = 1

Encoderright Alias Pine.6
Config Encoderright = Input
Encoderright = 1

Hab jetzt mal die Encoder als Eingänge definiert um auf Nummer sicher zu gehen und den Pull Up-Wiederstand aktiviert.



Config Int7 = Low Level 'springen wenn Ground ist
Config Int6 = Low Level 'springen wenn Ground ist


Ich hab statt Falling mal Low Level genommen ich hatte zwar eigentlich
gedacht dass das selbe ist da ja das Signal von High auf Low fällt aber
bitte

wenn ich irgentwas vergessen habe sagt es mir einfach ich werde mmorgen das dann mal genauer ausprobieren und dann die Ergebnisse posten den es ist sicher auch für den Asuro nützlich den es entlastet den Atmega, wenn er nur ein paar Interrups auslöst als wenn er dauernt das ADC abfrägt. Und danke nochmals Radbruch für deine Unterstüzung.

radbruch
28.10.2010, 08:42
Hallo

Naja, wirklich geholfen habe ich bisher ja noch nicht.

Ich bin immer noch verwirrt, weil ich nicht damit gerechnet hatte, dass die Odometry angeblich ohne ADC funktionieren soll. Ein Blick in die Beispielprogramme (http://www.c-control-pro.de/c-robotics/PRO-BOT128%20Demos.zip) bestätigt es aber:


Sollte Ihr PRO-BOT128 nicht Geradeausfahren, sondern sich nur im
Kreis drehen oder die Wegstrecke nicht stimmen,
müssen die Odometer-Sensoren (D2, T3 sowie T3, D4) justiert
werden. Dies kann sich durchaus als "Gefummel" herausstellen!
Die Bauteile D2, T3 sowie T3, D4 sollten dabei vorsichtig Richtung
Encoderscheiben gedrückt werden. Als Encoderscheibe wurde in
diesen Beispiel, die mit den vier schwarzen Flächen verwendet.
Es hilft auch zudem die Encoderscheiben mit schwarzem Edding-Stift
nachzuschwärzen. Hier ist ein wenig Fingerspitzengefühl und Ausdauer
gefragt ;-) Zudem sollte es nicht zu hell sein, da die
Foto-Transistoren bereits bei Sonnen-Einstrahlung durchsteuern.
(Beschreibung des Autors in der Datei GO_Odometer.cc)

Wenn T3 oder T4 durchsteuert, dann sollte am betreffenden Eingang ein Low anliegen. Wenn sie Sperren sollte es ein High sein. Laut Datenblatt des Mega128 (Seite 320, Anhang) sollte der Low-Pegel maximal 0,2V(!) sein, ab 0,6V wird sicher ein High erkannt. Der entsprechende ADC-Wert wäre dann 1023/5V*0,2V=41.

Obwohl ich mich an minimale ADC-Werte um 150 erinnere sollte das nach dem Datenblatt des LPT80A (http://www.c-control-pro.de/c-robotics/PRO-BOT128%20Datasheets.zip) durchaus möglich sein. Wieviel hell der LPT80A benötigt um wirklich auf die 150mV zu kommen kann ich aber nicht abschätzen.

Ich bin echt neugierig ob dir das gelingen wird.

Gruß

mic

Martinius11
28.10.2010, 19:15
Es funktioniert (teilweise) die Impulse werden rechts bei der config falling gezählt aber , da liegt auch mein Problem links nicht die Encoderleitung liegt immer auf ground was soll ich tun ist der Encoder kaputt?

radbruch
30.10.2010, 02:55
Hallo

Lötbrücke, Bauteile vertauscht, Bauteile beim Einlöten geschrottet, Auslöten und Pegel messen.. Es gibt viele Möglichkeiten.

Das mit der digitalen Auswertung läßt mir keine Ruhe. Ich bin mir sicher, das habe ich mit meinem orginalen asuro getestet und es hatte nicht funktioniert. Nun habe ich das mit meinem probot umgesetzt (wegen der fortgeschrittenen Stunde nicht in Bascom) und tatsächlich, es scheint zu funktionieren:


#include "asuro-probot.h"
#include "asuro-probot.c"

unsigned int data[2];
char c, pin_change=0;

int count_l=0, count_r=0, status_l, status_r;

int main(void)
{
Init();
MotorSpeed(150, 150); // Antriebe starten und Beschleunigen
Msleep(1000);
StatusLED(RED);

OdometrieData(data); // Startwerte setzen
c=PINC;
status_l = c & 2;
status_r = c & 1;

while((count_l + count_r) < 100)
{
c=PINC; // Pinstatus einlesen

if(status_l != (c & 2)) // links?
{
status_l = c & 2;
count_l++;
pin_change += 2;
}

if(status_r != (c & 1)) // rechts?
{
status_r = c & 1;
count_r++;
pin_change += 1;
}

if(pin_change != 0) // Bei Statuswechsel Werte zum Terminal senden
{
pin_change=0;
PrintInt(count_l);
SerWrite(" ", 1);
PrintInt(count_r);
SerWrite("\n\r", 2);
}
}
MotorSpeed(0,0);
StatusLED(GREEN);
while(1); // fertig
return 0;
}

Könnte das mal jemand mit einem orginalen asuro testen?

Gruß

mic

Martinius11
30.10.2010, 09:02
Ich ahb jetzt mal ein neues paar Encoder bestellt. Ich muss den linken irgentwie durchgeschmört haben da er ja immer auf Ground zieht.

Martinius11
31.10.2010, 01:45
gut jetzt funktioniert alles ich hatte bei meiner isp erweiterung ausversehen eine dünne leiterbahn durchtrennt. Habe übrigens den Pro-Bot 128 mit einem
Spannungsregler versehen werde die Anleitung bald auf meiner Website posten.

Martinius11
18.11.2010, 19:35
Der Wahnsinn kommt wieder über mich selbst das Einfachst Programm zum Abfahren einer Strecke funktioniert nicht. Ich weiß keinen rat mehr weiß einer
Wo ein Fehler stecken könnte ?



$regfile = "m128def.dat" 'es handelt sich um einen ATmega128
$framesize = 42
$swstack = 32
$hwstack = 32
$crystal = 14745600 'Systemtakt 14.7456 MHZ

Encoderled Alias Portb.0 'es wird auf beide Encoder der Radencoder
Config Encoderled = Output 'zugegriffen

Encoderleft Alias Pine.7
Config Encoderleft = Input
Encoderleft = 1

Encoderright Alias Pine.6
Config Encoderright = Input
Encoderright = 1

Motorleft Alias Portb.6 'Motor-PWM-Leitung-Links
Config Motorleft = Output

Motorright Alias Portb.5 'Motor-PWM-Leitung-Rechts
Config Motorright = Output

Motorenable Alias Portb.7 'Motorenable
Config Motorenable = Output

Encoderled = 0 'Die Encoder-Leds sind wieder über Ground Angeschlossen
Motorenable = 0 'Motoren sind aus

Declare Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte) 'Stelt die Motor-PWM ein
Declare Sub Encled(byval Status As Byte) 'schaltet die Encoder-Led bei 1 ein
Declare Sub Intodometrie() 'konfiguriert die Encoder der Odmetrie
Declare Sub Go(byval Speed As Byte , Byval Dis As Word) 'Roboter fährt eine bestimmte Strecke in cm
Dim Encleft As Word 'der Zwischenspeicher für die Werte des linken Odometrie Encoders
Dim Encright As Word 'der Zwischenspeicher für die Werte des rechten Odmetrie Encoders
Dim Encoderenable As Byte 'nur wenn diese Varriable 1 werden die Odometrie-Encoder-Impulse gezählt
Encoderenable = 1 'Die Odometrie-Encoder-Impulse werden im Grundzustand gezählt
Call Intodometrie()
Call Go(220 , 1000)
Do




Loop

End


Sub Encled(byval Status As Byte) 'Eigentlich unnötig aber der Vollständigkeit halber
If Status = 1 Then
Encoderled = 1
Elseif Status = 0 Then
Encoderled = 1
End If

End Sub


Sub Intodometrie() 'Konfiguriert die Odometrie

Encleft = 0 'Encleft wird zurückgesetzt
Encright = 0 'Encright wird zurückgesetzt
Encoderenable = 1 'die Odometrie-Encoder-Impulse können nun gezählt werden
Call Encled(1) 'die Encoder-Leds werden eingeschaltet
On Int7 Encoleft 'wenn ein Impuls vom linken Encoder kommt zu Encoleft springen
On Int6 Encoright 'wenn ein Impuls vom rechten Encoder kommt zu Encoright springen
Config Int7 = Falling 'springen wenn Ground ist
Config Int6 = Falling 'springen wenn Ground ist
Enable Int7 'Int7 freischalten
Enable Int6 'Int6 freischalten
Enable Interrupts 'Interrups aktivieren
End Sub


Sub Moveatspeed(byval Sleft As Byte , Byval Sright As Byte) 'Sub zur Regelung der Motorgeschwindikeiten

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 'Timer 1 wird als zwei 8-Bit PWM Leitungen mit dem Prescaler 1 konfiguriert
Start Timer1 'Timer 1 wird gestartet
Motorenable = 1 'Motoren werden entsperrt

Compare1a = Sright 'PMW-A entspricht der linken Geschwindikeit
Compare1b = Sleft 'PWM-B entspricht der rechten Geschwindikeit

End Sub

Sub Go(byval Speed As Byte , Byval Dis As Byte)

Local Strecke As Long
Local Relencoder As Long
Local Encodersp As Long
Call Moveatspeed(speed , Speed)
Encleft = 0
Encright = 0

Strecke = Dis / 12
Strecke = Strecke * 6
Strecke = Strecke * 2


Do
Relencoder = Encleft + Encright
Relencoder = Relencoder / 2

Loop Until Relencoder >= Strecke
Call Moveatspeed(128 , 128)
Waitms 10





End Sub

Encoleft: 'Interrupt-Rotine die ausgelöst wird wenn links ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encleft = Encleft + 1
End If
Return

Encoright: 'Interrupt-Rotine die ausgelöst wird wenn rechts ein Odometrie-Encoder-Impuls kommt
If Encoderenable = 1 Then
Encright = Encright + 1
End If
Return


Danke