Can't read one axis of my GY-521 Gyroscope

So I was using this code:

#include <Wire.h>

const int MPU=0x68;
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

void setup() {
    Wire.begin();
    Wire.beginTransmission(MPU);
    Wire.write(0x6B);
    Wire.write(0);
    Wire.endTransmission(true);
    Serial.begin(9600);
}

void loop() {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 12, true);
    AcX = Wire.read()<<8|Wire.read();
    AcY = Wire.read()<<8|Wire.read();
    AcZ = Wire.read()<<8|Wire.read();
    GyX = Wire.read()<<8|Wire.read();
    GyY = Wire.read()<<8|Wire.read();
    GyZ = Wire.read()<<8|Wire.read();

    Serial.print("Accelerometer: ");
    Serial.print("X = ");
    Serial.print(AcX);
    Serial.print("| Y = ");
    Serial.print(AcY);
    Serial.print("| Z = ");
    Serial.println(AcZ);

    Serial.print("Gyroscope: ");
    Serial.print("X = ");
    Serial.print(GyX);
    Serial.print("| Y = ");
    Serial.print(GyY);
    Serial.print("| Z = ");
    Serial.println(GyZ);
    Serial.println("");
    delay(2000);
}

to try and read a GY-521 sensor that I have with the sensor connected to 3.3V, GND, A4 and A5 and I can get results which change from all the accelerometer sensors by rotating the sensor so that gravity is acting in a different direction and by ‘pitching’ and ‘yawing’ the sensor as it is mounted on the breadboard I get a change in the Y and Z axes of the gyroscope but when I twist the sensor which is the one remaining direction nothing seems to change and my GyroX doesn’t seem to settle at nearly zero like the others but consistently sits at around -3600. I’m wondering if there is anything I can do or if I just have a dodgy sensor

    GyZ = Wire.read()<<8|Wire.read();

Isn’t doing what you think it is.

There is no order of evaluation defined in expressions.

So this code may or may not swap the bytes, or even neglect to read one of them.

You need to force a sequence point between the two calls to read(). Perhaps something like
this could be used:

inline int read_word ()
{
  int result = Wire.read() << 8 ;
  result |= Wire.read() ;
  return result ;
}

Until you get the program semantics correct you can’t assume anything else to be an issue as the compiler
might be generating code that doesn’t do what you are expecting (you can’t blame it if you break the language
rules).

To quote the rules:

Order of evaluation of any part of any expression, including order of evaluation of function arguments is unspecified (with some exceptions listed below). The compiler can evaluate operands and other subexpressions in any order, and may choose another order when the same expression is evaluated again.

There is no concept of left-to-right or right-to-left evaluation in C++.

(from Order of evaluation - cppreference.com)

Which Arduino are you using? You may need pullup resistors on the I2C lines.

That basic code structure has always worked for me, using the MPU-6050 with AVR-based Arduinos, and the avr-gcc compiler, but it is trivial to make the changes suggested above.

Example of a perfectly functional tilt/roll code:

// minimal MPU-6050 tilt and roll
// works perfectly with GY-521, pitch and roll signs agree with arrows on sensor module 7/2019
// tested with eBay Pro Mini, **no external pullups on SDA and SCL** (works with internal pullups!)
//
#include<Wire.h>
const int MPU_addr1 = 0x68;
float xa, ya, za, roll, pitch;

void setup() {

  Wire.begin();                                      //begin the wire communication
  Wire.beginTransmission(MPU_addr1);                 //begin, send the slave adress (in this case 68)
  Wire.write(0x6B);                                  //make the reset (place a 0 into the 6B register)
  Wire.write(0);
  Wire.endTransmission(true);                        //end the transmission
  Serial.begin(9600);
}

void loop() {

  Wire.beginTransmission(MPU_addr1);
  Wire.write(0x3B);  //send starting register address
  Wire.endTransmission(false); //restart for read
  Wire.requestFrom(MPU_addr1, 6, true); //get six bytes accelerometer data

  xa = Wire.read() << 8 | Wire.read();
  ya = Wire.read() << 8 | Wire.read();
  za = Wire.read() << 8 | Wire.read();
// formula from https://wiki.dfrobot.com/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing
  roll = atan2(ya , za) * 180.0 / PI;
  pitch = atan2(-xa , sqrt(ya * ya + za * za)) * 180.0 / PI; //account for roll already applied

  Serial.print("roll = ");
  Serial.print(roll,1);
  Serial.print(", pitch = ");
  Serial.println(pitch,1);
  delay(400);
}

I tried the change suggested by MarkT and the X gyro still doesn’t change when I expect it to although this morning it is reading -4600 rather than -3600. jremington I am using an Arduino Uno. I am sure that code you shared would work because it is only reading the accelerometer which I have measured as working fine. Given how everything else seems to be working fine and it is just this one gyro axis I think it is most likely to be a sensor failure

A bad module is certainly possible. The MPU-6050 was discontinued, so it is not worth investing much time into using it.