GY-521/MPU6050

Steve2381

Senior Member
Hello all
I have an MPU6050 gyro sensor board (marked GY-521) that I have connected to an 18m2 via I2C

I got this board 'kinda' working a long while back, and now I have need of programming one into a project on an urgent basis.

Anyone know of any base code available to get me off the ground? I just don't have the timescale to fluff around with it and hammer out the details for the comms.
I can't find anything much on good old Google, and I cannot find my own old code anywhere. Very annoying.

Just wondered if anyone had any ideas regards the I2C commands to put it in the correct mode etc

On a separate note... anyone have issues with editor 6.0.9.1 just losing the comms ports? I can be merrily programming away and all of a sudden, it cannot find the AXE027 lead. Uninstalling, refreshing drivers etc... nothing fixes it. I end up rebooting the laptop. Very annoying.

Thank you
 
Last edited:

Steve2381

Senior Member
Well... all irrelevant at the moment.... Error: Can't open port COM4.
That is all I have been getting for the last hour. Uninstalled drivers, rebooted, different USB sockets, removed device, re-installed.
This AXE027 lead/AXE091 Board has been problematic on all three of my latest laptops... such a waste of valuable time

I have upgraded to 6.1.0.0. No difference. Looks like its an Arduino Pro Mini after all :rolleyes:

edit... OK. No matter what USB port I use or re-number, it cannot use it - Cannot open port COM#. Tried removing drivers, new drivers, run as administrator, hitting it with a frustration hammer.
 
Last edited:

hippy

Technical Support
Staff member
Things always go wrong when one is is in a hurry and don't want things to go wrong. Frustration can then easily make problems harder to resolve.

That it was working and then suddenly stopped working suggests that it may be something to do with the AXE027.

Do you get the same "Cannot open COM port" error if you try "COM1" or any other port, even if they cannot be used to program the PICAXE ?
 

Captain Haddock

Senior Member
I find V5 of the program editor much easier and starts quicker so I stick with that, probably missing a few features but prefer the reliability.
 

Steve2381

Senior Member
I sat for 2.5 hours trying to resolve this. It will not work with any com port. Same error. Even if you search the comm port, and it lists say com port 5 (if that is what you set it as in device manager) in the top left 'Workspace explorer' window.... it then bangs up an error saying cannot find com 4.
Why the hell is it looking for com port 4 still.... the software itself is telling me on the screen that the AXE027 is on com port 5 :rolleyes:.

So.... no more Picaxe until this is resolved.

Yea... I liked the older versions of the software too, but that became pretty unreliable so I upgraded.
 

steliosm

Senior Member
Any change you have used the #com directive in your code to set the port manually?
Any change you can use the #com directive in your code to set the port manually?
Also, you could try using the AxePad to program the chip or probably use the command line version of the compilers (already installed with PE6) to check what is going on with your serial ports.

You are right in deed, PE6 it's a very disappointing piece of software. Everything looks so slow even if the application is running on high end equipment. I wish they had the #include directive either in PE5 or Axepad so I can remove PE6 from my system.
 

Steve2381

Senior Member
Hmm... the original purpose of this thread was to get an MPU6050 working.... not going well
Its a brand new Asus 3k laptop.... plenty powerful enough and should not have any issues with USB ports (well.. it doesn't with anything else).
 

steliosm

Senior Member
Check the serial ports from the device manager and verify functionality using the command line version of the compilers (already installed with PE6).
 

Steve2381

Senior Member
Annoyingly (or not)..... after wasting all last night, its working at the moment.

So... back to my original problem... the MPU6050 (SY-521). I have it reading all the raw data to my 18M2, but I have just realised that this idea is now probably dead in the water.... some of the values returned from the sensor are going to be negative, and the 18m2 cannot read those.
I can't even code that out, as I don't know what was negative or what was positive to start with.... hmmm
 
Last edited:

Buzby

Senior Member
... some of the values returned from the sensor are going to be negative, and the 18m2 cannot read those. I can't even code that out, as I don't know what was negative or what was positive to start with....
The datasheet indicates that the values are 16bit 2's complement numbers, not too difficult to process these into 'sign and magnitude'.

As to what 'positive' or 'negative' acceleration means in terms of the real world, it doesn't really matter. If you really need to know absolute +/- you can can easily determine the 'polarity' of each axis by orientating the board in each of the 6 directions relative to the Earth, and checking the 'sign' of the current vertical value.

When you get this working on your 18M2 it will generate lots of new new ideas for PICAXE projects.

Don't give up !

Cheers,

Buzby
 

Steve2381

Senior Member
Eh! Not sure I understand that Buzby :confused:
I have made excellent headway actually (by my standards)... its reading quite well, and achieving what I need, except this whole +/- thing.
I have my gyro connected, and reporting to a 1.3" Oled screen.

Quick overview of my project is that it needs to monitor something that must stay within a certain percentage of level.

I understood (maybe incorrectly) that a Picaxe cannot read a negative value that it receives over an I2C bus. It would always store that value in a variable as a plus number, even if it arrived as a negative. Never seen a negative value in the debug screen?

My code is reporting back all positive values from the Gyro, which includes repeat values for opposite directions, which makes me think one of those two reported values should be negative. Otherwise, you have no idea which direction the Gyro has been tilted (e.g. My code receives a value of say 45 for 45 degrees, but that could be to the left or right).

So, currently it works monitoring my Gyro board when held horizontal, and turns off LED when it goes outside its preset parameters... e.g. 10 degrees off level.
BUT..... turn it 180 over and rather than say you are way off level, it reports as if it was the correct way up (because it can't see the values are negative).

How do I read the negative value off the Gyro?

On a separate issue.....
https://www.dropbox.com/s/vw8mgrwu5hhi9dj/OLED Font.xls?dl=0

This chap made this font and I don't understand the 5x values that make up the 8x8 letters.
I need to make my own 16x16 font, and would like to understand this.

And on another note.... AXE027 has behaved itself all evening? Who knows....
 

Buzby

Senior Member
The sign of a 2's complement number is indicated by the MSB.

If your code is already generating the same number for both orientations of the axis then you are almost there !.

Please post your conversion routine, and we'll take a look.

Cheers,

Buzby
 

Steve2381

Senior Member
Oh my..... post my code.... :eek:
You will rip it to bits..... its not exactly pretty.

Now there are lots of bits that repeat.... and lots of bits that need tidying up or are still to complete. Formatting has gone to pot too.
I tend to play around and then once its working... tidy the whole lot up. Wasn't expecting anyone to examine it.

At the moment, it simply divides the incoming Z and Y values by 1000 to give me headroom to allow multiple sampling then average the result (probably a far better way of doing that).

I have then just basically read the result and used it to determine if I am within my required angle - I have not actually correctly converted it to degrees.
That was next on my list.

The 2x Pots allow me to adjust my window of allowable tilt in the Y axis
There is a tiltswitch coded in... that was my backup plan to work out whether the unit was inverted

:unsure: I await the laughter


Code:
dirsb = %100000                                '1=Output   0=input
dirsc = %110000                                '1=Output   0=input


symbol UpperPot     = c.1                            'Top tilt limit Pot
symbol LowerPot     = c.0                            'Lower tilt limit Pot
symbol TiltLed     = c.7                            'Tilt Led (Blue)
symbol EnabledLed = c.6                            'Enabled Led (Yellow)
symbol ArmedLed     = b.7                            'Armed Led (Green)
symbol Tiltswitch = Pinb.6                        'Tilt switch for main unit


Symbol xa = w0
Symbol xa.lsb = b0
Symbol xa.msb = b1

Symbol ya = w1
Symbol ya.lsb = b2
Symbol ya.msb = b3

Symbol za = w2
Symbol za.lsb = b4
Symbol za.msb = b5

Symbol Xaxis = w3
Symbol Yaxis = w4

symbol Upperlimit = w5                            'Top tilt limit
symbol Lowerlimit = w6                            'Lower tilt limit

symbol Xaverage = w7                            'Average value from the GYRO
symbol Yaverage = w8

Symbol Counter = b18

symbol Xlimit = b20                            'Limit flag
symbol Ylimit = b21

symbol TiltCalc = w11                            'Used to calculate the tilt limits
Symbol Holdoff = b24                            'Hold off timer
Holdoff=0                                    'When the unit turns off the output, this stops the output toggling quickly

symbol displaybank = b25
symbol fontlookup = b26
symbol subcounter = b27
symbol pixels = b19

; save Font codes in EEPROM

eeprom 0,(124,130,130,130,124)       ; 0 (ASCII 48)
'The rest of the eeprom alphabet has been deleted here to keep the post under 10000 characters


hi2csetup i2cmaster, $D0, i2cfast_8, i2cbyte            'set up the GYRO
pause 1000

init:

    'set clock source
    'register 107 0x6B
    'reset / sleep / cycle / NA / temperature disable / [2,1,0] clock source
    hi2cout $6B, (%00000000)'internal 8MHz
    'hi2cout $6B, (%00000001)'clk source from X gyro
    'hi2cout $6B, (%00000010)'clk source from Y gyro
    'hi2cout $6B, (%00000011)'clk source from Z gyro
    'hi2cout $6B, (%00000100)'external 32.768kHz
    'hi2cout $6B, (%00000101)'external 19.2MHz
    pause 100
  
    'gyro full scale
    'register 27 0x1B
    'x-test / y-test / z-test / [5,4] full scale / NA / NA / NA
    hi2cout $1B, (%00000000)'+-250 degrees/s
    'hi2cout $1B, (%00001000)'+-500 degrees/s
    'hi2cout $1B, (%00010000)'+-1000 degrees/s
    'hi2cout $1B, (%00011000)'+-2000 degrees/s
    pause 100
  
    'accel full scale
    'register 28 0x1C
    'x-test / y-test / z-test / [5,4] full scale / NA / NA / NA
    hi2cout $1C, (%00000000)'+-2g
    'hi2cout $1B, (%00001000)'+-4g
    'hi2cout $1B, (%00010000)'+-8g
    'hi2cout $1B, (%00011000)'+-16g
    pause 100

; initialise i2c for display (ID 0x78) and then send power up instructions                 
hi2csetup i2cmaster,%01111000,i2cfast,i2cbyte 
hi2cout 0x80,(0xAE,0x00,0x00,0xB0,0x20,0x00,0xD5,0x80,0xA8,0x1F,0xD3,0x00,0x8D, _
0x14,0xA1,0x00,0xC8,0xDA,0x02,0x81,0xCF,0xD9,0xF1, 0xDB,0x30,0xA4,0xA6)

gosub sendtodisplay                    ; send 4 blank lines to clear display
let displaybank = 0                    ; flag rows 0-3 for display
hi2cout 0x80,(0xAF)                    ; turn display on                    ; turn display on 
  
    high TiltLed
    pause 200
    low TiltLed
    pause 200
    high EnabledLed
    pause 200
    low EnabledLed
    pause 200
    high ArmedLed
    pause 200
    low ArmedLed

PAUSE 100

Readadc Upperpot,Upperlimit                    ;Read the endstop pots
Readadc Lowerpot,Lowerlimit

;convert angles here

poke 28,"T","i","l","t"," ","d","o","w","n"," ","a","n","g","l","e"," "
poke 44," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
poke 60,"T","i","l","t"," ","u","p"," ","a","n","g","l","e"," "," "," "
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "

displaybank = 1 - displaybank                    ; toggle lines to display
gosub sendtodisplay                            ; load message to display memory and point display at it

PAUSE 1500

poke 28," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "            ;data to send to display (4 * 16)
poke 44," "," "," "," "," ","R","E","A","D","Y"," "," "," "," "," "," "
poke 60," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "
poke 76," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "

displaybank = 1 - displaybank                    ; toggle lines to display
gosub sendtodisplay                            ; load message to display memory and point display at it

hi2csetup i2cmaster, $D0, i2cfast_8, i2cbyte        'Switch to the GYRO

'_________________________________________________________________________________________________________________________________________________

  
main:

if Tiltswitch=1 then                        ;Loop here if unit inverted
    low TiltLed
    ;Switch off the relay here
    goto main
endif

    Readadc Upperpot,Upperlimit                ;Read the endstop pots
    Readadc Lowerpot,Lowerlimit

for Counter=1 to 30                        'Sample the gyro 30 times and average             

    '0x3B is accel X first register
    hi2cin $3B, (xa.msb, xa.lsb, ya.msb, ya.lsb, za.msb, za.lsb)
    '0x41 is temperature first
    'hi2cin $41, (temp.msb, temp.lsb)
    '0x3B is gyro X first register
    'hi2cin $43, (xg.msb, xg.lsb, yg.msb, yg.lsb, zg.msb, zg.lsb)
  
    Xaxis=xa/1000
    Yaxis=ya/1000
  
    Xaverage=Xaverage+Xaxis
    Yaverage=Yaverage+Yaxis
  
next

    Xaxis=Xaverage/30
    Yaxis=Yaverage/30
    Xaverage=0;
    Yaverage=0;
    Xaxis=Xaxis*10
    Yaxis=Yaxis*10
  
    'debug
  
    if Holdoff>0 then
        Holdoff=Holdoff-1
    endif
  
    if Xaxis>99 and Xaxis<200 then            ;If out of X axis range, then turn off LED
        Xlimit=0
        Holdoff=4
    endif
  
    if Xaxis<100 and Xaxis>0 then                ;Within range
        Xlimit=1
    endif
  
    if Xaxis>500 and Xaxis<600 then            ;If out of X axis range, then turn off LED
        Xlimit=0
        Holdoff=4
    endif
      
    if Xaxis<700 and Xaxis>600 then            ;Within range
        Xlimit=1
    endif
  
  
    if Yaxis>Upperlimit and Yaxis<300 then         ;If out of Y axis range, then turn off LED
        Ylimit=0
        Holdoff=4
    endif
  
    if Yaxis<Upperlimit and Yaxis>0 then        ;Within range
        Ylimit=1
    endif
  
    TiltCalc=655-Lowerlimit
    if Yaxis<TiltCalc and Yaxis>400 then        ;If out of Y axis range, then turn off LED
        Ylimit=0
        Holdoff=4
    endif
  
    TiltCalc=655-Lowerlimit                    ;Within range
    if Yaxis<655 and Yaxis>TiltCalc then         
        Ylimit=1
    endif 

      
    if Xlimit=1 and Ylimit=1 and Holdoff=0 then     ;If within limits, switch the output on
        high TiltLed
        ;Switch on the relay here
    else
        low TiltLed
        ;Switch off the relay here
    endif
  
goto main

'_________________________________________________________________________________________________________________________________________________

sendtodisplay:                                          ; sends characters in memory locations 28-91 to the display
for Counter = 28 to 91
    PEEK Counter, fontlookup                        ; load character to output
    select case fontlookup
        case 48 to 57                            ; 0-9
            fontlookup = fontlookup - 48 * 5
        case 65 to 90                            ; A-Z
            fontlookup = fontlookup -65 * 5 + 50
        case 97 to 122                            ; a-z output as A-Z
            fontlookup = fontlookup - 97 * 5 + 50
        else
            fontlookup = 244                      ; all other characters will display a blank
    endselect                 
    hi2cout 0x40,(0)                              ; one blank column
    for subcounter = 0 to 4
        read fontlookup, pixels     
        hi2cout 0x40,(pixels)                      ; followed by 5 columns per character
        fontlookup = fontlookup + 1
    next subcounter
    hi2cout 0x40,(0,0)                          ; two blank columns
next Counter                                  ; this completes the 8x8 character output
If displaybank = 0 then
    hi2cout 0x80,(0x40)                          ; point display to lines 0-3 of display memory
    else hi2cout 0x80,(0x60)                      ; point display to lines 4-7 of display memory
Endif
return
 

Buzby

Senior Member
This bit not good .....

Code:
for Counter=1 to 30                        'Sample the gyro 30 times and average              

    '0x3B is accel X first register
    hi2cin $3B, (xa.msb, xa.lsb, ya.msb, ya.lsb, za.msb, za.lsb)
    '0x41 is temperature first
    'hi2cin $41, (temp.msb, temp.lsb)
    '0x3B is gyro X first register     <<<<<<<<<<<<< Comment typo I think
    'hi2cin $43, (xg.msb, xg.lsb, yg.msb, yg.lsb, zg.msb, zg.lsb)
   
    Xaxis=xa/1000     <<<<<<<<<< You are dividing a 2's complement by an unsigned integer, the result will always be positive
    Yaxis=ya/1000
   
    Xaverage=Xaverage+Xaxis
    Yaverage=Yaverage+Yaxis
   
next
You need to either (1) get the sign and magnitude first before dividing, or (2) re-scale the raw value into a 0-to-Max by adding a constant offset.

If you do it the second way then all your results will start at 0, so below 50% represents negative and above is positive.

In general your code is fine, just fixing this conversion will help get it doing what you want.

Cheers,

Buzby
 

Steve2381

Senior Member
Thanks Buzby....

Not sure I understand what I am doing here. How do I get the sign? This is the part I don't understand. All my reported values are 0-255 in lsb and msb.
Do you mean report the lsb and msb values into a word variable instead of a byte, add say 128 and then below 128 will be negative and above 128 will be positive?

Damn... I don't have enough word variables left!

I will have a play later
 

Buzby

Senior Member
The 0-255 in each byte is one half of a 16 bit 2's complement number.

e.g.
MSB . . . . . . . . . . .LSB
00000000 00000011 = +3

11111111 11111101 = -3

The MSB hi bit tells you the sign.

If the bit is '0' then the value is positive, so just use the number.

If the bit is '1' then the value is negative, so it needs converting, like this :

11111111 11111101 - Orig num, -3
00000000 00000010 - Invert each bit
00000000 00000001 - Add 1
00000000 00000011 - Result, +3

The huge benefit of 2'Cmp in the computer world is that adding a series of 2'Cmp numbers automatically takes care of signs, no need for a seperate 'subtract' routine.

I don't think you need any more variables, except for a few bits to indicate signs of each value.

Cheers,

Buzby
 
Last edited:

Steve2381

Senior Member
Ooh.... didn't know about those

That '0x3B is gyro X first register' isn't mine. Its part of some code I found elsewhere. Never noticed it was incorrect

I will have a look at this later after household repair chores. Thanks for the advice Buzby
 

Steve2381

Senior Member
OK... sat here for 20 mins. Yes, I can see the farthest left bit is giving me plus or minus.
Ha.... that is as far as I get. I can't use getbit with an 18m2, so not sure how to retrieve that bits status... my Picaxe is rusty oh wise one.

Really do need to get my head around this binary/bit stuff
 

lbenson

Senior Member
You can move the variable to W0 and look at individual bits 0-15.

IF bit15 = 1 then ' then number is negative.

Or you can say IF variable > 32767 then ' uppermost bit is on; number is negative.
 

hippy

Technical Support
Staff member
OK thanks. So, if I check bit 30, then that would be the MSB of W1?
Bit31 is the most significant bit but to handle negative numbers you simply need to compare with $8000 (32768). For example ...
Code:
w0 = $8000 : Gosub Show ; -32768
w0 = $8001 : Gosub Show ; -32767
;      :                   : 
w0 = $FFFE : Gosub Show ; -2
w0 = $FFFF : Gosub Show ; -1
w0 = $0000 : Gosub Show ;  0
w0 = $0001 : Gosub Show ; +1
w0 = $0002 : Gosub Show ; +2
;      :                   : 
w0 = $7FFE : Gosub Show ; +32766
w0 = $7FFF : Gosub Show ; +32767
End

Show:
  SerTxd( "Int 16 = ", #w0, TAB )
  If w0 >= $8000 Then
    w0 = -w0
    SerTxd( "Sgn 16 = -", #w0, CR, LF )
  Else
    SerTxd( "Sgn 16 = +", #w0, CR, LF )
  End If
  Return
For 8-bit negative numbers -
Code:
b0 = $80 : Gosub Show ; -128
b0 = $81 : Gosub Show ; -127
;     :                  : 
b0 = $FE : Gosub Show ; -2
b0 = $FF : Gosub Show ; -1
b0 = $00 : Gosub Show ;  0
b0 = $01 : Gosub Show ; +1
b0 = $02 : Gosub Show ; +2
;     :                  : 
b0 = $7E : Gosub Show ; +126
b0 = $7F : Gosub Show ; +127
End

Show:
  SerTxd( "Int 8 = ", #b0, TAB )
  If b0 >= $80 Then
    b0 = -b0
    SerTxd( "Sgn 8 = -", #b0, CR, LF )
  Else
    SerTxd( "Sgn 8 = +", #b0, CR, LF )
  End If
  Return
Using #DEFINE can be helpful here -
Code:
#Define WordIsNegative(wvar) wvar >= $8000
#Define WordIsPositive(wvar) wvar <  $8000

#Define ByteIsNegative(wvar) wvar >= $80
#Define ByteIsPositive(wvar) wvar <  $80

Show:
  SerTxd( "Int 16 = ", #w0, TAB )
  If WordIsNegative(w0) Then
    w0 = -w0
    SerTxd( "Sgn 16 = -", #w0, CR, LF )
  Else
    SerTxd( "Sgn 16 = +", #w0, CR, LF )
  End If
  Return
 

Steve2381

Senior Member
Therefore, below 32768 is positive and above 32768 will be negative. .. I think
I have a flag now stating whether its positive or negative, but I am still having an issue that I need to get my head around.

Basically, the GYRO is reporting the values Xa as my badly laid out text shows below: Had to use ...... to stop it messing up the text formatting

.........................-65025 | 0

.......-52000 .............................+12000

-48000...............(board)...........+16500

.......-52000 ................................+12000

.........................-65025 | 0

So I still don't know whether I am tilted up at 45 degrees or down at 45 degrees, as it reports the same number. I would have expected the sign to depict whether top to bottom axis, not left to right (if that makes sense)
 

hippy

Technical Support
Staff member
To do division of a signed number by an unsigned number -
Code:
#Define WordIsNegative(wvar) wvar >= $8000
#Define WordIsPositive(wvar) wvar <  $8000

#Macro ShowSigned(wvar)
  w0 = wvar : Gosub Show
#EndMacro

w1 = -12345 : w2 = 1000 : Gosub DivW1ByW2
w1 =  23456 : w2 = 1000 : Gosub DivW1ByW2
End

DivW1ByW2:
  SerTxd( "w1/W2 = " ) ShowSigned(w1)
  SerTxd( " / " )      ShowSigned(w2)
  If WordIsPositive(w1) Then
    w3 = w1/w2
  Else   
    w3 = -w1/w2
    w3 = -w3
  End If
  SerTxd( " = " ) ShowSigned(w3)
  SerTxd( CR, LF )
  Return

Show:
  If w0 >= $8000 Then
    w0 = -w0
    SerTxd( "-" )
  End If
  SerTxd( #w0 )
  Return
And to allow division by a signed number -
Code:
w1 = -12345 : w2 =  1000 : Gosub DivW1ByW2
w1 =  23456 : w2 =  1000 : Gosub DivW1ByW2
w1 = -12345 : w2 = -1000 : Gosub DivW1ByW2
w1 =  23456 : w2 = -1000 : Gosub DivW1ByW2
End

DivW1ByW2:
  SerTxd( "w1/W2 = " ) ShowSigned(w1)
  SerTxd( " / " )      ShowSigned(w2)
  If WordIsPositive(w1) Then
    If WordIsPositive(w2) Then
      w3 = w1/w2
    Else
      w3 = -w2
      w3 = w1/w3
      w3 = -w3
    End If
  Else   
    If WordIsPositive(w2) Then
      w3 = -w1/w2
      w3 = -w3
    Else
      w3 = -w2
      w3 = -w1/w3
    End If
  End If
  SerTxd( " = " ) ShowSigned(w3)
  SerTxd( CR, LF )
  Return
 

hippy

Technical Support
Staff member
-65025, -52000, -48000 ... Those aren't valid numbers for a signed 16-bit value. Values should be -32768 to +32767. There may be an error with the maths confusing the results.

You can defeat the forum's desire to remove spacing and formatting by enclosing the text within a [code]...[/code] block -
Code:
     Top
   /     \
Left     Right
   \     /
    Bottom
 

Steve2381

Senior Member
I am so lost :oops:
They are the decimal figures being reported directly into W0 and W1 (X and Y axis) in the debug screen.

So, is its reporting the value up to 65025 in the decimal window, because it cannot show that its a minus number, so it adds them?

This is what I am not understanding... how do I read the data from the gyro showing between -32768 to +32767? My data is arriving in both Hex and Decimal 0 - 65025. Is it possible the code I found isn't retrieving the data correctly?

Hmm.... I don't really understand all the code in the above posts (but thank you for trying to teach me!). I may be at my limit here.

The code was lifted from an earlier post, so I had hoped it was correct.

I think its time I admitted defeat and went back to good old mechanical tilt switches.
 
Last edited:

Steve2381

Senior Member
At the end of the day, it seems irrelevant whether its reporting 0-65535, or -32768 to 32767 .... the 15th bit is still showing the sign incorrectly in my code as far as I can tell.
I have tried your advice above, and all I end up with is the same set of results, but simply within the +/- 32768.
I still end up with values for 45 degrees off horizontal that read the same when tilted up or down. I would expect tilted up to be say + and tilted down -. I have looked at the gobblygook that is the data sheet and that really hasn't helped.

I lifted the code on this thread : (Where he does mention the fact debug doesn't show the results correctly), but no explanation of how to actually retrieve them correctly

https://picaxeforum.co.uk/threads/has-anyone-used-the-mpu-5060-3-axis-gyro-i-need-help-setting-up-coding-for-it.23851/

I am clearly missing something (knowledge being one of them)

Time to hang a heavy weight off a 10k pot then :confused:
 

Steve2381

Senior Member
At this point, I believe everyone has lost interest.... including me....

I am getting the correct -32768 to +32767 results.
My bits 15 and 31 are also reporting whether negative or positive (not that I really need to flag this separately now)

However...

I have checked my hi2cin statement (with other Arduino code and the datasheet), and I am pulling in the data in the correct order - 6x Accelerometer, 2x temp then 6x Gyro.
I am now putting all that information into variables, even though I only need the Accelerometer.

But... my results are still not giving me the ability to determine whether I am tilted up or down 45 degrees (for example), as the sign isn't changing between those two angles, its staying the same.
The sign changes vertically through the PCB if that makes sense. roll right 180 degrees and you are negative, and roll left 180 degrees and you are positive. It needs to be one sign when within 90 degrees either way of horizontal, and the other sign when inverted.

I have also noticed that my X and Y axis report differently to the PCB legend on the board - They are opposite. X is Y and vise-versa.
That is why I checked the order I was receiving the data

Any ideas?


mpu-6050-1.jpg
 

Steve2381

Senior Member
My final opinion... dud Gyro. Been reading about people that have had these Gyro's that report incorrect values
 

The bear

Senior Member
Steve,
I'm sure no one's given up.
The forum members will be meditating and studying their crystal balls like crazy.
Its way above my pay grade.
Good luck, bear..
 

hippy

Technical Support
Staff member
The forum members will be meditating and studying their crystal balls like crazy.
And as it's a weekend; busy with their own projects or hobbies, out shopping, playing sports or being healthy,. or otherwise 'getting away from it'.

I have done some Gyro/Accelerometer coding with a Wii Nunchuck and also a PCB sensor, but cannot remember which. Might have been the MPU6050, maybe not.

I recall results not being exactly what I was expecting but I recall I did manage to get the Nunchuck able to indicate when it was pointing left or right, tilted up or down when held in front of me. I also recall it couldn't do yaw so if you are getting unchanging data it might be you are just looking at the wrong axis.

I just looked at the data and correlated it to what I was doing, said that's 'left-right' that's tilt 'up and own', paying no attention to which data it was meant to be. I vaguely remember one signal was going negative when it should have been going positive and vice-versa so just negated that in the code.

I recall the PCB sensor wasn't so easy, and never did figure that out though I might have just lost interest or run out of time and never got back to it. I'll see if I can dig it or anything useful out.

I started just reading the values and using SERTXD to show them on the Terminal. That way you can see what they actually mean as signed representations using the earlier code. Most of that came about from doing this myself.

Then it's 'investigation time'. Sticky-tape it to the side of a box so you can alter its orientation by rotating the box and sticky-tape that to something sturdy so its readings are fairly static. Then move it from its 'home position' in one axis and back again. Note which numbers change for each movement. Don't worry if they are inverted.

Then try with the sensor and box mounted in the three different orientations. From that you might see some correlation.

You might be better off just using a Wii Nunchuck as they are fairly easy to interface to using I2C and I am pretty certain that did work. They're really cheap (50p) in second-hand stores - https://uk.webuy.com/product-detail/?id=5016743074111

If you pick up a Wii Motion Plus you can pull that apart and have a socket which connects to the PICAXE I2C which every Wii interface can plug into with no furher hacking - https://uk.webuy.com/product-detail/?id=swiivalue66

Strip the nunchuck down to it's bare PCB and it's really quite compact.

As you can probably guess I did a fair bit of playing with Wii kit and a PICAXE but never completed documenting that. It's what I'd likely recommend.
 

Steve2381

Senior Member
It wasn't a complaint about lack of interest! I know people have their own lives and projects, plus I have had lots of help so far.

I can only assume it is a faulty sensor. I cannot see any other reason for it doing what it does. The fact the X and Y are reversed is bizarre.

I have had to give it up for now, purely because I have exhausted Google and my own head
 

Steve2381

Senior Member
OK. I am CLEARLY thicker than I thought...

I purchased a replacement MPU6050..... same damn results.

Because I just don't seem to be getting this, can you please explain it like I am 5 years old.

I am pulling in the data from the board on I2c, using the command hi2cin $3B, (xa.msb, xa.lsb, ya.msb, ya.lsb, za.msb, za.lsb)

I am allocating these results using:

Symbol xa = w0
Symbol xa.lsb = b0
Symbol xa.msb = b1
Symbol ya = w1
Symbol ya.lsb = b2
Symbol ya.msb = b3
Symbol za = w2
Symbol za.lsb = b4
Symbol za.msb = b5

My results are the same, does not matter how I try to read them, I cannot get over this problem where I get the same results for different angles, so something is not reporting correctly. It should be reporting -32768 to +32767

If I have the statement if xa <0 then... Can the Picaxe handle that, or is the fact that its under zero instantly messing up the result?

Or, if I say if xa+32768<32768 then will it report it correctly? Or can it simply not report the minus value coming back to the Picaxe to start with?
(I have tried this and it doesn't work).

Do I need to calculate this in binary because using decimals is messing up the 15th bit sign value?

Bit 15 reports on the X axis (and bit 30 on the Y) with a value of 0 or 1.
They are reporting 1 (Negative) from vertical (0 degrees) to straight down (180 degrees). Then reports 0 (Positive) from 181 degrees to vertical again.

The reported angle is the same for 45 degrees up and down in either axis. So you cannot tell which way the board is tilted, as they are both the same sign.

Hmm
 

Buzby

Senior Member
The fact that bit15 is changing is a good sign, my suspicion is that you might have some bytes mixed up.

Also, those two code statements ( xa < 0 and xa+32768<32768 #) will not give you the results you expect.

I would first write a simple piece of code that just reads the raw data and use sertxd to report results, with no processing at all.

Once you are happy the raw data is as you expect, then move on to the rest of the project.

Wtite this simple test and post it here. We'll check it out for you.

EDIT : I've just found a 3-axis accelerometer (ADXL345) in my bits box, and an application note on measuring angles with a chip :

https://www.analog.com/media/en/technical-documentation/application-notes/AN-1057.pdf

I'll give it a go, but not tonight.

Cheers,

Buzby
 
Last edited:

Steve2381

Senior Member
If I watch the MSB, it reports the same values twice in different positions. I would not have thought that would ever happen.
I cannot watch the results in debug, as they won't show the correct value (I don't think).

I am resisting the temptation to move this over to a different platform where it can read negative values.... I hate being defeated

I don't seem to be even able to read the raw data. If I was reading uncorrupted raw data, I think I could work it out, but I don't seem to be able to pull the correct values from the sensor.
 
Last edited:

Buzby

Senior Member
If I watch the MSB, it reports the same values twice in different positions. I would not have thought that would ever happen.
This will happen with an accelerometer. Imagine a pendulum swinging. At each end of the swing the pendulum is stationary, and the acceleration due to gravity is 1g in both cases, but the angle of each is different. One is x, and the other is 180-x. Using 1 axis only won't be able to discriminate.

See page 4 of that application note.

Cheers,

Buzby
 

Steve2381

Senior Member
Hmm.. so how do you use a Gyro module to determine an angle? You can only ever monitor 0-180 degrees?
So, I need to find a dual output accelerometer with outputs offset from each other. I thought these modules were the type used in phones (data sheet says they are). Phones know which way they are tilted.

Maybe use the Gyro to determine the direction it is moved from its last position, therefore whether tilting forwards or backwards?

Many thanks for your help on this Buzby. I do appreciate your assistance. I clearly misunderstood the capabilities of a gyro.
I will read on....
 
Last edited:

Steve2381

Senior Member
After reading some documents regarding gyros in mobile phones.... it's becoming apparent that this is a madly complicated affair.
I have a feeling this is heading to an Arduino with a pre-written library. Shame, as the 18m2 was coping well up until my lack of knowledge and understanding shot it down!
 

Buzby

Senior Member
Here is a simple program that reads the 3-axis ADXL345 accelerometer data.

It prints the values as -255 to +255. ( I can't seem to get the ADXL345 to operate in 13bit mode, but the convertion would be the same. )

For your device you will need to adjust the hi2c stuff, but the rest of the code won't need changing.

The screenshot is from the Serialplot program mentioned in the forum recently. It seems quite good.
Using this it is easy to see the relationship of each axis as the board is tilted in various directions.

My feeling is that your project can be done with a PICAXE. No need for one of those A****** thingies.

Cheers,

Buzby

Code:
' Accelerometer ADXL345

#picaxe 28X2
#no_data
#no_table

#terminal 9600


symbol X_raw  = w2  ' Raw 16 bit 2c values
symbol Y_raw  = w3 
symbol Z_raw  = w4

symbol X_out  = w5  ' Converted values
symbol Y_out  = w6
symbol Z_out  = w7

symbol X_sgn  = b16 ' Sign labels
symbol Y_sgn  = b17
symbol Z_sgn  = b18

sertxd(cr,lf,"Accelerometer ADXL345",cr,lf)


' Initialise I2C
hi2csetup i2cmaster, $A6, i2cslow, i2cbyte
 
' Show chip ID
hi2cin $00, (b0)
sertxd("DevID=",#b0,cr,lf)

' Quit if chip ID wrong
if b0 <> 229 then
    sertxd("--- Problem ---")
    end
endif

' Set FullRes bit
' hi2cout $31, (8)

' Start measuring
hi2cout $2D, (8)

do
    ' Read registers XYZ
    hi2cin $32, (b4,b5,b6,b7,b8,b9)

      ' Convert X
    if X_raw > $8000 then
        X_sgn = "-"
        X_out = 0 - X_raw
    else
        X_sgn = "+"
        X_out = X_raw
    endif   

    ' Convert Y
    if Y_raw > $8000 then
        Y_sgn = "-"
        Y_out = 0 - Y_raw
    else
        Y_sgn = "+"
        y_out = Y_raw
    endif   

    ' Convert Z
    if Z_raw > $8000 then
        Z_sgn = "-"
        Z_out = 0 - Z_raw
    else
        Z_sgn = "+"
        Z_out = Z_raw
    endif   

    sertxd ( X_sgn,#X_out,",",Y_sgn,#Y_out,",",Z_sgn,#Z_out,cr,lf)
    
    pause 100
loop
1540450641789.png
 

Steve2381

Senior Member
Thanks Buzby. I will have a go with this later.
I sat up reading quite a lot about these gyros, and watching some Youtube tutorials. They do make it madly complicated, but from what I understand, you determine the actual 360 degree position by working out what the standard 1g gravity does to more than one of the axis (as you pointed out... a single axis cannot give 360 degree position).
Its certainly more difficult with my lack of knowledge, negative number handling issues and no decimal points to play with... but hey, who doesn't love a challenge (me... at 1am looking at a debug screen)
 
Top