mirror of https://github.com/arendst/Tasmota.git
208 lines
7.3 KiB
C++
208 lines
7.3 KiB
C++
/*
|
|
xsns_32_mpu6050.ino - MPU6050 gyroscope and temperature sensor support for Sonoff-Tasmota
|
|
|
|
Copyright (C) 2018 Oliver Welter
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef USE_I2C
|
|
#ifdef USE_MPU6050
|
|
/*********************************************************************************************\
|
|
* MPU6050 3 axis gyroscope and temperature sensor
|
|
*
|
|
* Source: Oliver Welter, with special thanks to Jeff Rowberg
|
|
*
|
|
* I2C Address: 0x68 or 0x69 with AD0 HIGH
|
|
\*********************************************************************************************/
|
|
|
|
#define XSNS_32 32
|
|
|
|
#define D_SENSOR_MPU6050 "MPU6050"
|
|
|
|
#define MPU_6050_ADDR_AD0_LOW 0x68
|
|
#define MPU_6050_ADDR_AD0_HIGH 0x69
|
|
|
|
uint8_t MPU_6050_address;
|
|
uint8_t MPU_6050_addresses[] = { MPU_6050_ADDR_AD0_LOW, MPU_6050_ADDR_AD0_HIGH };
|
|
uint8_t MPU_6050_found;
|
|
|
|
int16_t MPU_6050_ax = 0, MPU_6050_ay = 0, MPU_6050_az = 0;
|
|
int16_t MPU_6050_gx = 0, MPU_6050_gy = 0, MPU_6050_gz = 0;
|
|
int16_t MPU_6050_temperature = 0;
|
|
|
|
#include <MPU6050.h>
|
|
MPU6050 mpu6050;
|
|
|
|
void MPU_6050PerformReading(void)
|
|
{
|
|
mpu6050.getMotion6(
|
|
&MPU_6050_ax,
|
|
&MPU_6050_ay,
|
|
&MPU_6050_az,
|
|
&MPU_6050_gx,
|
|
&MPU_6050_gy,
|
|
&MPU_6050_gz
|
|
);
|
|
|
|
MPU_6050_temperature = mpu6050.getTemperature();
|
|
}
|
|
|
|
/* Work in progress - not yet fully functional
|
|
void MPU_6050SetGyroOffsets(int x, int y, int z)
|
|
{
|
|
mpu050.setXGyroOffset(x);
|
|
mpu6050.setYGyroOffset(y);
|
|
mpu6050.setZGyroOffset(z);
|
|
}
|
|
|
|
void MPU_6050SetAccelOffsets(int x, int y, int z)
|
|
{
|
|
mpu6050.setXAccelOffset(x);
|
|
mpu6050.setYAccelOffset(y);
|
|
mpu6050.setZAccelOffset(z);
|
|
}
|
|
*/
|
|
|
|
void MPU_6050Detect(void)
|
|
{
|
|
if (MPU_6050_found)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (byte i = 0; i < sizeof(MPU_6050_addresses); i++)
|
|
{
|
|
MPU_6050_address = MPU_6050_addresses[i];
|
|
|
|
mpu6050.setAddr(MPU_6050_address);
|
|
mpu6050.initialize();
|
|
|
|
Settings.flag2.axis_resolution = 2; // Need to be services by command Sensor32
|
|
|
|
MPU_6050_found = mpu6050.testConnection();
|
|
}
|
|
|
|
if (MPU_6050_found)
|
|
{
|
|
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, D_SENSOR_MPU6050, MPU_6050_address);
|
|
AddLog(LOG_LEVEL_DEBUG);
|
|
}
|
|
}
|
|
|
|
#ifdef USE_WEBSERVER
|
|
const char HTTP_SNS_AX_AXIS[] PROGMEM = "%s{s}%s " D_AX_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
const char HTTP_SNS_AY_AXIS[] PROGMEM = "%s{s}%s " D_AY_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
const char HTTP_SNS_AZ_AXIS[] PROGMEM = "%s{s}%s " D_AZ_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
const char HTTP_SNS_GX_AXIS[] PROGMEM = "%s{s}%s " D_GX_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
const char HTTP_SNS_GY_AXIS[] PROGMEM = "%s{s}%s " D_GY_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
const char HTTP_SNS_GZ_AXIS[] PROGMEM = "%s{s}%s " D_GZ_AXIS "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
|
#endif // USE_WEBSERVER
|
|
|
|
#define D_JSON_AXIS_AX "AccelXAxis"
|
|
#define D_JSON_AXIS_AY "AccelYAxis"
|
|
#define D_JSON_AXIS_AZ "AccelZAxis"
|
|
#define D_JSON_AXIS_GX "GyroXAxis"
|
|
#define D_JSON_AXIS_GY "GyroYAxis"
|
|
#define D_JSON_AXIS_GZ "GyroZAxis"
|
|
|
|
void MPU_6050Show(boolean json)
|
|
{
|
|
double tempConv = (MPU_6050_temperature / 340.0 + 35.53);
|
|
|
|
if (MPU_6050_found) {
|
|
MPU_6050PerformReading();
|
|
|
|
char temperature[10];
|
|
dtostrfd(tempConv, Settings.flag2.temperature_resolution, temperature);
|
|
char axis_ax[10];
|
|
dtostrfd(MPU_6050_ax, Settings.flag2.axis_resolution, axis_ax);
|
|
char axis_ay[10];
|
|
dtostrfd(MPU_6050_ay, Settings.flag2.axis_resolution, axis_ay);
|
|
char axis_az[10];
|
|
dtostrfd(MPU_6050_az, Settings.flag2.axis_resolution, axis_az);
|
|
char axis_gx[10];
|
|
dtostrfd(MPU_6050_gx, Settings.flag2.axis_resolution, axis_gx);
|
|
char axis_gy[10];
|
|
dtostrfd(MPU_6050_gy, Settings.flag2.axis_resolution, axis_gy);
|
|
char axis_gz[10];
|
|
dtostrfd(MPU_6050_gz, Settings.flag2.axis_resolution, axis_gz);
|
|
|
|
if (json) {
|
|
char json_axis_ax[40];
|
|
snprintf_P(json_axis_ax, sizeof(json_axis_ax), PSTR(",\"" D_JSON_AXIS_AX "\":%s"), axis_ax);
|
|
char json_axis_ay[40];
|
|
snprintf_P(json_axis_ay, sizeof(json_axis_ay), PSTR(",\"" D_JSON_AXIS_AY "\":%s"), axis_ay);
|
|
char json_axis_az[40];
|
|
snprintf_P(json_axis_az, sizeof(json_axis_az), PSTR(",\"" D_JSON_AXIS_AZ "\":%s"), axis_az);
|
|
char json_axis_gx[40];
|
|
snprintf_P(json_axis_gx, sizeof(json_axis_gx), PSTR(",\"" D_JSON_AXIS_GX "\":%s"), axis_gx);
|
|
char json_axis_gy[40];
|
|
snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy);
|
|
char json_axis_gz[40];
|
|
snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s,\"}"),
|
|
mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz);
|
|
#ifdef USE_DOMOTICZ
|
|
DomoticzTempHumSensor(temperature, 0);
|
|
#endif // USE_DOMOTICZ
|
|
#ifdef USE_WEBSERVER
|
|
} else {
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, D_SENSOR_MPU6050, temperature, TempUnit());
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AX_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_ax);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AY_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_ay);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_AZ_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_az);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GX_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gx);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GY_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gy);
|
|
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GZ_AXIS, mqtt_data, D_SENSOR_MPU6050, axis_gz);
|
|
#endif // USE_WEBSERVER
|
|
}
|
|
}
|
|
}
|
|
|
|
/*********************************************************************************************\
|
|
* Interface
|
|
\*********************************************************************************************/
|
|
|
|
boolean Xsns32(byte function)
|
|
{
|
|
boolean result = false;
|
|
|
|
if (i2c_flg) {
|
|
switch (function) {
|
|
case FUNC_PREP_BEFORE_TELEPERIOD:
|
|
MPU_6050Detect();
|
|
break;
|
|
case FUNC_EVERY_SECOND:
|
|
if (tele_period == Settings.tele_period -3) {
|
|
MPU_6050PerformReading();
|
|
}
|
|
break;
|
|
case FUNC_JSON_APPEND:
|
|
MPU_6050Show(1);
|
|
break;
|
|
#ifdef USE_WEBSERVER
|
|
case FUNC_WEB_APPEND:
|
|
MPU_6050Show(0);
|
|
MPU_6050PerformReading();
|
|
break;
|
|
#endif // USE_WEBSERVER
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#endif // USE_MPU6050
|
|
#endif // USE_I2C
|