connections
Photon --- GY-80
3v3 ---> 3v3
Gnd ---> GND
D0 <---> SDA
D1 ---> SCL
the GY-80 has pull-ups installed so you dont need external ones.
I have modded the code linked above slightly, but i haven’t got the hardware to test it on front of me… let me know how you get on, copy this to the first tab
#include "GY80.h"
GY80 sensor = GY80(); //create GY80 instance
void setup()
{
// initialize serial communication at 115200 bits per second:
Serial.begin(115200);
sensor.begin(); //initialize sensors
}
void loop()
{
GY80_scaled val = sensor.read_scaled(); //get values from all sensors
// print out values
Serial.print("Mag:"); //magnetometer values
Serial.print(val.m_x,2);
Serial.print(',');
Serial.print(val.m_y,2);
Serial.print(',');
Serial.print(val.m_z,2);
Serial.print(' ');
Serial.print("Acc:"); //accelerometer values
Serial.print(val.a_x,3);
Serial.print(',');
Serial.print(val.a_y,3);
Serial.print(',');
Serial.print(val.a_z,3);
Serial.print(' ');
Serial.print("Gyro:"); //gyroscope values
Serial.print(val.g_x,1);
Serial.print(',');
Serial.print(val.g_y,1);
Serial.print(',');
Serial.print(val.g_z,1);
Serial.print(' ');
Serial.print("P:"); //pressure values
Serial.print(val.p,5);
Serial.print(' ');
Serial.print("T:"); //temperature values
Serial.println(val.t,1);
delay(250); // delay in between reads for stability
}
create a new set of tabs in the ide (+ in the top right) called GY80. copy this to the new GY80.cpp tab
#include "application.h"
#include "GY80.h"
#include "math.h"
GY80::GY80()
{
m_scale = 1;
//a_scale = 0;
g_scale = 1;
//g_scale_z = 1;
m_scale_values[0] = 0;
m_scale_values[1] = 100.0/1100;
m_scale_values[2] = 100.0/855;
m_scale_values[3] = 100.0/670;
m_scale_values[4] = 100.0/450;
m_scale_values[5] = 100.0/400;
m_scale_values[6] = 100.0/330;
m_scale_values[7] = 100.0/230;
m_scale_values_z[0] = 0;
m_scale_values_z[1] = 100.0/980;
m_scale_values_z[2] = 100.0/760;
m_scale_values_z[3] = 100.0/600;
m_scale_values_z[4] = 100.0/400;
m_scale_values_z[5] = 100.0/355;
m_scale_values_z[6] = 100.0/295;
m_scale_values_z[7] = 100.0/205;
g_scale_values[0] = 0.007629;
g_scale_values[1] = 0.015259;
g_scale_values[2] = 0.061035;
p_oss = 0;
}
void GY80::begin()
{
Wire.begin();
m_init();
a_init();
g_init();
p_init();
}
GY80_raw GY80::read_raw()
{
GY80_single_raw single;
GY80_raw raw;
single = m_read_raw();
raw.m_x = single.x;
raw.m_y = single.y;
raw.m_z = single.z;
single = g_read_raw();
raw.g_x = single.x;
raw.g_y = single.y;
raw.g_z = single.z;
single = a_read_raw();
raw.a_x = single.x;
raw.a_y = single.y;
raw.a_z = single.z;
raw.p = p_read_raw();
raw.t = t_read_raw();
return raw;
}
GY80_scaled GY80::read_scaled()
{
GY80_single_scaled single;
GY80_scaled scaled;
single = m_read_scaled();
scaled.m_x = single.x;
scaled.m_y = single.y;
scaled.m_z = single.z;
single = g_read_scaled();
scaled.g_x = single.x;
scaled.g_y = single.y;
scaled.g_z = single.z;
single = a_read_scaled();
scaled.a_x = single.x;
scaled.a_y = single.y;
scaled.a_z = single.z;
scaled.p = p_read_scaled();
scaled.t = t_read_scaled();
return scaled;
}
//######################################################### MAGNETOMETER CODE
void GY80::m_init()
{
m_set_scale(GY80_m_scale_8_1);
m_set_mode(GY80_m_mode_continous);
}
GY80_single_raw GY80::m_read_raw()
{
uint8_t* buffer = read(GY80_dev_m,GY80_m_reg_data, 6);
GY80_single_raw raw;
raw.x = (buffer[0] << 8) | buffer[1];
raw.z = (buffer[2] << 8) | buffer[3];
raw.y = (buffer[4] << 8) | buffer[5];
return raw;
}
GY80_single_scaled GY80::m_read_scaled()
{
GY80_single_raw raw = m_read_raw();
GY80_single_scaled scaled;
scaled.x = raw.x * m_scale;
scaled.y = raw.y * m_scale;
scaled.z = raw.z * m_scale_z;
return scaled;
}
void GY80::m_set_scale(uint8_t scale)
{
scale &= 0x07; //only lower 3 bits
m_scale = m_scale_values[scale];
m_scale_z = m_scale_values_z[scale];
write(GY80_dev_m, GY80_m_reg_cfgB, (scale<<5));
}
void GY80::m_set_mode(uint8_t mode)
{
write(GY80_dev_m, GY80_m_reg_mode, mode);
}
//######################################################### ACCELEROMETER CODE
void GY80::a_init()
{
write(GY80_dev_a, GY80_a_reg_pwrctrl, 0x00);
write(GY80_dev_a, GY80_a_reg_pwrctrl, 0x10);
write(GY80_dev_a, GY80_a_reg_pwrctrl, 0x08);
a_set_scale(GY80_a_scale_16);
a_set_bw(GY80_a_bw_12_5);
}
void GY80::a_set_scale(uint8_t scale)
{
uint8_t format = *read(GY80_dev_a,GY80_a_reg_format,1);
scale &= 0x03;
format &= ~0x0F;
format |= scale;
format |= 0x08;
write(GY80_dev_a,GY80_a_reg_format, format);
}
void GY80::a_set_bw(uint8_t bw)
{
bw &= 0x0F;
write(GY80_dev_a,GY80_a_reg_bw,bw);
}
GY80_single_raw GY80::a_read_raw()
{
GY80_single_raw raw;
uint8_t * buf;
buf = read(GY80_dev_a,GY80_a_reg_data,6); //read the acceleration data from the ADXL345
// each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!
// thus we are converting both bytes in to one int
raw.x = (((int16_t)buf[1]) << 8) | buf[0];
raw.y = (((int16_t)buf[3]) << 8) | buf[2];
raw.z = (((int16_t)buf[5]) << 8) | buf[4];
return raw;
}
GY80_single_scaled GY80::a_read_scaled()
{
GY80_single_scaled scaled;
GY80_single_raw raw = a_read_raw();
scaled.x = raw.x * GY80_a_scale;
scaled.y = raw.y * GY80_a_scale;
scaled.z = raw.z * GY80_a_scale;
return scaled;
}
//######################################################### GYROMETER CODE
void GY80::g_init()
{
write(GY80_dev_g, GY80_g_reg_ctrl1, 0x0F); //power on, enable x,y,z
write(GY80_dev_g, GY80_g_reg_ctrl2, 0x00);
write(GY80_dev_g, GY80_g_reg_ctrl3, 0x00);
write(GY80_dev_g, GY80_g_reg_ctrl5, 0x00);
g_set_scale(GY80_g_scale_2000);
}
void GY80::g_set_scale(uint8_t scale)
{
switch(scale)
{
case GY80_g_scale_250:
g_scale = g_scale_values[0];
break;
case GY80_g_scale_500:
g_scale = g_scale_values[1];
break;
case GY80_g_scale_2000:
g_scale = g_scale_values[2];
break;
default:
scale = GY80_g_scale_2000;
g_scale = g_scale_values[2];
break;
}
write(GY80_dev_g, GY80_g_reg_ctrl4, scale);
}
GY80_single_raw GY80::g_read_raw()
{
uint8_t buffer[6];
for(uint8_t i = 0; i<6;i++)
{
buffer[i] = *read(GY80_dev_g,GY80_g_reg_datax+i, 1);
}
GY80_single_raw raw;
raw.x = (buffer[1] << 8) | buffer[0];
raw.y = (buffer[3] << 8) | buffer[2];
raw.z = (buffer[5] << 8) | buffer[4];
return raw;
}
GY80_single_scaled GY80::g_read_scaled()
{
GY80_single_raw raw = g_read_raw();
GY80_single_scaled scaled;
scaled.x = raw.x * g_scale;
scaled.y = raw.y * g_scale;
scaled.z = raw.z * g_scale;
return scaled;
}
//######################################################### BAROMETER CODE
void GY80::p_init()
{
//Wire.begin();
uint8_t * ptr;
ptr = read(GY80_dev_p,0xAA,22);
p_calib.ac1 = (ptr[0]<<8)|ptr[1];
p_calib.ac2 = (ptr[2]<<8)|ptr[3];
p_calib.ac3 = (ptr[4]<<8)|ptr[5];
p_calib.ac4 = (ptr[6]<<8)|ptr[7];
p_calib.ac5 = (ptr[8]<<8)|ptr[9];
p_calib.ac6 = (ptr[10]<<8)|ptr[11];
p_calib.b1 = (ptr[12]<<8)|ptr[13];
p_calib.b2 = (ptr[14]<<8)|ptr[15];
p_calib.mb = (ptr[16]<<8)|ptr[17];
p_calib.mc = (ptr[18]<<8)|ptr[19];
p_calib.md = (ptr[20]<<8)|ptr[21];
t_read_scaled();
}
uint32_t GY80::p_read_raw()
{
uint8_t *buffer;
uint32_t up = 0;
// Write 0x34+(OSS<<6) into register 0xF4
// Request a pressure reading w/ oversampling setting
write(GY80_dev_p, 0xF4, (0x34 + (p_oss<<6)));
// Wait for conversion, delay time dependent on OSS
delay(2 + (3<<p_oss));
// Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
buffer = read(GY80_dev_p,0xF6,3);
up = (((unsigned long) buffer[0] << 16) | ((unsigned long) buffer[1] << 8) | (unsigned long) buffer[2]) >> (8-p_oss);
return up;
}
float GY80::p_read_scaled()
{
long x1, x2, x3, b3, b6, p;
unsigned long b4, b7;
uint32_t up = p_read_raw();
b6 = p_calib.b5 - 4000;
// Calculate B3
x1 = (p_calib.b2 * (b6 * b6)>>12)>>11;
x2 = (p_calib.ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)p_calib.ac1)*4 + x3)<<p_oss) + 2)>>2;
// Calculate B4
x1 = (p_calib.ac3 * b6)>>13;
x2 = (p_calib.b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (p_calib.ac4 * (unsigned long)(x3 + 32768))>>15;
b7 = ((unsigned long)(up - b3) * (50000>>p_oss));
if (b7 < 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;
x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
p += (x1 + x2 + 3791)>>4;
float temp = ((float)p)/100000.0;
return temp;
}
float GY80::p_read_altitude()
{
float A = p_read_scaled()/1.01325;
float B = 1/5.25588;
float C = pow(A,B);
C = 1 - C;
C = C /0.0000225577;
return C;
}
uint16_t GY80::t_read_raw()
{
uint16_t ut;
uint8_t *buffer;
// Write 0x2E into Register 0xF4
// This requests a temperature reading
write(GY80_dev_p, 0xF4, 0x2E);
// Wait at least 4.5ms
delay(5);
buffer = read(GY80_dev_p,0xF6,2);
// Read two bytes from registers 0xF6 and 0xF7
ut = (buffer[0]<<8)|buffer[1];
return ut;
}
float GY80::t_read_scaled()
{
uint16_t ut = t_read_raw();
long x1, x2;
x1 = (((long)ut - (long)p_calib.ac6)*(long)p_calib.ac5) >> 15;
x2 = ((long)p_calib.mc << 11)/(x1 + p_calib.md);
p_calib.b5 = x1 + x2;
float temp = ((p_calib.b5 + 8)>>4);
temp = temp /10;
return temp;
}
//######################################################### I2C CODE
void GY80::write(uint8_t device, uint8_t address, uint8_t data)
{
Wire.beginTransmission(device);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}
uint8_t* GY80::read(uint8_t device, uint8_t address, uint8_t length)
{
Wire.beginTransmission(device);
Wire.write(address);
Wire.endTransmission();
//Wire.beginTransmission(device);
Wire.requestFrom(device, length);
uint8_t buffer[length];
while(Wire.available()<length);
if(Wire.available() == length)
{
for(uint8_t i = 0; i < length; i++)
{
buffer[i] = Wire.read();
}
}
Wire.endTransmission();
return buffer;
}
this to the GY80.h tab
#ifndef GY80_H
#define GY80_H
#include "application.h"
#define GY80_dev_m 0x1E
#define GY80_dev_a 0x53
#define GY80_dev_g 0x69
#define GY80_dev_p 0x77
#define GY80_m_reg_cfgA 0x00
#define GY80_m_reg_cfgB 0x01
#define GY80_m_reg_mode 0x02
#define GY80_m_reg_data 0x03
#define GY80_m_mode_continous 0x00
#define GY80_m_mode_single 0x01
#define GY80_m_mode_idle 0x03
#define GY80_m_scale_0_88 0x00
#define GY80_m_scale_1_3 0x01
#define GY80_m_scale_1_9 0x02
#define GY80_m_scale_2_5 0x03
#define GY80_m_scale_4_0 0x04
#define GY80_m_scale_4_7 0x05
#define GY80_m_scale_5_6 0x06
#define GY80_m_scale_8_1 0x07
#define GY80_g_reg_ctrl1 0x20
#define GY80_g_reg_ctrl2 0x21
#define GY80_g_reg_ctrl3 0x22
#define GY80_g_reg_ctrl4 0x23
#define GY80_g_reg_ctrl5 0x24
#define GY80_g_reg_datax 0x28
#define GY80_g_reg_datay 0x2A
#define GY80_g_reg_dataz 0x2C
#define GY80_g_scale_250 0x00
#define GY80_g_scale_500 0x10
#define GY80_g_scale_2000 0x30
#define GY80_a_reg_pwrctrl 0x2D
#define GY80_a_reg_data 0x32
#define GY80_a_reg_format 0x31
#define GY80_a_reg_bw 0x2C
#define GY80_a_bw_3200 0b1111 // 1600Hz Bandwidth 140µA IDD
#define GY80_a_bw_1600 0b1110 // 800Hz Bandwidth 90µA IDD
#define GY80_a_bw_800 0b1101 // 400Hz Bandwidth 140µA IDD
#define GY80_a_bw_400 0b1100 // 200Hz Bandwidth 140µA IDD
#define GY80_a_bw_200 0b1011 // 100Hz Bandwidth 140µA IDD
#define GY80_a_bw_100 0b1010 // 50Hz Bandwidth 140µA IDD
#define GY80_a_bw_50 0b1001 // 25Hz Bandwidth 90µA IDD
#define GY80_a_bw_25 0b1000 // 12.5Hz Bandwidth 60µA IDD
#define GY80_a_bw_12_5 0b0111 // 6.25Hz Bandwidth 50µA IDD
#define GY80_a_bw_6_25 0b0110 // 3.13Hz Bandwidth 45µA IDD
#define GY80_a_bw_3_13 0b0101 // 1.56Hz Bandwidth 40µA IDD
#define GY80_a_bw_1_56 0b0100 // 0.78Hz Bandwidth 34µA IDD
#define GY80_a_bw_0_78 0b0011 // 0.39Hz Bandwidth 23µA IDD
#define GY80_a_bw_0_39 0b0010 // 0.20Hz Bandwidth 23µA IDD
#define GY80_a_bw_0_20 0b0001 // 0.10Hz Bandwidth 23µA IDD
#define GY80_a_bw_0_10 0b0000 // 0.05Hz Bandwidth 23µA IDD (default value)
#define GY80_a_scale 0.004
#define GY80_a_scale_2 0x00
#define GY80_a_scale_4 0x01
#define GY80_a_scale_8 0x02
#define GY80_a_scale_16 0x03
struct GY80_scaled
{
float a_x;
float a_y;
float a_z;
float m_x;
float m_y;
float m_z;
float g_x;
float g_y;
float g_z;
float p;
float t;
};
struct GY80_raw
{
int16_t a_x;
int16_t a_y;
int16_t a_z;
int16_t m_x;
int16_t m_y;
int16_t m_z;
int16_t g_x;
int16_t g_y;
int16_t g_z;
uint32_t p;
uint16_t t;
};
struct GY80_single_raw
{
int16_t x;
int16_t y;
int16_t z;
};
struct GY80_single_scaled
{
float x;
float y;
float z;
};
struct GY80_p_calibration_type
{
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;
long b5;
};
class GY80
{
public:
GY80();
void begin();
GY80_raw read_raw();
GY80_scaled read_scaled();
//magnetometer HMC5883L
void m_set_mode(uint8_t mode);
void m_set_scale(uint8_t scale);
GY80_single_raw m_read_raw();
GY80_single_scaled m_read_scaled();
//accelerometer
void a_set_scale(uint8_t scale);
void a_set_bw(uint8_t bw);
GY80_single_raw a_read_raw();
GY80_single_scaled a_read_scaled();
//gyro
void g_set_scale(uint8_t scale);
GY80_single_raw g_read_raw();
GY80_single_scaled g_read_scaled();
//pressure
uint32_t p_read_raw();
float p_read_scaled();
float p_read_altitude();
//temperature
uint16_t t_read_raw();
float t_read_scaled();
protected:
void m_init();
void a_init();
void g_init();
void p_init();
void write(uint8_t device, uint8_t address, uint8_t data);
uint8_t* read(uint8_t device, uint8_t address, uint8_t length);
private:
float m_scale;
float m_scale_values[8];
float m_scale_z;
float m_scale_values_z[8];
float g_scale;
float g_scale_values[3];
unsigned char p_oss;
GY80_p_calibration_type p_calib;
};
#endif // GY80_H