PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : NIBOBee mit BASCOM Programmieren



pinsel120866
28.11.2009, 09:46
In diesem Threat werden Programme und Fragen gepostet, die sich um das Thema BASCOM mit der Bee drehen.

Gleich mal mein Programm wo ich ein SRF05 an die Bee angeschlossen habe:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Entfernung wird gemessen und in Zentimetern über
'RS232 ausgegeben
'Autor: Pinsel120866
'################################################# ##

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600
$hwstack = 32
$framesize = 32
$swstack = 32
Dim Zeitmessung As Word
Dim Entfernung As Word
Wait 1
Print "**** SRF05 mit NIBOBee *****"
Print "Entfernung in cm anzeigen"
Print " "
Config Pinc.2 = Output[
Do
Portc.2 = 0
Pulseout Portc , 2 , 40
Pulsein Zeitmessung , Pinc , 2 , 1
Zeitmessung = Zeitmessung * 10
Entfernung = Zeitmessung / 58
Print "Entfernung: " ; Entfernung ; " cm"
Wait 1
Loop

Noch eine Frage an die BASCOM-Profis:

Wie werden die Motoren der NIBOBee mit BASCOM angesteuert?

pinsel120866
28.11.2009, 17:05
Hmm, vielleicht hätte ich diesen Threat ins BASCOM-Forum stellen sollen. Jetzt habe ich den ganzen Nachmittag damit verbracht aber ich komme einfach nicht drauf wie die Motoren richtig angesteuert werden.

Hat keiner Erbarmen mit mir und gibt mit einen Tipp?

radbruch
28.11.2009, 18:09
Hallo

*lol* Ich bin ja auch kein Bascom-Guru, deshalb würde ich einfach das Timer1-Setup der nibobee-Lib (oder des RP6) eins zu eins nach Bascom übersetzen. Profis würden wohl den passenden Config-Timer-Befehl von Bascom verwenden. Als C-Anwender braucht man aber gelegentlich reichlich Zeit um die kleinen Ungereimtheiten der Bascom-Configs zu ergründen, deshalb führt das direkte Manipulieren der Timerregister wohl schneller zum Ziel. Wenn der Timer mal läuft und die OC1x-Pins richtig ansteuert werden, braucht man nur noch die OCR1x-Register mit dem gewünschten PWM-Wert zu laden und mit PD6/7 die jeweilige Drehrichtung auszuwählen. Ich denke, das wirst du hinbekommen.

Gruß

mic

Thomas$
28.11.2009, 18:15
wo hängen die motoren dran? wenn sie an den hardware pwm ins hängen guck einfach mal nach pwm bsp programmen im rn-wiki oder bei den bascom bsp programmen. ansonsten mal probiern den jeweiligen pin einschalten und dann nach softwarepwm suchen

radbruch
28.11.2009, 18:20
Der Motortreiber hängt an den Hardware-PWM-Pins OC1A/B und an PD6/7 für die Drehrichtung. Das RN-Wissen ist natürlich auch ein toller Tipp:
http://www.rn-wissen.de/index.php/Bascom_und_PWM

pinsel120866
28.11.2009, 19:44
OK,

ich weiss nur nicht wie ich mit einem PIN umschalten kann. Mein Code sieht so aus:



$regfile = "m16def.dat"
$crystal = 15000000

Declare Sub Motordir(byval Motleftdir As Byte , Byval Motrightdir As Byte)
Declare Sub Motorspeed(byval Motleftpwm As Byte , Byval Motrightpwm As Byte)
Init:

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

Const Driverwd = 0
Const Drivefwd = 1

Main:
Do
Call Motordir(drivefwd , Drivefwd)
Call Motorspeed(100 , 100)
Wait 1
Call Motorspeed(0 , 0)
Wait 1
Loop

Sub Motordir(byval Motleftdir As Byte , Byval Motrightdir As Byte)
Ddrd.6 = 1
Ddrd.7 = 1
If Motleftdir.0 = 0 Then
Portd.6 = 1
Else
Portd.6 = 0
End If
If Motrightdir.0 = 0 Then
Portb.7 = 1
Else
Portb.7 = 0
End If
End Sub

Sub Motorspeed(byval Motleftpwm As Byte , Byval Motrightpwm As Byte)
Ddrd.5 = 1
Ddrd.4 = 1
Pwm1a = Motleftpwm
Pwm1b = Motrightpwm
End Sub

pinsel120866
29.11.2009, 08:00
Ich komme einfach nicht weiter. Mit dem oben gezeigtem Programm drehen sich die Räder, aber beide in entgegengesetzte Richtung. Mir ist das einfach nicht klar.

Wie muss ich nun das Programm abändern dass ich die Drehrichtung umsteuern und die Geschwindigkeit anpassen kann?

Bitte nochmals um Hilfe.

oberallgeier
29.11.2009, 08:23
Hallo Nachbar,

in Bascom bin ich ja die bekannte Doppelnull - wo ich doch schon in Cäh ne Null bin. Aber hier mal auf die Schnelle ein Schnippsel, wie ICH bei meinen Döschen die Motoren schalte (ist aber ein H-Brücken-IC). Weiß ja nicht ob Dir das hilft. In den Wahrheitstabellen der H-Brücken-ICs gibts vielleicht auch ne Hilfe/Erklärung.

Initialisierung:
/* ================================================== ============================ */
/* == PWM-Routinen zur Motoransteuerung ======================================= */
void TC0PWM_init(void) //Init Timer/Counter0 für Erzeugung des PWM-Signals
{
TCCR0A |= (1<<COM0A1)|(1<<COM0B1); //Clear/set OC0A/OC0B on Compare Match,
// doc S102 , OC0A/OC0B ist Port PD6/D5
TCCR0A |= (1<<WGM01)|(1<<WGM00); // Fast PWM, TOP=0xFF=dez255, doc S104
// das ergibt aus 20 MHz mit Prescaler 1/64 1220 Hz
TCCR0B |= (1<<CS01)|(1<<CS00); // Prescaler ist clk/64 doc S106
TIMSK0 &= ~(1<<OCIE0A)|(1<<OCIE0B); // Tmr/Cntr0 Oput CompB Match intrrpt dsabld
TIMSK0 &= ~(1<<TOIE0); // Tmr/Cntr0 Overflow interrupt disabled
OCR0A = 0; // PWM auf Null setzen
OCR0B = 0; // PWM auf Null setzen
Iz_diff0 = 0;
isum12 = isum34 = 0;
ie_mot12 = ie_mot34 = 0;
ie_alt12 = ie_alt34 = 0;
}
/* ================================================== ============================ */
void setPWMrechts(uint8_t speed) //Geschwindigkeit Motor 12 (rechter)
{OCR0B = speed;} // PWM auf PD5/OC0B, korrig. 24mrz09
/* ================================================== ============================ */
void setPWMlinks(uint8_t speed) //Geschwindigkeit Motor 34 (linker)
{OCR0A = speed;} // PWM auf PD6/OC0A, korrig. 24mrz09
/* ================================================== ============================ */
...
und die verschiedenen Richtungen:
// Drehrichtungsbefehle für Motor 1,2 = "rechter" Motor
void M12pos (void) // Mot12 dreht im Uhrzeigersinn = neg. math.
{ PORTB |= (1<<PB4); PORTD &= ~(1<<PD4); mdir12 = 1; }
// r r r r r r r Motor 1,2 = rechter Motor r r r r r r
void M12neg (void) // Mot12 dreht im mathematisch positiven Drehsinn
{ PORTB &= ~(1<<PB4); PORTD |= (1<<PD4); mdir12 = -1; }
// r r r r r r r Motor 1,2 = rechter Motor r r r r r r
void M12stp (void) // Motor 12 aus
{ PORTB &= ~(1<<PB4); PORTD &= ~(1<<PD4); }
// -----------------------
// Drehrichtungsbefehle für Motor 3,4 = "linker" Motor
void M34neg (void) // Mot3,4 dreht im Uhrzeigersinn = neg. math.
{ PORTB |= (1<<PB0); PORTD &= ~(1<<PD7); mdir34 = 1; }
// l l l l l l l Motor 3,4 = linker Motor l l l l l l
void M34pos (void) // Mot3,4 dreht im mathematisch positiven Drehsinn
{ PORTB &= ~(1<<PB0); PORTD |= (1<<PD7); mdir34 = -1; }
// l l l l l l l Motor 3,4 = linker Motor l l l l l l
void M34stp (void) // Motor 12 aus
{ PORTB &= ~(1<<PB0); PORTD &= ~(1<<PD7); }
// - - - -
Anmerkung zum Code: beim Mot12 geht Mot12neg in die mathematisch positive Richtung, weil Motxxneg natürlich "fahre rückwärts" heißt.

Vielleicht bringt Dir das RNWiki (http://www.rn-wissen.de/index.php/Getriebemotoren_Ansteuerung) mehr Hilfe?

radbruch
29.11.2009, 09:54
Hallo

Das Drehrichtungsproblem wird tatsächlich vom Ansteuerungs-IC der H-Brücke verursacht. Deshalb sieht meine Motorsteuerung (ohne PWM) so aus:

#define DIR_R 7
#define DIR_L 6
#define PWM_L 5
#define PWM_R 4

void motorDir(uint8_t dir_left, uint8_t dir_right)
{
if(dir_left) PORTD |= (1<<DIR_L); else PORTD &= ~(1<<DIR_L);
if(dir_right) PORTD &= ~(1<<DIR_R); else PORTD |= (1<<DIR_R);
}

void motorSpeed(uint8_t speed_left, uint8_t speed_right)
{
if(speed_left) PORTD &= ~(1<<PWM_L); else PORTD |= (1<<PWM_L);
if(speed_right) PORTD &= ~(1<<PWM_R); else PORTD |= (1<<PWM_R);
}


Gruß

mic

oberallgeier
29.11.2009, 10:27
Hallo pinsel120866,

hast Du Dir die Bauanleitung (neue Doc!) (http://download.nicai-systems.com/nibo/Doku_NIBObee_20091115.pdf) Seite 7, Punkt 1.2.2 angesehen ? Da ist die Motorbrücke einigermassen erklärt. Dazu KÖNNTEST Du Dir noch den Schaltplan (http://download.nicai-systems.com/nibo/nibobee_schematic_1_07.pdf) ansehen, Sheet 2.

pinsel120866
29.11.2009, 10:28
OK, danke.

Offensichtlich habe ich ein Brett vorm Kopf.

Fassen wir mal zusammen:

- Der IC, der für die Motorbrücken zuständig ist, ist ein 74HC139.
- Das Drehrichtungssignal vom rechten Motor kommt vom PIN PD7 (Atmega16 DIR_R) und geht in den PIN2 des 74HC139.
- dort wird das Signal aufgeteilt in PIN4 (Y0 Uhrzeigersinn) und in PIN6 (Y2 Gegen Uhrzeiger)

Soweit, sogut. Nur wie mache ich das in BASCOM???

oberallgeier
29.11.2009, 10:35
... wie mache ich das in BASCOM ...Ohhh - to bee or not to bee - sorry - to left or not to left, that´s the question

Anmerkung: meine Ratschläge zu BASCOM sind rein zufällig. Jede Verwandtschaft oder Ähnlichkeit mit funktionierenden Codestücken ebenso wie die Funktionstüchtigkeit meiner realisierten Vorschläge sind rein zufällig und nicht gewollt.

pinsel120866
29.11.2009, 17:22
Noch ein paar BSACOM Programme:

1. Ein kleines Lauflicht der 4 LEDs:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Lauflicht mit den 4 LEDs
'Autor: Pinsel120866
'################################################# ##

Declare Sub Lauflicht()

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600
$hwstack = 32
$framesize = 32
$swstack = 32

Dim I As Integer
Dim N As Integer

Wait 5
Print "**** Lauflicht mit NIBOBee *****"
Print " "

Do
Call Lauflicht
Waitms 500
Loop
End

Sub Lauflicht()

Config Portb.0 = Output
Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
For N = 1 To 10
For I = 0 To 3
Portb.i = 1
Waitms 500
Portb.i = 0
Next I
Next N
Config Portb = Input
End Sub


2. Batteriespannung über die serielle Schnittstelle ausgeben:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Batteriespannung über RS232 anzeigen
'Autor: Pinsel120866
'################################################# ##

Declare Sub Batteriespannung()

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600
$hwstack = 32
$framesize = 32
$swstack = 32

Const Ref = 5 / 1023 'Für Batteriespannungsberechnung
Dim Volt As Single

Wait 5
Print " "
Print "**** Batteriespannung NIBOBee *****"
Print " "

Do
Call Batteriespannung
Wait 1
Loop
End

Sub Batteriespannung()
Local W As Word
Start Adc
W = Getadc(6)
Volt = W * Ref
Print "Die aktuelle Spannung: " ; Volt ; " Volt"

End Sub


3. Werte der Linien-/Bodensensoren über die serielle Schnittstelle ausgeben:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Werte der Linien-/Bodensensoren ausgeben
'Autor: Pinsel120866
'################################################# ##

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600
$hwstack = 32
$framesize = 32
$swstack = 32

Declare Sub Linedata()

Dim Linesensl As Integer
Dim Linesensc As Integer
Dim Linesensr As Integer

Config Adc = Single , Prescaler = Auto , Reference = Internal
Start Adc

Wait 5
Print " "
Print "**** Liniensensorgruppe NIBOBee *****"
Print " "

Do
Call Linedata
Print "Rechts " ; Linesensr ; " Mitte " ; Linesensc ; " Links " ; Linesensl
Wait 1
Loop

End

Sub Linedata()
Config Portb.4 = Output
Portb.4 = 1
Linesensl = Getadc(5)
Linesensc = Getadc(6)
Linesensr = Getadc(7)
Portb.4 = 0
End Sub


Was den Antrieb angeht, bin ich leider noch keinen Schritt weiter.

Ich wende mich nun der Frage zu: "Two Bee(r)s or not two bee(r)s, that's the question!"
:-)

Hubert.G
29.11.2009, 17:37
"oberallgeier" hat da den Schaltplan hereingestellt, da ist mir auf der Seite mit dem Tiny44 am Taster S1 aufgefallen, VCC an der Wurzel und GND auf der Arbeitsseite, kann nur ein Scherz sein, oder?
Hat zwar nichts mit BASCOM zu tun, aber auch wichtig.

oberallgeier
29.11.2009, 18:41
... Two Bee(r)s or not two bee(r)s, that's the question ...Machs easy, machs mit Musik, "Take five (http://www.lastfm.de/music/Dave+Brubeck/_/Take+Five)" . . . meinte (bzw. jazzte) Dave B. schon vor Jahrzehnten.


"oberallgeier" hat da den Schaltplan hereingestellt ... Taster S1 aufgefallen ... Scherz ... ? ...Oh! Ich beneide Dich um Deine Augen (na ja, eigentlich um Deine Erfahrung). Muss ich mir mal ansehen und durchdenken.

radbruch
29.11.2009, 19:03
Hallo

Die Motorsteuerung ist recht trickreich. Ein High auf dem jeweiligen PWM-Eingang des 74139 erzeugt an den Ausgängen y0 und y2 je ein High und sperrt damit die H-Brücke. Deshalb sind die Sicherheitswiderstände R10 und R11 (je 4k7) auch als PullUp gegen Vcc ausgeführt. Man muss also das PWM-Signal mit einem Low starten (Motor dreht) und beim Compare auf High schalten (Motor steht). Ich weiß noch nicht, ob dein Setup das kann, aber ich bin noch dran:

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

Noch ein Aspekt ist die PWM-Frequenz. Bei 8Bit-PWM wäre sie bei Prescaler=1 so um die 58kHz (15000000/256=58593,75). Das ergibt vermutlich große Umschaltverluste. Mit Prescaler=8 wären es nur etwas über 7kHz, das wäre zu Kontrollzwecken sogar hörbar.

Ich könnte auch falsch liegen, denn ich bin PWM-Neuling :)


Das Drehrichtungsproblem wird tatsächlich vom Ansteuerungs-IC der H-Brücke verursacht.Das stimmt so eigentlich nicht. Die beiden Seiten sind schon richtig angeschlossen, allerdings wurde wohl nicht berücksichtigt, dass die Motoren um 180° zueinander gedreht sind...

Gruß

mic

pinsel120866
09.12.2009, 14:56
Hallo,

nochmals der Appell an die RN-Gemeinde:

Hat schon jemand eine Motorbrücke mit 2vorgeschalteten ICs mit der Bezeichnung "74HC139N" unter BASCOM programmiert?

Wenn ja, bitte um Erklärung/Hilfe/Beispielcode.

BitteDanke

radbruch
09.12.2009, 16:45
Hallo

Als Bascomlaie habe ich mal ein Grundgerüst angefangen:

' nibobee mit Bascom 9.12.09 mic'

' Achtung! Nach einer kurzen Verzögerung starten die Motoren!

$regfile = "m16def.dat"

$crystal = 15000000

$baud = 9600

Config Portb.0 = Output ' LEDs 0-3
Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output

Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
Declare Sub Setleds(byval Leds As Byte)


Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1

Call Setleds(1)
Wait 3

Do
Call Setleds(9)
Call Motordir(1 , 1)
Call Motorpwm(127 , 127)
Wait 2
Call Motorpwm(255 , 255)
Wait 1
Call Motorpwm(127 , 127)
Wait 2
Call Motorpwm(0 , 0)
Wait 1

Call Setleds(6)
Call Motordir(0 , 0)
Call Motorpwm(127 , 127)
Wait 2
Call Motorpwm(255 , 255)
Wait 1
Call Motorpwm(127 , 127)
Wait 2
Call Motorpwm(0 , 0)
Wait 1
Loop

End

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portb.7 = 1 Else Portb.7 = 0
End Sub

Sub Setleds(byval Leds As Byte)
If Leds.0 = 1 Then Portb.0 = 1 Else Portb.0 = 0
If Leds.1 = 1 Then Portb.1 = 1 Else Portb.1 = 0
If Leds.2 = 1 Then Portb.2 = 1 Else Portb.2 = 0
If Leds.3 = 1 Then Portb.3 = 1 Else Portb.3 = 0
End Sub

Ich verwende 10-bit-PWM, die Funktion Motorpwm() erwartet aber Werte zwischen 0 und 255. Diese werden dann mit 4 multpliziert in die 10-bit Timerregister geschrieben (nicht atomar!).

Im Parameter für Setleds() ist den Bits 0 bis 3 jeweils die entsprechende Led zugeordnet.


Sub Linedata()
Config Portb.4 = Output
Portb.4 = 0
Linesensl = Getadc(5)
Linesensc = Getadc(6)
Linesensr = Getadc(7)
Portb.4 = 1
End Sub Die LineLEDs IR3 und IR4 hängen zwischen Vcc und PB4 (LINE_EN). Deshalb schaltet ein Low die Leds an und ein High wieder aus!

Gruß

mic

pinsel120866
09.12.2009, 18:20
WOW!

Also mic, ich bin echt begeistert wie souverän du die Sache angepackt und gelöst hast. Vielen, vielen Dank für deine Hilfe!

Ich habe den Code analysiert und bin echt fasziniert - du hast die Nuss geknackt, gratuliere!

\:D/ Bravissimo!

pinsel120866
09.12.2009, 19:12
Und weiter geht's,

das 3x16 Zeichen Display mit Portexpander PCF8574 will auch noch seinen BASCOM Code:

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600

$lib "Lcd_i2c.lib" 'I2c driver for the LCD
Config I2cdelay = 1
Const Pcf8574_lcd = &H4E 'Defines the address of the I/O expander for LCD
Config Scl = Portc.0 'Configure i2c SCL
Config Sda = Portc.1 'Configure i2c SDA

Dim _lcd_e As Byte 'Needed to control 4 line LCD
Enable Interrupts

Config Lcd = 16 * 3 'configure lcd screen

I2cstart

_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "Hello world." 'display this at the top line
Wait 1
Lowerline 'select the lower line
Wait 1
Lcd "Line 2" 'display this at the lower line
Wait 1
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "Line 3"

Das Blöde ist nur - es wird am Display nichts angezeigt. Kann mir jemand sagen, why???

m.a.r.v.i.n
09.12.2009, 22:07
Hallo pinsel,

einen kleinen Teilerfolg kann ich vermelden. Das DOGM Display braucht eine spezielle Initialisierung. Das habe ich mal ausprobiert und es funktioniert sogar. Allerdings taucht dann das nächste Problem auf. Die Cursor Positionierung stimmt nicht ganz. Das liegt ebenfalls am DOGM163, bzw. wie die Zeichen im Display RAM abgelegt werden. Und ich habe keine Ahnung wie man das ändern kann, sorry.

Die beigefügte lib muß gegen die vorhandene lcd_i2c.lib ausgetauscht werden.

pinsel120866
10.12.2009, 08:56
Hi m.a.r.v.i.n,

danke für die Anpassung der Datei.

Ich habe die Lib ausgetauscht, das oben von mir angegebene Programm neu kompiliert und geflasht. Bei mir zeigt das Display in der 3. Zeile nichts an, Zeile 1 und 2 werden richtig positioniert - ist das bei dir auch so?

EDIT: Ich habe einen Weg gefunden, wie die 3. Zeile auch verwendet wird mit

$regfile = "m16def.dat"
$crystal = 15000000
$baud = 9600

$lib "Lcd_i2c.lib" 'I2c driver for the LCD
Config I2cdelay = 1
Const Pcf8574_lcd = &H4E 'Defines the address of the I/O expander for LCD
Config Scl = Portc.0 'Configure i2c SCL
Config Sda = Portc.1 'Configure i2c SDA

Dim _lcd_e As Byte 'Needed to control 4 line LCD
Enable Interrupts

Config Lcd = 16 * 3 'configure lcd screen

I2cstart

_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "ABCDEFGHIJKLMNOP" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "QRSTUVWXYZ1234567890abcdefghijk"
Waitms 1 'display this at the lower line
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "nix"
Waitms 1
Lowerline
Lcd "nix"

Probier es mal aus.

m.a.r.v.i.n
10.12.2009, 09:43
Hallo pinsel,

ja verhält sich bei mir genauso.
Hier habe ich noch etwas interessantes entdeckt:
http://avrhelp.mcselec.com/index.html?config_lcd.htm

vielleicht hilft das ja:


Config Lcd = 16 * 3 , Chipset = Dogm163v5 '16*3 type LCD display 5V

radbruch
11.12.2009, 22:43
Hallo

Bascom ist zwar etwas "sperriger" als C, aber grundsätzlich nicht schlechter ;) Mein "Grundgerüst" beherrscht nun die Tasten, die Leds, Motor-PWM, Liniensensoren und Odometry:


' nibobee mit Bascom 11.12.09 mic

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 32
$swstack = 8
$framesize = 24

$baud = 19200

Led0 Alias Portb.0
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3
Lineled Alias Portb.4

Config Led0 = Output ' LEDs 0-3
Config Led1 = Output
Config Led2 = Output
Config Led3 = Output
Config Lineled = Output ' Lineled

Config Portc.4 = Input ' keys
Config Portc.5 = Input
Config Portc.6 = Input
Config Portc.7 = Input

Config Portd.2 = Input ' odo_l int0
Config Portd.3 = Input ' odo_r int1
Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r

'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz
Config Int0 = Change
Config Int1 = Change

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
Declare Sub Setleds(byval Leds As Byte)
Declare Function Getkeys() As Byte

Dim B As Byte , W As Word
Dim Odo_count_l As Word , Odo_count_r As Word

Start Adc
On Int0 Isr_int0
On Int1 Isr_int1
Enable Int0
Enable Int1
Enable Interrupts

Portc = &B11110000 'Tasten-PullUp Bit 4-7 einschalten

Call Setleds(0)
Lineled = 0 ' Lineled on
Waitms 10

Print
Print "nibobee in Bascom 11.12.09 mic"
Print
Print "Liniensensoren (l-m-r): " ; Getadc(5) ; "-" ; Getadc(6) ; "-" ; Getadc(7)
Lineled = 1 ' Lineled off

While Getkeys() = 0 'warten auf Taste (mit aktiver Odometry;)
Led1 = Not Pinb.1
Led2 = Not Pinb.1
Print Odo_count_l ; " - " ; Odo_count_r
Waitms 200
Wend
Call Setleds(0)
Wait 2

Do
Disable Interrupts
Odo_count_l = 0
Odo_count_r = 0
Enable Interrupts

Call Motordir(1 , 1)
Call Motorpwm(100 , 100)
Call Setleds(2)

Do
W = Odo_count_l + Odo_count_r
Loop Until W > 300

Call Motorpwm(0 , 0)
Wait 1

Disable Interrupts
Odo_count_l = 0
Odo_count_r = 0
Enable Interrupts

Call Motordir(1 , 0)
Call Motorpwm(100 , 100)
Call Setleds(4)

Do
W = Odo_count_l + Odo_count_r
Loop Until W > 115 'ca. 180°

Call Motorpwm(0 , 0)
Wait 1

Loop
End

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Sub Setleds(byval Leds As Byte)
Led0 = Leds.0
Led1 = Leds.1
Led2 = Leds.2
Led3 = Leds.3
End Sub

Function Getkeys() As Byte
Getkeys = Pinc / 16 ' Pins einlesen und nach rechts schieben
Getkeys = Getkeys Xor 255 ' invertieren
Getkeys = Getkeys And 15 ' Bit4-7 ausblenden
End Function

Isr_int0:
Incr Odo_count_l
Led0 = Pind.2
Return

Isr_int1:
Incr Odo_count_r
Led3 = Pind.3
Return
In Motordir() hatte sich ein Bug eingeschlichen den ich in dieser Version erschlagen habe:)

Gruß

mic

pinsel120866
21.12.2009, 10:01
Hallo,

ich habe versucht ein Programm zu machen, das die Bee nicht vom Tisch fallen lässt:

'Verwendeter Compiler Bascom V 1.11.9.7
'
'Aufgabe:
'NIBOBee fällt nicht vom Tisch
'Autor: Pinsel120866
'################################################# ##

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 32
$swstack = 8
$framesize = 24

Lineled Alias Portb.4

Config Lineled = Output ' Lineled
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
Declare Sub Frontled(byval Ledstatus As Byte)
Declare Sub Linedata()

Dim Linesensl As Integer
Dim Linesensc As Integer
Dim Linesensr As Integer

Start Adc
Wait 3

Do

Call Frontled(0)
Call Linedata

If Linesensl > 30 Or Linesensc > 30 Or Linesensr > 30 Then
Call Motordir(0 , 0)
Call Motorpwm(0 , 0)
Waitms 500
Call Motordir(0 , 0)
Call Motorpwm(100 , 100)
Waitms 500
Call Motordir(1 , 0)
Call Motorpwm(100 , 100)
Waitms 500
Call Motordir(1 , 1)
Call Motorpwm(100 , 100)

Else
Call Motordir(1 , 1)
Call Motorpwm(100 , 100)

End If
Loop
End

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Sub Frontled(byval Ledstatus As Byte) ' LED für Liniensensor ein-/aus-schalten
Ddrb.4 = 1
Portb.4 = Ledstatus.0
End Sub

Sub Linedata() ' Liniensensoren lesen
Config Portb.4 = Output
Portb.4 = 1
Linesensl = Getadc(5)
Linesensc = Getadc(6)
Linesensr = Getadc(7)
Portb.4 = 0
End Sub

Lässt sich fehlerfrei kompilieren und flashen, aber die Bee rührt sich nicht.
Warum?

Bitte um Hilfe.

radbruch
21.12.2009, 11:38
Hallo

Config Timer1 fehlt, der Timer1 erzeugt die PWM-Ansteuerung für die Motoren. Außerdem müssen die Motorpins PD4 bis PD7 auf Ausgang konfiguriert werden. Nach dem Schalten der LineLED sollte man kurz warten, denn auch LEDs brauchen etwas Zeit um volle Leuchtstärke zu erreichen bzw. dunkel zu werden:


Sub Linedata() ' Liniensensoren lesen
Config Portb.4 = Output
Portb.4 = 1
Linesensl = Getadc(5)
Linesensc = Getadc(6)
Linesensr = Getadc(7)
Portb.4 = 0
End Sub
Die Anoden der LineLeds (IR3+4) hängen direkt an Vcc, deshalb muss PB4 auf low geschaltet werden damit die LEDs leuchten.

Übrigends ist "vom Tisch fallen" die häufigste Ursache für ein frühes Ableben von Kleinrobotern.

Gruß

mic

pinsel120866
21.12.2009, 19:34
Danke Radbruch, jetzt hat's geklappt.

Der Vollständigkeit halber noch der richtige Code:

'Verwendeter Compiler Bascom V 1.11.9.7
'
'Aufgabe:
'NIBOBee fällt nicht vom Tisch
'Autor: Pinsel120866
'################################################# ##

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 32
$swstack = 8
$framesize = 24

Lineled Alias Portb.4

Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r
Config Lineled = Output ' Lineled
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
Declare Sub Frontled(byval Ledstatus As Byte)
Declare Sub Linedata()

Dim Linesensl As Integer
Dim Linesensc As Integer
Dim Linesensr As Integer
Dim _lcd_e As Byte 'Needed to control 4 line LCD
Enable Interrupts

Start Adc
$lib "Lcd_i2c_DOGM.lib" 'I2c driver for the LCD
Config I2cdelay = 1
Const Pcf8574_lcd = &H4E 'Defines the address of the I/O expander for LCD
Config Scl = Portc.0 'Configure i2c SCL
Config Sda = Portc.1 'Configure i2c SDA
Config Lcd = 16 * 3 , Chipset = Dogm163v5 '16*3 type LCD display 5V

I2cstart

Call Linedata

_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "*Liniensensoren*" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "R-" ; Linesensr ; " M-" ; Linesensc ; " L-" ; Linesensl
Waitms 1 'display this at the lower line
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "nix"
Waitms 1
Lowerline
Lcd "nix"

Wait 3

Do

Call Frontled(0)
Waitms 10
Call Linedata
_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "*Liniensensoren*" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "R-" ; Linesensr ; " M-" ; Linesensc ; " L-" ; Linesensl
Waitms 1 'display this at the lower line
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "nix"
Waitms 1
Lowerline
Lcd "nix"

Waitms 10

If Linesensc < 7 Or Linesensr < 12 Or Linesensl < 22 Then 'hier anpassen!
Call Motordir(0 , 0)
Call Motorpwm(0 , 0)
Waitms 500
Call Motordir(0 , 0)
Call Motorpwm(100 , 100)
Waitms 500
Call Motordir(1 , 0)
Call Motorpwm(100 , 100)
Waitms 500
Call Motordir(1 , 1)
Call Motorpwm(100 , 100)

Else
Call Motordir(1 , 1)
Call Motorpwm(100 , 100)

End If
Loop
End

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Sub Frontled(byval Ledstatus As Byte) ' LED für Liniensensor ein-/aus-schalten
Ddrb.4 = 1
Portb.4 = Ledstatus.0
End Sub

Sub Linedata() ' Liniensensoren lesen
Config Portb.4 = Output
Portb.4 = 1
Linesensl = Getadc(5)
Linesensc = Getadc(6)
Linesensr = Getadc(7)
Portb.4 = 0
End Sub

Sind bei euch die 3 Liniensensor-Werte auch so unterschiedlich?

radbruch
16.01.2010, 14:15
Hallo

Um das Bascom mit der bee etwas zu pushen habe ich die ACS-Funktion (https://www.roboternetz.de/phpBB2/viewtopic.php?t=52115) von C nach Bascom umgeschrieben:

' nibobee ACS mit Bascom (und zusätzlich allgemeinene Funktionen) 16.1.10 mic

' https://www.roboternetz.de/phpBB2/viewtopic.php?p=480966#480966

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte) 'Pwm für Motoren setzen (0-255)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte) 'Drehrichtungen der Motoren setzen (1/0)
Declare Sub Setleds(byval Leds As Byte) 'Leds als Bitmuster setzen &B000xxxx
Declare Function Getkeys() As Byte 'Bitmuster der Tasten einlesen &B0000xxxx
Declare Sub Odo_reset ' Odometryzähler auf null setzen
Declare Sub Sleep(byval Pause As Byte) 'Pause 1/36000 Sekunde warten
Declare Sub Msleep(byval Pause As Word) 'Pause 1/1000 Sekunde warten
Declare Sub Acs ' acs_left und acs_right aktuallisieren

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 48 ' kleiner 48 ergibt Stapelüberlauf!
$swstack = 8
$framesize = 24

$baud = 19200

Acs_led_left Alias Porta.2 'acs Anoden
Acs_led_right Alias Porta.3
Acs_led_36khz Alias Portc.2 ' Kathode mit Widerstand
Acs_tsop Alias Pinc.3 'Eingang!

Led0 Alias Portb.0
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3
Lineled Alias Portb.4

Config Led0 = Output ' LEDs 0-3
Config Led1 = Output
Config Led2 = Output
Config Led3 = Output
Config Lineled = Output ' Lineled

Config Acs_led_left = Output 'acs
Config Acs_led_right = Output
Config Acs_led_36khz = Output
Config Acs_tsop = Input

Config Portc.4 = Input ' keys
Config Portc.5 = Input
Config Portc.6 = Input
Config Portc.7 = Input
Portc = &B11110000 'Tasten-PullUp Bit 4-7 einschalten

Config Portd.2 = Input ' odo_l int0
Config Portd.3 = Input ' odo_r int1
Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r

'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Timer2 = Pwm , Compare Pwm = Disconnect , Prescale = 1 'gemessene 36kHz!
Ocr2 = 151 '36kHz mit Puls:Pause 50:50
Tcnt2 = 99 'Frequenzkorrektur beim Start
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz
Config Int0 = Change
Config Int1 = Change

Dim B As Byte , W As Word
Dim Odo_count_l As Word , Odo_count_r As Word
Dim Count36khz As Byte
Dim Acs_left As Byte , Acs_right As Byte
Dim Acs_count As Byte

Start Adc
On Oc2 Isr_timer2_comp
On Ovf2 Isr_timer2_ovl
On Int0 Isr_int0
On Int1 Isr_int1
Enable Oc2
Enable Ovf2
Enable Int0
Enable Int1
Enable Interrupts

Do
Call Acs
Reset Led0
Reset Led1
Reset Led2
Reset Led3
If Acs_left > 251 Then
Set Led1
Else
If Acs_left > 230 Then Set Led0
End If
If Acs_right > 251 Then
Set Led2
Else
If Acs_right > 230 Then Set Led3
End If
Call Msleep(100)
Loop
End

Sub Acs
Ocr2 = 253
Set Acs_led_left
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_left
Acs_left = Ocr2
While Acs_tsop = 0
Wend

Ocr2 = 253
Set Acs_led_right
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_right
Acs_right = Ocr2
While Acs_tsop = 0
Wend
End Sub

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Sub Setleds(byval Leds As Byte)
Led0 = Leds.0
Led1 = Leds.1
Led2 = Leds.2
Led3 = Leds.3
End Sub

Function Getkeys() As Byte
Getkeys = Pinc / 16 ' Pins einlesen und nach rechts schieben
Getkeys = Getkeys Xor 255 ' invertieren
Getkeys = Getkeys And 15 ' Bit4-7 ausblenden
End Function

Sub Odo_reset
Disable Interrupts
Odo_count_l = 0
Odo_count_r = 0
Enable Interrupts
End Sub

Sub Sleep(byval Pause As Byte)
Count36khz = Pause
While Count36khz > 0
Wend
End Sub

Sub Msleep(byval Pause As Word)
While Pause > 0
Call Sleep(36)
Decr Pause
Wend
End Sub

Isr_int0:
Incr Odo_count_l
Led0 = Pind.2
Return

Isr_int1:
Incr Odo_count_r
Led3 = Pind.3
Return

Isr_timer2_comp:
Toggle Acs_led_36khz
Return

Isr_timer2_ovl:
Tcnt2 = Tcnt2 + 99 'Frequenzkorrektur 36kHz
Reset Acs_led_36khz
If Count36khz > 0 Then Decr Count36khz
If Acs_count > 0 Then Decr Acs_count
Return

Die Werte meiner Liniensensoren sind auch unterschiedlich. Die Mitte hat (aufbaubedingt?) immer den höchsten Wert, die linke Seite schwächelt etwas und hat ca. 50 weniger als die rechte Seite bei hell.

Gruß

mic

[Edit]
Setup Timer2 geändert!!!

pinsel120866
16.01.2010, 18:36
Super, tolle Arbeit - danke mic.

Ich habe mir dein Programm gleich geschnappt und so erweitert, dass die Bee autonom durch den Raum fährt:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Autonome Bewegung mit
'Abstandsmessung (IR-LEDs 2x links, 2x rechts)
'und Werte auf DODM 3x16 LCD ausgeben
'Autor: Pinsel120866
'################################################# ##

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte) 'Pwm für Motoren setzen (0-255)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte) 'Drehrichtungen der Motoren setzen (1/0)
Declare Sub Setleds(byval Leds As Byte) 'Leds als Bitmuster setzen &B000xxxx
Declare Function Getkeys() As Byte 'Bitmuster der Tasten einlesen &B0000xxxx
Declare Sub Odo_reset ' Odometryzähler auf null setzen
Declare Sub Sleep(byval Pause As Byte) 'Pause 1/36000 Sekunde warten
Declare Sub Msleep(byval Pause As Word) 'Pause 1/1000 Sekunde warten
Declare Sub Acs ' acs_left und acs_right aktuallisieren

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 48 ' kleiner 48 ergibt Stapelüberlauf!
$swstack = 8
$framesize = 24

$baud = 19200

Acs_led_left Alias Porta.1 'acs Anoden
Acs_led_right Alias Porta.0
Acs_led_36khz Alias Porta.3 ' Kathode mit Widerstand
Acs_tsop Alias Pina.2 'Eingang!

Led0 Alias Portb.0
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3
Lineled Alias Portb.4

$lib "Lcd_i2c_DOGM.lib" 'I2c driver for the LCD
Config I2cdelay = 1
Const Pcf8574_lcd = &H4E 'Defines the address of the I/O expander for LCD
Config Scl = Portc.0 'Configure i2c SCL
Config Sda = Portc.1 'Configure i2c SDA

Config Led0 = Output ' LEDs 0-3
Config Led1 = Output
Config Led2 = Output
Config Led3 = Output
Config Lineled = Output ' Lineled

Config Acs_led_left = Output 'acs
Config Acs_led_right = Output
Config Acs_led_36khz = Output
Config Acs_tsop = Input

Config Portc.4 = Input ' keys
Config Portc.5 = Input
Config Portc.6 = Input
Config Portc.7 = Input
Portc = &B11110000 'Tasten-PullUp Bit 4-7 einschalten

Config Portd.2 = Input ' odo_l int0
Config Portd.3 = Input ' odo_r int1
Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r

'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Timer2 = Phase Correct , Compare Pwm = Disconnect , Prescale = 1
Ocr2 = 151 '36kHz mit Puls:Pause 50:50
Tcnt2 = 99 'Frequenzkorrektur beim Start
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz
Config Int0 = Change
Config Int1 = Change

Dim B As Byte , W As Word
Dim Odo_count_l As Word , Odo_count_r As Word
Dim Count36khz As Byte
Dim Acs_left As Byte , Acs_right As Byte
Dim Acs_count As Byte
Dim _lcd_e As Byte 'Needed to control 4 line LCD

Config Lcd = 16 * 3 , Chipset = Dogm163v5 '16*3 type LCD display 5V

I2cstart
Start Adc
On Oc2 Isr_timer2_comp
On Ovf2 Isr_timer2_ovl
On Int0 Isr_int0
On Int1 Isr_int1
Enable Oc2
Enable Ovf2
Enable Int0
Enable Int1
Enable Interrupts

_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "Pinsel's NIBOBee" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "Abstandsmessung mit 2x2 IR-LEDs"
Waitms 1 'display this at the lower line
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "nix"
Waitms 1
Lowerline
Lcd "nix"

Waitms 500

Do
Call Acs

Reset Led0
Reset Led1
Reset Led2
Reset Led3

Call Motordir(1 , 1)
Call Motorpwm(197 , 197)

If Acs_left > 251 And Acs_right > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led1
Call Motordir(1 , 0)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(127 , 127)
Waitms 300
End If

If Acs_left > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led1
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(127 , 0)
Waitms 300
End If

If Acs_right > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Waitms 1
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led2
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(0 , 127)
Waitms 300
End If

Loop
End

Sub Acs
Ocr2 = 253
Set Acs_led_left
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_left
Acs_left = Ocr2
While Acs_tsop = 0
Wend

Ocr2 = 253
Set Acs_led_right
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_right
Acs_right = Ocr2
While Acs_tsop = 0
Wend
End Sub

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Function Getkeys() As Byte
Getkeys = Pinc / 16 ' Pins einlesen und nach rechts schieben
Getkeys = Getkeys Xor 255 ' invertieren
Getkeys = Getkeys And 15 ' Bit4-7 ausblenden
End Function

Sub Odo_reset
Disable Interrupts
Odo_count_l = 0
Odo_count_r = 0
Enable Interrupts
End Sub

Sub Sleep(byval Pause As Byte)
Count36khz = Pause
While Count36khz > 0
Wend
End Sub

Sub Msleep(byval Pause As Word)
While Pause > 0
Call Sleep(36)
Decr Pause
Wend
End Sub

Isr_int0:
Incr Odo_count_l
Led0 = Pind.2
Return

Isr_int1:
Incr Odo_count_r
Led3 = Pind.3
Return

Isr_timer2_comp:
Toggle Acs_led_36khz
Return

Isr_timer2_ovl:
Tcnt2 = Tcnt2 + 99 'Frequenzkorrektur 36kHz
Reset Acs_led_36khz
If Count36khz > 0 Then Decr Count36khz
If Acs_count > 0 Then Decr Acs_count
Return

radbruch
16.01.2010, 18:59
Hallo

Sieht gut aus, ich kann es leider nicht testen, weil mir deine LCD-Lib fehlt :(

Aber wenn es bei dir funktioniert ist es prima. Vielleicht kannst du uns ein Video zeigen?

Eigentlich brauchen wir bei Bascom die Sleep/Msleep-Funktionen nicht, oder?

Gruß

mic

[Edit]
Klasse, es funktioniert wunderbar. Ich habe in meinem Programm lediglich die Hauptscheife ausgetauscht:

Do
Call Acs

Reset Led0
Reset Led1
Reset Led2
Reset Led3

Call Motordir(1 , 1)
Call Motorpwm(197 , 197)

If Acs_left > 251 And Acs_right > 251 Then
Set Led1
Call Motordir(1 , 0)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(127 , 127)
Waitms 300
End If

If Acs_left > 251 Then
Set Led1
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(127 , 0)
Waitms 300
End If

If Acs_right > 251 Then
Set Led2
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Waitms 100
Call Motorpwm(0 , 127)
Waitms 300
End If

Loop
End
http://www.youtube.com/watch?v=upszgUzs69g
Kann es sein, dass waitms länger dauert als erwartet?

pinsel120866
17.01.2010, 11:17
Hi mic,

super Video, bei mir verhält die Bee sich genauso. Ich habe ein bisschen herumexperementiert und festegestellt dass man mir der Abschirmung der IR-LEDs einiges herausholen kann.

Die LCD-Lib habe ich noch angehängt.

radbruch
17.01.2010, 11:51
Hallo

Ändere mal die waitms xxx-Aufrufe in Msleep(xxx) um, dann wird aus den sinnlosen Drehungen echtes Ausweichen.

Setup Timer2 geändert:
Config Timer2 = Pwm , Compare Pwm = Disconnect , Prescale = 1 'gemessene 36kHz!

Zuvor wurden die Impulse wohl nur über die Warteschleifen im Programm erzeugt. Keine Ahnung, warum das funktionierte. Sorry.

Gruß

mic

pinsel120866
17.01.2010, 17:35
Hi mic,

du hast Recht, die Bee fährt nun viel besser.

Nur der Parkettboden ist bei mir zu rutschig, hier muss ich mir noch überlegen wie ich den Reifen mehr Grip geben kann.

Noch mein angepasster Code:

'Verwendeter Compiler Bascom V 1.11.9.3
'
'Aufgabe:
'Abstandsmessung mit IR-LEDs 2xlinks, 2x rechts
'und Werte auf DODM 3x16 LCD ausgeben
'Autor: Pinsel120866
'################################################# ##

Declare Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte) 'Pwm für Motoren setzen (0-255)
Declare Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte) 'Drehrichtungen der Motoren setzen (1/0)
Declare Sub Setleds(byval Leds As Byte) 'Leds als Bitmuster setzen &B000xxxx
Declare Function Getkeys() As Byte 'Bitmuster der Tasten einlesen &B0000xxxx
Declare Sub Odo_reset ' Odometryzähler auf null setzen
Declare Sub Sleep(byval Pause As Byte) 'Pause 1/36000 Sekunde warten
Declare Sub Msleep(byval Pause As Word) 'Pause 1/1000 Sekunde warten
Declare Sub Acs ' acs_left und acs_right aktuallisieren

$regfile = "m16def.dat"
$crystal = 15000000
$hwstack = 48 ' kleiner 48 ergibt Stapelüberlauf!
$swstack = 8
$framesize = 24

$baud = 19200

Acs_led_left Alias Porta.1 'acs Anoden
Acs_led_right Alias Porta.0
Acs_led_36khz Alias Porta.3 ' Kathode mit Widerstand
Acs_tsop Alias Pina.2 'Eingang!

Led0 Alias Portb.0
Led1 Alias Portb.1
Led2 Alias Portb.2
Led3 Alias Portb.3
Lineled Alias Portb.4

$lib "Lcd_i2c_DOGM.lib" 'I2c driver for the LCD
Config I2cdelay = 1
Const Pcf8574_lcd = &H4E 'Defines the address of the I/O expander for LCD
Config Scl = Portc.0 'Configure i2c SCL
Config Sda = Portc.1 'Configure i2c SDA

Config Led0 = Output ' LEDs 0-3
Config Led1 = Output
Config Led2 = Output
Config Led3 = Output
Config Lineled = Output ' Lineled

Config Acs_led_left = Output 'acs
Config Acs_led_right = Output
Config Acs_led_36khz = Output
Config Acs_tsop = Input

Config Portc.4 = Input ' keys
Config Portc.5 = Input
Config Portc.6 = Input
Config Portc.7 = Input
Portc = &B11110000 'Tasten-PullUp Bit 4-7 einschalten

Config Portd.2 = Input ' odo_l int0
Config Portd.3 = Input ' odo_r int1
Config Portd.4 = Output ' pmw_r
Config Portd.5 = Output ' pwm_l
Config Portd.6 = Output ' dir_l
Config Portd.7 = Output ' dir_r

'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
Config Timer2 = Pwm , Compare Pwm = Disconnect , Prescale = 1 'gemessene 36kHz!
Ocr2 = 151 '36kHz mit Puls:Pause 50:50
Tcnt2 = 99 'Frequenzkorrektur beim Start
Config Adc = Single , Prescaler = 64 , Reference = Avcc ' 235 kHz
Config Int0 = Change
Config Int1 = Change

Dim B As Byte , W As Word
Dim Odo_count_l As Word , Odo_count_r As Word
Dim Count36khz As Byte
Dim Acs_left As Byte , Acs_right As Byte
Dim Acs_count As Byte
Dim _lcd_e As Byte 'Needed to control 4 line LCD

Config Lcd = 16 * 3 , Chipset = Dogm163v5 '16*3 type LCD display 5V

I2cstart
Start Adc
On Oc2 Isr_timer2_comp
On Ovf2 Isr_timer2_ovl
On Int0 Isr_int0
On Int1 Isr_int1
Enable Oc2
Enable Ovf2
Enable Int0
Enable Int1
Enable Interrupts

_lcd_e = 128 'Upper half of 4-line display is selected
Cls 'clear the LCD display
Lcd "Pinsel's NIBOBee" 'display this at the top line
Call Msleep(1)
Lowerline 'select the lower line
Lcd "Abstandsmessung mit 2x2 IR-LEDs"
Call Msleep(1) 'display this at the lower line
_lcd_e = 64 'Lower half of 4-line display is selected
Lcd "nix"
Call Msleep(1)
Lowerline
Lcd "nix"

Call Msleep(1500)

Do
Call Acs

Reset Led0
Reset Led1
Reset Led2
Reset Led3

Call Motordir(1 , 1)
Call Motorpwm(197 , 197)

If Acs_left > 251 And Acs_right > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Call Msleep(1)
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led1
Call Motordir(1 , 0)
Call Motorpwm(0 , 0)
Call Msleep(300)
Call Motorpwm(77 , 77)
Call Msleep(700)
End If

If Acs_left > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Call Msleep(1)
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led1
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Call Msleep(300)
Call Motorpwm(77 , 0)
Call Msleep(700)
End If

If Acs_right > 251 Then
_lcd_e = 128
Cls
Lcd "" 'display this at the top line
Call Msleep(1)
Lowerline 'select the lower line
Lcd "Abstand li: " ; Acs_left ; " Abstand re: " ; Acs_right ; 'Wert ausgeben auf Display
Set Led2
Call Motordir(1 , 1)
Call Motorpwm(0 , 0)
Call Msleep(300)
Call Motorpwm(0 , 77)
Call Msleep(700)
End If

Loop
End

Sub Acs
Ocr2 = 253
Set Acs_led_left
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_left
Acs_left = Ocr2
While Acs_tsop = 0
Wend

Ocr2 = 253
Set Acs_led_right
While Acs_tsop = 1 And Ocr2 > 151
Acs_count = 8
While Acs_count > 0
Wend
Ocr2 = Ocr2 - 1
Wend
Reset Acs_led_right
Acs_right = Ocr2
While Acs_tsop = 0
Wend
End Sub

Sub Motorpwm(byval Pwm_l As Byte , Byval Pwm_r As Byte)
Pwm1a = Pwm_l * 4
Pwm1b = Pwm_r * 4
End Sub

Sub Motordir(byval Dir_l As Byte , Byval Dir_r As Byte)
If Dir_l = 0 Then Portd.6 = 0 Else Portd.6 = 1
If Dir_r = 0 Then Portd.7 = 1 Else Portd.7 = 0
End Sub

Function Getkeys() As Byte
Getkeys = Pinc / 16 ' Pins einlesen und nach rechts schieben
Getkeys = Getkeys Xor 255 ' invertieren
Getkeys = Getkeys And 15 ' Bit4-7 ausblenden
End Function

Sub Odo_reset
Disable Interrupts
Odo_count_l = 0
Odo_count_r = 0
Enable Interrupts
End Sub

Sub Sleep(byval Pause As Byte)
Count36khz = Pause
While Count36khz > 0
Wend
End Sub

Sub Msleep(byval Pause As Word)
While Pause > 0
Call Sleep(36)
Decr Pause
Wend
End Sub

Isr_int0:
Incr Odo_count_l
Led0 = Pind.2
Return

Isr_int1:
Incr Odo_count_r
Led3 = Pind.3
Return

Isr_timer2_comp:
Toggle Acs_led_36khz
Return

Isr_timer2_ovl:
Tcnt2 = Tcnt2 + 99 'Frequenzkorrektur 36kHz
Reset Acs_led_36khz
If Count36khz > 0 Then Decr Count36khz
If Acs_count > 0 Then Decr Acs_count
Return

jackr
12.02.2010, 21:41
Hallo,
Ich möchte so eine Bascom program in die NiboBee laden. Aber nach compilieren und Program chip komt die meldung:USB programmer not found. Muss ich bei OPTIONS was änderen? Bitte helfe.
M.f.g.
Jack.

radbruch
13.02.2010, 00:09
Hallo

Ich verwende zum Flashen der Bascom-Hex-Dateien den orginalen nibobee-Programmer mit dem ich auch die C-Programme flashe.

Gruß

mic