'( ################################################################################ project: MPU-6050 Evaluation -------------------------------------------------------------------------------- name : MPU6050_Test.bas copyright : (c) Chris Hirt, OE3HBW, Austria, JN87AQ, 2021 purpose : Test code for first MPU-6050 evaluation micro : ATmega644P-20PU programmer : homebrew (STK200/STK300 emulation) compiler : MCS BASCOM-AVR 2.0.8.4 - 001 flash : 5% code build : V1.0 @ 12082021 (12 Aug 2021) status : test -------------------------------------------------------------------------------- This small project is just to get acquainted with the very low cost gyroscope and accelerometer MEMS chips. As a simple example I start with the SEN-MPU6050 module. The goal is to use the know-how later to develop a self-built seismometer. ########################### HARDWARE ########################################### '----------------------------- uC ATmega644P 40 PDIP 20 MHz PIN 01 PB0 PORTB.0 T0 / XCK0 02 PB1 PORTB.1 T1 / CLKO 03 PB2 PORTB.2 INT2 / AIN0 04 PB3 PORTB.3 OC0A / AIN1 05 PB4 PORTB.4 OC0B / SS 06 PB5 MOSI ISP MOSI 07 PB6 MISO ISP MISO 08 PB7 SCK ISP SCK 09 /RESET ISP RST 10 VCC +5V 11 GND 0V 12 XTAL2 Quartz 16.0000 MHz 13 XTAL1 Quartz 16.0000 MHz 14 PD0 PORTD.0 RXD --> RS232 15 PD1 PORTD.1 TXD --> RS232 16 PD2 PORTD.2 INT0 / RXD1 17 PD3 PORTD.3 INT1 / TXD1 18 PD4 PORTD.4 OC1B / XCK1 19 PD5 PORTD.5 OC1A 20 PD6 PORTD.6 OC2B / ICP 21 PD7 PORTD.7 OC2A 22 PC0 PORTC.0 TWI SCL --> I2C Bus SCL MPU6050 23 PC1 PORTC.1 TWI SDA --> I2C Bus SDA MPU6050 24 PC2 PORTC.2 TCK --> LCD RS 25 PC3 PORTC.3 TMS --> LCD E 26 PC4 PORTC.4 TDO 27 PC5 PORTC.5 TDI --> MPU6050 INT 28 PC6 PORTC.6 TOSC1 29 PC7 PORTC.7 TOSC2 30 AVCC VCC +5V 31 AGDN GND 0V 32 AREF ADC REF 33 PA7 PORTA.7 ADC7 --> LCD DB7 34 PA6 PORTA.6 ADC6 --> LCD DB6 35 PA5 PORTA.5 ADC5 --> LCD DB5 36 PA4 PORTA.4 ADC4 --> LCD DB4 37 PA3 PORTA.3 ADC3 38 PA2 PORTA.2 ADC2 39 PA1 PORTA.1 ADC1 40 PA0 PORTA.0 ADC0 ----------------------------- LCD YL162-90 PIN 01 VSS GND 02 VDD +5V 03 V0 -2.5V ! 04 RS Register Select 05 R/W Read/Write --> GND 06 E Enable 07 D0 (Data 0, 4-Bit mod open) 08 D1 (Data 1, 4-Bit mod open) 09 D2 (Data 2, 4-Bit mod open) 10 D3 (Data 3, 4-Bit mod open) 11 D4 (Data 4) 12 D5 (Data 5) 13 D6 (Data 6) 14 D7 (Data 7) 15 Background Light + BL2 Background Light - ----------------------------- SEN-MPU6050 Module PIN 01 VCC Power supply voltage and digital I/O supply voltage 02 GND Power supply ground 03 SCL I2C serial clock 04 SDA I2C serial data 05 XDA I2C master serial data, for connecting to external sensors 06 XCL I2C Master serial clock, for connecting to external sensors 07 AD0 I2C Slave address LSB 08 INT Interrupt digital output (totem pole or open-drain) For MPU6050-test only main I2C bus is used; AD0 on GND ------------------------------ Literature: MPU-6000 and MPU-6050 Product Specification InvenSense Inc PS-MPU-6000A-00 Revision 3.4 Release 08/19/2013 MPU-6000 and MPU-6050 Register Map and Descriptions InvenSense Inc RM-MPU-6000A-00 Revision 4.2 Release 08/19/2013 ################################################################################ ') '$PROG &HFF,&HD7,&HD9,&HFC 'Take care! Fuse Bits !!! $regfile = "m644pdef.dat" 'ATmega644P $crystal = 16000000 '16.0 MHz 'stack and framesize not optimized! $hwstack = 128 $framesize = 128 $swstack = 128 $lib "I2C_TWI.lbx" 'include TWI Lib; force BASCOM to use the hardware TWI '----- Config I2C -------------------------------------------------------------- Config SDA = PortC.1 'Configures a port pin for use as serial data SDA Config SCL = PortC.0 'Configures a port pin for use as serial clock SCL Config Twi = 400000 'TWI = I2C clock speed is 400 kHz '----- Config LCD -------------------------------------------------------------- Config LCD = 16 * 2 Config LCDmode = Port Config LCDbus = 4 Config LCDpin = Pin , Db4 = PortA.4 , Db5 = PortA.5 , Db6 = PortA.6 , Db7 = PortA.7 , Rs = PortC.2 , E = PortC.3 '----- Config Ports ------------------------------------------------------------ Config PORTD.7 = Output 'Port D.7 Output --> Buzzer 'Port C.5 Input --> MPU6050 INT DDRC.5 = 0 'PC.5 as Input PortC.5 = 0 'and no PullUp - enabled for MPU6050 INT '----- MPU6050 Constants ------------------------------------------------------- 'MPU6050_Adress = &b0110_1000 (&h68) AD0 --> GND Const MPU6050_WriteAdr = &b1101_0000 '&hD0 Const MPU6050_ReadAdr = &b1101_0001 '&hD1 'Default value of register 107 Power Management 1: h40 b0100_0000 'Default value of register 117 Who Am I: h68 b0110_1000 'Default value of all other registers: h00 b0000_0000 Const MPU6050_PMgmt1 = &h6B 'Register 107 Power Management 1 Const MPU6050_WhoAmIReg = &h75 'Register 117 Who Am I Const MPU6050_GConfig = &h1B 'Register 27 Gyroscope Configuration Const MPU6050_AConfig = &h1C 'Register 28 Accelerometer Configuration Const MPU6050_SP_Reset = &h68 'Register 104 Signal Path Reset Const MPU6050_AXO_H = &h3B 'Register 59 Accelerometer XOUT High Const MPU6050_TO_H = &h41 'Register 65 Temperatur TOUT High Const MPU6050_GXO_H = &h43 'Register 67 Gyroscope XOUT High Const MPU6050_GYRO_FS_250 = &h00 Const MPU6050_ACCEL_FS_2 = &h00 '----- Declarations ------------------------------------------------------------ Declare Sub Warning() Declare Sub I2CwriteRegister(ByVal reg As Byte, ByVal cont As Byte) Declare Function I2CreadRegister(ByVal reg As Byte) As Byte Declare Function I2CreadWord(ByVal reg As Byte) As Word Declare Function Complement(ByVal xc As Word) As Integer Declare Function MPU6050_WhoAmI() As Byte Declare Sub MPU6050_Initialize() Declare Sub MPU6050_setDeviceReset() Declare Sub MPU6050_setSignalPathReset() Declare Function MPU6050_GyroXout() As Integer Declare Function MPU6050_AccXout() As Integer Declare Function MPU6050_TempOut() As Integer '----- Global Variable --------------------------------------------------------- Dim MPU6050 As Byte Dim buz As Byte Dim intx As Byte Dim hB As Byte Dim lB As Byte Dim regW As Word Dim value As Word Dim tmp As Word Dim gxo As Integer Dim axo As Integer Dim tempi As Integer Dim wai As Word Dim gxos As Single Dim axos As Single Dim temps As Single '############################################################################### '---------------------------- Main --------------------------------------------- Cls 'clearing the LCD display Cursor Off Noblink 'hide cursor I2Cinit 'initializes the I2C SCL and SDA pins Waitms 50 MPU6050 = MPU6050_WhoAmI() ' If ERR = 1 OR MPU6050 = 1 Then 'I2C Error oder MPU6050 not found! LCD "ERROR" Call Warning() End 'Program End End If LCD "MPU6050 Test" Lowerline LCD "ChipID = " + Hex(wai) 'MPU-6050 chip ID = &h34 Wait 5 Cls Call MPU6050_Initialize() 'Initialize MPU6050 LCD "MPU6050 Interrupt" Lowerline intx = PINC.5 LCD "INT = " + Bin(intx) 'MPU-6050 INT Wait 5 Cls LCD "Temperatur" Lowerline tempi = MPU6050_TempOut() 'read Temperature out temps = tempi / 340 temps = temps + 36.53 'scaling LCD temps 'show scaled TOUT only once Wait 5 Cls Do 'measurement loop; for test only X values gxo = MPU6050_GyroXout() 'read Gyro XOUT gxos = gxo / 131 'scaling LCD gxos 'show scaled Gyro XOUT Lowerline axo = MPU6050_AccXout() 'read Accelerometer XOUT axos = axo / 16384.0 'scaling LCD axos 'show scaled Accelerometer XOUT Wait 1 Cls Loop End 'of program '---------------------------- Subs and Functions ------------------------------- Sub Warning() ' Error warning sound for buzzer For buz = 1 to 100 Toggle PORTD.7 Waitms 2 Next End Sub 'write cont in register reg Sub I2CwriteRegister(ByVal reg As Byte , ByVal cont As Byte) I2cstart 'START condition I2cwbyte MPU6050_WriteAdr 'write mode I2cwbyte reg 'register reg I2cwbyte cont 'write byte I2cstop 'STOP condition End Sub Function I2CreadRegister(ByVal reg As Byte) As Byte 'read register reg I2cstart 'START condition I2cwbyte MPU6050_WriteAdr 'write mode I2cwbyte reg 'register reg 'I2cstop 'STOP condition ???? I2cstart 'START condition I2cwbyte MPU6050_ReadAdr 'read mode I2crbyte I2CreadRegister , Nack 'read Byte I2cstop 'STOP condition End Function Function I2CreadWord(ByVal reg As Byte) As Word 'function read 2 register I2cstart 'START condition I2cwbyte MPU6050_WriteAdr 'write mode I2cwbyte reg 'first register reg 'I2cstop 'STOP condition ???? I2cstart 'START condition I2cwbyte MPU6050_ReadAdr 'read mode in Burst Read Sequence I2crbyte hB , ack 'read high Byte I2crbyte lB , Nack 'read low Byte I2cstop 'STOP condition regW = hb shift regW , left , 8 regW = regW + lb I2CreadWord = regW 'return 2 Byte End Function Function Complement(ByVal xc As Word) As Integer '16-bit 2’s complement If xc >= &h8000 Then tmp = 65535 - xc tmp = tmp + 1 Complement = -tmp Else Complement = xc End If End Function '---- Start MPU6050 ---- Function MPU6050_WhoAmI() As Byte 'read "Who Am I" value from register 117 wai = I2CreadRegister(MPU6050_WhoAmIReg) 'read MPU6050 "who am I" value Shift wai , right , 1 If wai = &h34 Then 'default WhoAmI of reg 117 is &b0011_0100 = &h34 MPU6050_WhoAmI = 0 'correct ID Else MPU6050_WhoAmI = 1 'wrong ID End If End Function Sub MPU6050_Initialize() 'Reset all registers Call MPU6050_setDeviceReset() Waitms 100 Call MPU6050_setSignalPathReset() Waitms 100 'Clock to ZGYRO PLL and Wake Up Call I2CwriteRegister(MPU6050_PMgmt1 , &b0000_0011) Call I2CwriteRegister(MPU6050_GConfig , MPU6050_GYRO_FS_250)'Gyro +/- 250 °/s Call I2CwriteRegister(MPU6050_AConfig , MPU6050_ACCEL_FS_2) 'Acc +/- 2g End Sub '---- MPU6050 Powermanagement ---- 'p40 'Register 107 Power Management 1 Sub MPU6050_setDeviceReset() Call I2CwriteRegister(MPU6050_PMgmt1 , &b1000_0000) End Sub '---- MPU6050 Signal Path Reset ---- 'p37 'Register 104 SIGNAL_PATH_RESET Sub MPU6050_setSignalPathReset() Call I2CwriteRegister(MPU6050_SP_Reset , &b0000_0111) End Sub '---- Gyroscope Measurement Out ---- 'p31 'Register 67 - 72 'GYRO_XOUT_H [15:8], GYRO_XOUT_L [7:0] etc Function MPU6050_GyroXout() As Integer 'read GyroXout from register 67-68 value = I2CreadWord(MPU6050_GXO_H) MPU6050_GyroXout = Complement(value) End Function '---- Acceleromter Measurement Out ---- 'p29 'Register 59 - 64 'ACCEL_XOUT_H [15:8], ACCEL_XOUT_L [7:0] etc Function MPU6050_AccXout() As Integer 'read AccXout from register 59-60 value = I2CreadWord(MPU6050_AXO_H) MPU6050_AccXout = Complement(value) End Function '---- Temperature Measurement ---- 'p30 'Register 65 - 66 TEMP_OUT_H [15:8] , TEMP_OUT_L [7:0] Function MPU6050_TempOut() As Integer 'read Temperation from register 65-66 value = I2CreadWord(MPU6050_TO_H) MPU6050_TempOut = Complement(value) End Function '############################ End Of File ######################################