![[Rozmiar: 10329 bajtów]](naglowek.gif)
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 40
$swstack = 16
$framesize = 32
Config Submode = New
$lib "i2c_twi.lib" 'używamy biblioteki do sprzętowego TWI (I2C)
Config Scl = Portc.5 'określanie pinów żeby biblioteka wiedziała które
Config Sda = Portc.4
I2cinit 'ustawia piny w pożądany stan
Config Twi = 400000 'ustawia predkośc na 400kHz
Dim Servo_val As Byte 'zmienna trzyma wartość wypełnienia dla serwa
Dim New_x As Byte 'odczytana z żyroskopu pozycja względem osi X
Dim Help_w As Word 'zmienna pomocnicza do obliczeń
Dim New_val As Word 'zmienna żeby zaznaczyć w kodzie gdzie powstaje nowa wartość
Dim Old_val As Byte 'poprzednia wartość do porówniania
Config Portb.1 = Output 'ustawia port dla diody jako wyjściowy,
Led Alias Portb.1 'nadawanie przyjaznej nazwy dla pinu portu
Config Servos = 1 , Servo1 = Portd.2 , Reload = 10 'konfiguracja 1 serwa na PORTD.2
Config Portd.2 = Output 'ustawienie pinu portu jako wyjscie (dla serwa)
'skrajne połozenia serwa przy których nie dobija do końca powodując przeciążenie to 45 min i 165 max
' 165 - 45 = 120 kroków od jednego do drugiego skrajnego jest zatem 120
' czyli środkowe położenie to 60 + 45 = 115 (60 środek + minimum gdzie serwo sie zatrzymuje)
Const Polozenie_srodkowe = 60 + 45 'kompilator to sam wyliczy (105)
' Z żyroskopu wartosci odczytywane są nie tak "zwyczajnie"
' Kiedy płytka jest ustawiona horyzontalnie i przechylasz DO GÓRY to wartośc odczytywana zmienia sie od 0 do 64 ( rośnie )
' Kiedy płytka jest ustawiona horyzontalnie i przechylasz W DÓŁ to wartosć odczytywana zmienia się od 255 do 193 ( zmniejsza sie )
' Od horyzontalniej do pionowej jest kąt prosty czyli 90 stopni
' na 90stopni są 64 kroki (wartość odczytywana)
' na 90stopni serva sa 60 kroki
'przelicznik 64/60 = 1,066
Enable Interrupts
'***********************************************************
'* TEN SUB ZAINICJUJE I POUSTAWIA ŻYROSKOP *
'***********************************************************
Sub Init_mpu
'--- (25) Sample Rate Divider = 1 ---
I2cstart 'start condition
I2cwbyte &HD0 'write adress of MPU-6050
I2cwbyte 25 'Register 25 Sample Rate Divider (1..8 kHz)
I2cwbyte &B00000000 'Divider set to 1 (soll)
I2cstop 'stop condition
'--- (26) DLPF = 42/44 Hz ---
I2cstart 'start condition
I2cwbyte &HD0 'write adress of MPU-6050
I2cwbyte 26 'Register 26 DLPF_CFG (digital lowpass filter) Configuration
I2cwbyte &B00000011 'Bits 0..2 = 011 (3) - ACC:44Hz, 4.9ms; Gyro:42Hz, 4.8ms
I2cstop 'stop condition
'--- (27) Gyro Full Range = +-2000°/s ---
I2cstart 'start condition
I2cwbyte &HD0 'write adress of MPU-6050
I2cwbyte 27 'Register 27 Gyro Configuration
I2cwbyte &B00011000 'Bits 3+4 = 11 - Full Scale Range: +/-2000°/ss
I2cstop 'stop condition
'--- (28) ACC Full Range = +-2g ---
I2cstart 'start condition
I2cwbyte &HD0 'write adress of MPU-6050
I2cwbyte 28 'Register 28 ACC Configuration
I2cwbyte &B00000000 'Bits 3+4 = 00 - Full Scale Range: +/-2g / No High Pass Filter
I2cstop 'stop condition
'--- (107) Power Management 1 ---
I2cstart 'start condition
I2cwbyte &HD0 'write adress of MPU-6050
I2cwbyte 107 'Register 107 Power Management 1
I2cwbyte &B00001011 'No Reset / No Sleep / No Cycle / Temp_Sens: Dis / Clock Source: Z-Gyro
I2cstop
End Sub
'************************************************************
'* TEN SUB WYKONA RUCH SERWA TAM I Z POWROTEM (TEST) *
'************************************************************
Sub Servo_test
Waitms 100
For Servo_val = 45 To 165 'od minimu do maksimum
Servo(1) = Servo_val 'ustaw serwo
Waitms 5 'i poczekaj 5ms
Next
Waitms 100
For Servo_val = 165 To 45 Step - 1
Servo(1) = Servo_val
Waitms 5
Next
End Sub
Call Servo_test ' na początku serwo wykona ruchy w skrajne położenia
Servo_val = Polozenie_srodkowe
Servo(1) = Servo_val
Call Init_mpu
Do
I2cstart 'start magistrali I2C
I2cwbyte &HD0 'wpisuje adres żyroskopu do zapisu
I2cwbyte 59 'wybieram rejestr który chcę czytać
I2crepstart 'ponawiam start (wymagane przez żyroskop)
I2cwbyte &HD1 ' wpisuje adres żyroskopu do odczytu
I2crbyte New_x , Nack 'czytam wybrany bajt
I2cstop 'zakonczenie pracy z magistralą
'wykonaj operacje w zalezności od tego jaką wartość ma odczytana zmienna
Select Case New_x
Case 0 'przy 0 i 255 serwo jest na środku
New_val = Polozenie_srodkowe
'czyli serwo jest wysuniete już w połowie
'kiedy odchylasz do góry to trzeba odjąć wartośc z serwa żeby się "schowało"
Case 1 To 64
Help_w = 64 - New_x
Help_w = Help_w * 100
Help_w = Help_w / 106 '100/106 to przełozenie ruchu serwa w stosunku do żyro
New_val = 45 + Help_w
'serwo ma minimalną wartość 45 wiec obliczone wychylenie dodajemy do minimum
'kiedy odchylasz na dół wartośc nagle z 0 robi sie 255 i potem spada
Case 193 To 254
Help_w = 255 - New_x
Help_w = Help_w * 100
Help_w = Help_w / 106
New_val = 105 + Help_w
'105 = 60 od srodka + 45 przesuniecie
Case 255
New_val = Polozenie_srodkowe
End Select
'*******************************************************
'* TUTAJ DODAJE DO SIEBIE NOWA WARTOŚĆ DO POPRZEDNIEJ *
'* I DZIELE PRZEZ DWA, TAKIE UŚREDNIANIE POWODUJE *
'* ŁAGODNIEJSZE REAKCJE SERWA NA ZMIANY *
'*******************************************************
Help_w = Servo_val 'pobranie starej wartosci do zmiennej
Help_w = Help_w + New_val 'dodanie nowej wartosci
Shift Help_w , Right , 1 ' Shift 1 powoduje podział przez 2
Servo_val = Help_w ' zapis nowej zmiennej
If Old_val <> Servo_val Then 'jesli nowa wartość jest inna/różna od poprzedniej
Old_val = Servo_val 'to zapamietaj nową
Reset Led 'ale włącz diodę (ruch, zmiany)
Servo(1) = Servo_val 'i wpisz nową wartośc dla serwa
Else 'jesli jednak nowa wartość jest taka sama (brak ruchu)
Set Led 'to zgaś LED
End If
Waitms 25 'krótkie opóźnienie (można spróbować pozmieniać lub usunąć)
Loop
End
Za pomocą I2creceive wciągamy 14 bajtów a dlatego ze na tej tablicy zbudowałem "strukturę" to w programie mogę odwoływać się bezpośrednio do gotowych wartości typu Integer
Dim Rbytes(14) As Byte
Dim X_accel As Integer At Rbytes(1) Overlay
Dim Y_accel As Integer At Rbytes(3) Overlay
Dim Z_accel As Integer At Rbytes(5) Overlay
Dim Temp As Integer At Rbytes(7) Overlay
Dim X_gyro As Integer At Rbytes(9) Overlay
Dim Y_gyro As Integer At Rbytes(11) Overlay
Dim Z_gyro As Integer At Rbytes(13) Overlay
Const Mpu_i2c_address = &HD0
Rbytes(1) = 59
I2creceive Mpu_i2c_address , Rbytes(1) , 1 , 14
Swap X_accel : Swap Y_accel : Swap Z_accel : Swap Temp : Swap X_gyro : Swap Y_gyro : Swap Z_gyro