$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