Merge branch 'arendst/development' into development

This commit is contained in:
reloxx13 2018-07-31 22:22:11 +02:00
commit daac8999a1
44 changed files with 7751 additions and 177 deletions

View File

@ -0,0 +1,372 @@
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class using DMP (MotionApps v2.0)
// 6/21/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2013-05-08 - added seamless Fastwire support
// - added note about gyro calibration
// 2012-06-21 - added note about Arduino 1.0.1 + Leonardo compatibility error
// 2012-06-20 - improved FIFO overflow handling and simplified read process
// 2012-06-19 - completely rearranged DMP initialization code and simplification
// 2012-06-13 - pull gyro and accel data from FIFO packet instead of reading directly
// 2012-06-09 - fix broken FIFO read sequence and change interrupt detection to RISING
// 2012-06-05 - add gravity-compensated initial reference frame acceleration output
// - add 3D math helper file to DMP6 example sketch
// - add Euler output and Yaw/Pitch/Roll output formats
// 2012-06-04 - remove accel offset clearing for better results (thanks Sungon Lee)
// 2012-06-01 - fixed gyro sensitivity to be 2000 deg/sec instead of 250
// 2012-05-30 - basic DMP initialization working
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
//#include "MPU6050.h" // not necessary if using MotionApps include file
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 mpu;
//MPU6050 mpu(0x69); // <-- use for AD0 high
/* =========================================================================
NOTE: In addition to connection 3.3v, GND, SDA, and SCL, this sketch
depends on the MPU-6050's INT pin being connected to the Arduino's
external interrupt #0 pin. On the Arduino Uno and Mega 2560, this is
digital I/O pin 2.
* ========================================================================= */
/* =========================================================================
NOTE: Arduino v1.0.1 with the Leonardo board generates a compile error
when using Serial.write(buf, len). The Teapot output uses this method.
The solution requires a modification to the Arduino USBAPI.h file, which
is fortunately simple, but annoying. This will be fixed in the next IDE
release. For more info, see these links:
http://arduino.cc/forum/index.php/topic,109987.0.html
http://code.google.com/p/arduino/issues/detail?id=958
* ========================================================================= */
// uncomment "OUTPUT_READABLE_QUATERNION" if you want to see the actual
// quaternion components in a [w, x, y, z] format (not best for parsing
// on a remote host such as Processing or something though)
//#define OUTPUT_READABLE_QUATERNION
// uncomment "OUTPUT_READABLE_EULER" if you want to see Euler angles
// (in degrees) calculated from the quaternions coming from the FIFO.
// Note that Euler angles suffer from gimbal lock (for more info, see
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER
// uncomment "OUTPUT_READABLE_YAWPITCHROLL" if you want to see the yaw/
// pitch/roll angles (in degrees) calculated from the quaternions coming
// from the FIFO. Note this also requires gravity vector calculations.
// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL
// uncomment "OUTPUT_READABLE_REALACCEL" if you want to see acceleration
// components with gravity removed. This acceleration reference frame is
// not compensated for orientation, so +X is always +X according to the
// sensor, just without the effects of gravity. If you want acceleration
// compensated for orientation, us OUTPUT_READABLE_WORLDACCEL instead.
//#define OUTPUT_READABLE_REALACCEL
// uncomment "OUTPUT_READABLE_WORLDACCEL" if you want to see acceleration
// components with gravity removed and adjusted for the world frame of
// reference (yaw is relative to initial orientation, since no magnetometer
// is present in this case). Could be quite handy in some cases.
//#define OUTPUT_READABLE_WORLDACCEL
// uncomment "OUTPUT_TEAPOT" if you want output that matches the
// format used for the InvenSense teapot demo
//#define OUTPUT_TEAPOT
#define LED_PIN 13 // (Arduino is 13, Teensy is 11, Teensy++ is 6)
bool blinkState = false;
// MPU control/status vars
bool dmpReady = false; // set true if DMP init was successful
uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer
// orientation/motion vars
Quaternion q; // [w, x, y, z] quaternion container
VectorInt16 aa; // [x, y, z] accel sensor measurements
VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
VectorFloat gravity; // [x, y, z] gravity vector
float euler[3]; // [psi, theta, phi] Euler angle container
float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
// packet structure for InvenSense teapot demo
uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };
// ================================================================
// === INTERRUPT DETECTION ROUTINE ===
// ================================================================
volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
mpuInterrupt = true;
}
// ================================================================
// === INITIAL SETUP ===
// ================================================================
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialize serial communication
// (115200 chosen because it is required for Teapot Demo output, but it's
// really up to you depending on your project)
Serial.begin(115200);
while (!Serial); // wait for Leonardo enumeration, others continue immediately
// NOTE: 8MHz or slower host processors, like the Teensy @ 3.3v or Ardunio
// Pro Mini running at 3.3v, cannot handle this baud rate reliably due to
// the baud timing being too misaligned with processor ticks. You must use
// 38400 or slower in these cases, or use some kind of external separate
// crystal solution for the UART timer.
// initialize device
Serial.println(F("Initializing I2C devices..."));
mpu.initialize();
// verify connection
Serial.println(F("Testing device connections..."));
Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
// wait for ready
Serial.println(F("\nSend any character to begin DMP programming and demo: "));
while (Serial.available() && Serial.read()); // empty buffer
while (!Serial.available()); // wait for data
while (Serial.available() && Serial.read()); // empty buffer again
// load and configure the DMP
Serial.println(F("Initializing DMP..."));
devStatus = mpu.dmpInitialize();
// supply your own gyro offsets here, scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788); // 1688 factory default for my test chip
// make sure it worked (returns 0 if so)
if (devStatus == 0) {
// turn on the DMP, now that it's ready
Serial.println(F("Enabling DMP..."));
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
// set our DMP Ready flag so the main loop() function knows it's okay to use it
Serial.println(F("DMP ready! Waiting for first interrupt..."));
dmpReady = true;
// get expected DMP packet size for later comparison
packetSize = mpu.dmpGetFIFOPacketSize();
} else {
// ERROR!
// 1 = initial memory load failed
// 2 = DMP configuration updates failed
// (if it's going to break, usually the code will be 1)
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
// configure LED for output
pinMode(LED_PIN, OUTPUT);
}
// ================================================================
// === MAIN PROGRAM LOOP ===
// ================================================================
void loop() {
// if programming failed, don't try to do anything
if (!dmpReady) return;
// wait for MPU interrupt or extra packet(s) available
while (!mpuInterrupt && fifoCount < packetSize) {
// other program behavior stuff here
// .
// .
// .
// if you are really paranoid you can frequently test in between other
// stuff to see if mpuInterrupt is true, and if so, "break;" from the
// while() loop to immediately process the MPU data
// .
// .
// .
}
// reset interrupt flag and get INT_STATUS byte
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
// get current FIFO count
fifoCount = mpu.getFIFOCount();
// check for overflow (this should never happen unless our code is too inefficient)
if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
// reset so we can continue cleanly
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
// otherwise, check for DMP data ready interrupt (this should happen frequently)
} else if (mpuIntStatus & 0x02) {
// wait for correct available data length, should be a VERY short wait
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
// read a packet from FIFO
mpu.getFIFOBytes(fifoBuffer, packetSize);
// track FIFO count here in case there is > 1 packet available
// (this lets us immediately read more without waiting for an interrupt)
fifoCount -= packetSize;
#ifdef OUTPUT_READABLE_QUATERNION
// display quaternion values in easy matrix form: w x y z
mpu.dmpGetQuaternion(&q, fifoBuffer);
Serial.print("quat\t");
Serial.print(q.w);
Serial.print("\t");
Serial.print(q.x);
Serial.print("\t");
Serial.print(q.y);
Serial.print("\t");
Serial.println(q.z);
#endif
#ifdef OUTPUT_READABLE_EULER
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetEuler(euler, &q);
Serial.print("euler\t");
Serial.print(euler[0] * 180/M_PI);
Serial.print("\t");
Serial.print(euler[1] * 180/M_PI);
Serial.print("\t");
Serial.println(euler[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_YAWPITCHROLL
// display Euler angles in degrees
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
Serial.print("ypr\t");
Serial.print(ypr[0] * 180/M_PI);
Serial.print("\t");
Serial.print(ypr[1] * 180/M_PI);
Serial.print("\t");
Serial.println(ypr[2] * 180/M_PI);
#endif
#ifdef OUTPUT_READABLE_REALACCEL
// display real acceleration, adjusted to remove gravity
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
Serial.print("areal\t");
Serial.print(aaReal.x);
Serial.print("\t");
Serial.print(aaReal.y);
Serial.print("\t");
Serial.println(aaReal.z);
#endif
#ifdef OUTPUT_READABLE_WORLDACCEL
// display initial world-frame acceleration, adjusted to remove gravity
// and rotated based on known orientation from quaternion
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetAccel(&aa, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
Serial.print("aworld\t");
Serial.print(aaWorld.x);
Serial.print("\t");
Serial.print(aaWorld.y);
Serial.print("\t");
Serial.println(aaWorld.z);
#endif
#ifdef OUTPUT_TEAPOT
// display quaternion values in InvenSense Teapot demo format:
teapotPacket[2] = fifoBuffer[0];
teapotPacket[3] = fifoBuffer[1];
teapotPacket[4] = fifoBuffer[4];
teapotPacket[5] = fifoBuffer[5];
teapotPacket[6] = fifoBuffer[8];
teapotPacket[7] = fifoBuffer[9];
teapotPacket[8] = fifoBuffer[12];
teapotPacket[9] = fifoBuffer[13];
Serial.write(teapotPacket, 14);
teapotPacket[11]++; // packetCount, loops at 0xFF on purpose
#endif
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
}

View File

@ -0,0 +1,247 @@
// I2C device class (I2Cdev) demonstration Processing sketch for MPU6050 DMP output
// 6/20/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2012-06-20 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
import processing.serial.*;
import processing.opengl.*;
import toxi.geom.*;
import toxi.processing.*;
// NOTE: requires ToxicLibs to be installed in order to run properly.
// 1. Download from http://toxiclibs.org/downloads
// 2. Extract into [userdir]/Processing/libraries
// (location may be different on Mac/Linux)
// 3. Run and bask in awesomeness
ToxiclibsSupport gfx;
Serial port; // The serial port
char[] teapotPacket = new char[14]; // InvenSense Teapot packet
int serialCount = 0; // current packet byte position
int aligned = 0;
int interval = 0;
float[] q = new float[4];
Quaternion quat = new Quaternion(1, 0, 0, 0);
float[] gravity = new float[3];
float[] euler = new float[3];
float[] ypr = new float[3];
void setup() {
// 300px square viewport using OpenGL rendering
size(300, 300, OPENGL);
gfx = new ToxiclibsSupport(this);
// setup lights and antialiasing
lights();
smooth();
// display serial port list for debugging/clarity
println(Serial.list());
// get the first available port (use EITHER this OR the specific port code below)
String portName = "/dev/ttyUSB1";
// get a specific serial port (use EITHER this OR the first-available code above)
//String portName = "COM4";
// open the serial port
port = new Serial(this, portName, 115200);
// send single character to trigger DMP init/start
// (expected by MPU6050_DMP6 example Arduino sketch)
port.write('r');
}
void draw() {
if (millis() - interval > 1000) {
// resend single character to trigger DMP init/start
// in case the MPU is halted/reset while applet is running
port.write('r');
interval = millis();
}
// black background
background(0);
// translate everything to the middle of the viewport
pushMatrix();
translate(width / 2, height / 2);
// 3-step rotation from yaw/pitch/roll angles (gimbal lock!)
// ...and other weirdness I haven't figured out yet
//rotateY(-ypr[0]);
//rotateZ(-ypr[1]);
//rotateX(-ypr[2]);
// toxiclibs direct angle/axis rotation from quaternion (NO gimbal lock!)
// (axis order [1, 3, 2] and inversion [-1, +1, +1] is a consequence of
// different coordinate system orientation assumptions between Processing
// and InvenSense DMP)
float[] axis = quat.toAxisAngle();
rotate(axis[0], -axis[1], axis[3], axis[2]);
// draw main body in red
fill(255, 0, 0, 200);
box(10, 10, 200);
// draw front-facing tip in blue
fill(0, 0, 255, 200);
pushMatrix();
translate(0, 0, -120);
rotateX(PI/2);
drawCylinder(0, 20, 20, 8);
popMatrix();
// draw wings and tail fin in green
fill(0, 255, 0, 200);
beginShape(TRIANGLES);
vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // wing top layer
vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // wing bottom layer
vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // tail left layer
vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); // tail right layer
endShape();
beginShape(QUADS);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80);
vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98);
vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70);
endShape();
popMatrix();
}
void serialEvent(Serial port) {
interval = millis();
while (port.available() > 0) {
int ch = port.read();
print((char)ch);
if (ch == '$') {serialCount = 0;} // this will help with alignment
if (aligned < 4) {
// make sure we are properly aligned on a 14-byte packet
if (serialCount == 0) {
if (ch == '$') aligned++; else aligned = 0;
} else if (serialCount == 1) {
if (ch == 2) aligned++; else aligned = 0;
} else if (serialCount == 12) {
if (ch == '\r') aligned++; else aligned = 0;
} else if (serialCount == 13) {
if (ch == '\n') aligned++; else aligned = 0;
}
//println(ch + " " + aligned + " " + serialCount);
serialCount++;
if (serialCount == 14) serialCount = 0;
} else {
if (serialCount > 0 || ch == '$') {
teapotPacket[serialCount++] = (char)ch;
if (serialCount == 14) {
serialCount = 0; // restart packet byte position
// get quaternion from data packet
q[0] = ((teapotPacket[2] << 8) | teapotPacket[3]) / 16384.0f;
q[1] = ((teapotPacket[4] << 8) | teapotPacket[5]) / 16384.0f;
q[2] = ((teapotPacket[6] << 8) | teapotPacket[7]) / 16384.0f;
q[3] = ((teapotPacket[8] << 8) | teapotPacket[9]) / 16384.0f;
for (int i = 0; i < 4; i++) if (q[i] >= 2) q[i] = -4 + q[i];
// set our toxilibs quaternion to new data
quat.set(q[0], q[1], q[2], q[3]);
/*
// below calculations unnecessary for orientation only using toxilibs
// calculate gravity vector
gravity[0] = 2 * (q[1]*q[3] - q[0]*q[2]);
gravity[1] = 2 * (q[0]*q[1] + q[2]*q[3]);
gravity[2] = q[0]*q[0] - q[1]*q[1] - q[2]*q[2] + q[3]*q[3];
// calculate Euler angles
euler[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
euler[1] = -asin(2*q[1]*q[3] + 2*q[0]*q[2]);
euler[2] = atan2(2*q[2]*q[3] - 2*q[0]*q[1], 2*q[0]*q[0] + 2*q[3]*q[3] - 1);
// calculate yaw/pitch/roll angles
ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1);
ypr[1] = atan(gravity[0] / sqrt(gravity[1]*gravity[1] + gravity[2]*gravity[2]));
ypr[2] = atan(gravity[1] / sqrt(gravity[0]*gravity[0] + gravity[2]*gravity[2]));
// output various components for debugging
//println("q:\t" + round(q[0]*100.0f)/100.0f + "\t" + round(q[1]*100.0f)/100.0f + "\t" + round(q[2]*100.0f)/100.0f + "\t" + round(q[3]*100.0f)/100.0f);
//println("euler:\t" + euler[0]*180.0f/PI + "\t" + euler[1]*180.0f/PI + "\t" + euler[2]*180.0f/PI);
//println("ypr:\t" + ypr[0]*180.0f/PI + "\t" + ypr[1]*180.0f/PI + "\t" + ypr[2]*180.0f/PI);
*/
}
}
}
}
}
void drawCylinder(float topRadius, float bottomRadius, float tall, int sides) {
float angle = 0;
float angleIncrement = TWO_PI / sides;
beginShape(QUAD_STRIP);
for (int i = 0; i < sides + 1; ++i) {
vertex(topRadius*cos(angle), 0, topRadius*sin(angle));
vertex(bottomRadius*cos(angle), tall, bottomRadius*sin(angle));
angle += angleIncrement;
}
endShape();
// If it is not a cone, draw the circular top cap
if (topRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, 0, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(topRadius * cos(angle), 0, topRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
// If it is not a cone, draw the circular bottom cap
if (bottomRadius != 0) {
angle = 0;
beginShape(TRIANGLE_FAN);
// Center point
vertex(0, tall, 0);
for (int i = 0; i < sides + 1; i++) {
vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle));
angle += angleIncrement;
}
endShape();
}
}

View File

@ -0,0 +1,151 @@
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
// 10/7/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2013-05-08 - added multiple output formats
// - added seamless Fastwire support
// 2011-10-07 - initial release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2011 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"
// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;
//MPU6050 accelgyro(0x69); // <-- use for AD0 high
int16_t ax, ay, az;
int16_t gx, gy, gz;
// uncomment "OUTPUT_READABLE_ACCELGYRO" if you want to see a tab-separated
// list of the accel X/Y/Z and then gyro X/Y/Z values in decimal. Easy to read,
// not so easy to parse, and slow(er) over UART.
#define OUTPUT_READABLE_ACCELGYRO
// uncomment "OUTPUT_BINARY_ACCELGYRO" to send all 6 axes of data as 16-bit
// binary, one right after the other. This is very fast (as fast as possible
// without compression or data loss), and easy to parse, but impossible to read
// for a human.
//#define OUTPUT_BINARY_ACCELGYRO
#define LED_PIN 13
bool blinkState = false;
void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
// initialize serial communication
// (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
// it's really up to you depending on your project)
Serial.begin(38400);
// initialize device
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
// use the code below to change accel/gyro offset values
/*
Serial.println("Updating internal sensor offsets...");
// -76 -2359 1688 0 0 0
Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
Serial.print("\n");
accelgyro.setXGyroOffset(220);
accelgyro.setYGyroOffset(76);
accelgyro.setZGyroOffset(-85);
Serial.print(accelgyro.getXAccelOffset()); Serial.print("\t"); // -76
Serial.print(accelgyro.getYAccelOffset()); Serial.print("\t"); // -2359
Serial.print(accelgyro.getZAccelOffset()); Serial.print("\t"); // 1688
Serial.print(accelgyro.getXGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getYGyroOffset()); Serial.print("\t"); // 0
Serial.print(accelgyro.getZGyroOffset()); Serial.print("\t"); // 0
Serial.print("\n");
*/
// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// these methods (and a few others) are also available
//accelgyro.getAcceleration(&ax, &ay, &az);
//accelgyro.getRotation(&gx, &gy, &gz);
#ifdef OUTPUT_READABLE_ACCELGYRO
// display tab-separated accel/gyro x/y/z values
Serial.print("a/g:\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.print(az); Serial.print("\t");
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.println(gz);
#endif
#ifdef OUTPUT_BINARY_ACCELGYRO
Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
Serial.write((uint8_t)(gx >> 8)); Serial.write((uint8_t)(gx & 0xFF));
Serial.write((uint8_t)(gy >> 8)); Serial.write((uint8_t)(gy & 0xFF));
Serial.write((uint8_t)(gz >> 8)); Serial.write((uint8_t)(gz & 0xFF));
#endif
// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}

3151
lib/MPU6050/MPU6050.cpp Normal file

File diff suppressed because it is too large Load Diff

993
lib/MPU6050/MPU6050.h Normal file
View File

@ -0,0 +1,993 @@
// I2Cdev library collection - MPU6050 I2C device class
// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
// 10/3/2011 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Adapted for Sonoff-Tasmota by Oliver Welter <contact@verbotene.zone> 02-04-2018
//
// Changelog:
// ... - ongoing debug release
// NOTE: THIS IS ONLY A PARIAL RELEASE. THIS DEVICE CLASS IS CURRENTLY UNDERGOING ACTIVE
// DEVELOPMENT AND IS STILL MISSING SOME IMPORTANT FEATURES. PLEASE KEEP THIS IN MIND IF
// YOU DECIDE TO USE THIS PARTICULAR CODE FOR ANYTHING.
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#ifndef _MPU6050_H_
#define _MPU6050_H_
#include "I2Cdev.h"
//#include <avr/pgmspace.h>
#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board
#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC)
#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW
#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN
#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN
#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN
#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS
#define MPU6050_RA_XA_OFFS_L_TC 0x07
#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS
#define MPU6050_RA_YA_OFFS_L_TC 0x09
#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS
#define MPU6050_RA_ZA_OFFS_L_TC 0x0B
#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR
#define MPU6050_RA_XG_OFFS_USRL 0x14
#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR
#define MPU6050_RA_YG_OFFS_USRL 0x16
#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR
#define MPU6050_RA_ZG_OFFS_USRL 0x18
#define MPU6050_RA_SMPLRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_FF_THR 0x1D
#define MPU6050_RA_FF_DUR 0x1E
#define MPU6050_RA_MOT_THR 0x1F
#define MPU6050_RA_MOT_DUR 0x20
#define MPU6050_RA_ZRMOT_THR 0x21
#define MPU6050_RA_ZRMOT_DUR 0x22
#define MPU6050_RA_FIFO_EN 0x23
#define MPU6050_RA_I2C_MST_CTRL 0x24
#define MPU6050_RA_I2C_SLV0_ADDR 0x25
#define MPU6050_RA_I2C_SLV0_REG 0x26
#define MPU6050_RA_I2C_SLV0_CTRL 0x27
#define MPU6050_RA_I2C_SLV1_ADDR 0x28
#define MPU6050_RA_I2C_SLV1_REG 0x29
#define MPU6050_RA_I2C_SLV1_CTRL 0x2A
#define MPU6050_RA_I2C_SLV2_ADDR 0x2B
#define MPU6050_RA_I2C_SLV2_REG 0x2C
#define MPU6050_RA_I2C_SLV2_CTRL 0x2D
#define MPU6050_RA_I2C_SLV3_ADDR 0x2E
#define MPU6050_RA_I2C_SLV3_REG 0x2F
#define MPU6050_RA_I2C_SLV3_CTRL 0x30
#define MPU6050_RA_I2C_SLV4_ADDR 0x31
#define MPU6050_RA_I2C_SLV4_REG 0x32
#define MPU6050_RA_I2C_SLV4_DO 0x33
#define MPU6050_RA_I2C_SLV4_CTRL 0x34
#define MPU6050_RA_I2C_SLV4_DI 0x35
#define MPU6050_RA_I2C_MST_STATUS 0x36
#define MPU6050_RA_INT_PIN_CFG 0x37
#define MPU6050_RA_INT_ENABLE 0x38
#define MPU6050_RA_DMP_INT_STATUS 0x39
#define MPU6050_RA_INT_STATUS 0x3A
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_ACCEL_XOUT_L 0x3C
#define MPU6050_RA_ACCEL_YOUT_H 0x3D
#define MPU6050_RA_ACCEL_YOUT_L 0x3E
#define MPU6050_RA_ACCEL_ZOUT_H 0x3F
#define MPU6050_RA_ACCEL_ZOUT_L 0x40
#define MPU6050_RA_TEMP_OUT_H 0x41
#define MPU6050_RA_TEMP_OUT_L 0x42
#define MPU6050_RA_GYRO_XOUT_H 0x43
#define MPU6050_RA_GYRO_XOUT_L 0x44
#define MPU6050_RA_GYRO_YOUT_H 0x45
#define MPU6050_RA_GYRO_YOUT_L 0x46
#define MPU6050_RA_GYRO_ZOUT_H 0x47
#define MPU6050_RA_GYRO_ZOUT_L 0x48
#define MPU6050_RA_EXT_SENS_DATA_00 0x49
#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
#define MPU6050_RA_EXT_SENS_DATA_07 0x50
#define MPU6050_RA_EXT_SENS_DATA_08 0x51
#define MPU6050_RA_EXT_SENS_DATA_09 0x52
#define MPU6050_RA_EXT_SENS_DATA_10 0x53
#define MPU6050_RA_EXT_SENS_DATA_11 0x54
#define MPU6050_RA_EXT_SENS_DATA_12 0x55
#define MPU6050_RA_EXT_SENS_DATA_13 0x56
#define MPU6050_RA_EXT_SENS_DATA_14 0x57
#define MPU6050_RA_EXT_SENS_DATA_15 0x58
#define MPU6050_RA_EXT_SENS_DATA_16 0x59
#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
#define MPU6050_RA_EXT_SENS_DATA_23 0x60
#define MPU6050_RA_MOT_DETECT_STATUS 0x61
#define MPU6050_RA_I2C_SLV0_DO 0x63
#define MPU6050_RA_I2C_SLV1_DO 0x64
#define MPU6050_RA_I2C_SLV2_DO 0x65
#define MPU6050_RA_I2C_SLV3_DO 0x66
#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67
#define MPU6050_RA_SIGNAL_PATH_RESET 0x68
#define MPU6050_RA_MOT_DETECT_CTRL 0x69
#define MPU6050_RA_USER_CTRL 0x6A
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_PWR_MGMT_2 0x6C
#define MPU6050_RA_BANK_SEL 0x6D
#define MPU6050_RA_MEM_START_ADDR 0x6E
#define MPU6050_RA_MEM_R_W 0x6F
#define MPU6050_RA_DMP_CFG_1 0x70
#define MPU6050_RA_DMP_CFG_2 0x71
#define MPU6050_RA_FIFO_COUNTH 0x72
#define MPU6050_RA_FIFO_COUNTL 0x73
#define MPU6050_RA_FIFO_R_W 0x74
#define MPU6050_RA_WHO_AM_I 0x75
#define MPU6050_TC_PWR_MODE_BIT 7
#define MPU6050_TC_OFFSET_BIT 6
#define MPU6050_TC_OFFSET_LENGTH 6
#define MPU6050_TC_OTP_BNK_VLD_BIT 0
#define MPU6050_VDDIO_LEVEL_VLOGIC 0
#define MPU6050_VDDIO_LEVEL_VDD 1
#define MPU6050_CFG_EXT_SYNC_SET_BIT 5
#define MPU6050_CFG_EXT_SYNC_SET_LENGTH 3
#define MPU6050_CFG_DLPF_CFG_BIT 2
#define MPU6050_CFG_DLPF_CFG_LENGTH 3
#define MPU6050_EXT_SYNC_DISABLED 0x0
#define MPU6050_EXT_SYNC_TEMP_OUT_L 0x1
#define MPU6050_EXT_SYNC_GYRO_XOUT_L 0x2
#define MPU6050_EXT_SYNC_GYRO_YOUT_L 0x3
#define MPU6050_EXT_SYNC_GYRO_ZOUT_L 0x4
#define MPU6050_EXT_SYNC_ACCEL_XOUT_L 0x5
#define MPU6050_EXT_SYNC_ACCEL_YOUT_L 0x6
#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L 0x7
#define MPU6050_DLPF_BW_256 0x00
#define MPU6050_DLPF_BW_188 0x01
#define MPU6050_DLPF_BW_98 0x02
#define MPU6050_DLPF_BW_42 0x03
#define MPU6050_DLPF_BW_20 0x04
#define MPU6050_DLPF_BW_10 0x05
#define MPU6050_DLPF_BW_5 0x06
#define MPU6050_GCONFIG_FS_SEL_BIT 4
#define MPU6050_GCONFIG_FS_SEL_LENGTH 2
#define MPU6050_GYRO_FS_250 0x00
#define MPU6050_GYRO_FS_500 0x01
#define MPU6050_GYRO_FS_1000 0x02
#define MPU6050_GYRO_FS_2000 0x03
#define MPU6050_ACONFIG_XA_ST_BIT 7
#define MPU6050_ACONFIG_YA_ST_BIT 6
#define MPU6050_ACONFIG_ZA_ST_BIT 5
#define MPU6050_ACONFIG_AFS_SEL_BIT 4
#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_ACONFIG_ACCEL_HPF_BIT 2
#define MPU6050_ACONFIG_ACCEL_HPF_LENGTH 3
#define MPU6050_ACCEL_FS_2 0x00
#define MPU6050_ACCEL_FS_4 0x01
#define MPU6050_ACCEL_FS_8 0x02
#define MPU6050_ACCEL_FS_16 0x03
#define MPU6050_DHPF_RESET 0x00
#define MPU6050_DHPF_5 0x01
#define MPU6050_DHPF_2P5 0x02
#define MPU6050_DHPF_1P25 0x03
#define MPU6050_DHPF_0P63 0x04
#define MPU6050_DHPF_HOLD 0x07
#define MPU6050_TEMP_FIFO_EN_BIT 7
#define MPU6050_XG_FIFO_EN_BIT 6
#define MPU6050_YG_FIFO_EN_BIT 5
#define MPU6050_ZG_FIFO_EN_BIT 4
#define MPU6050_ACCEL_FIFO_EN_BIT 3
#define MPU6050_SLV2_FIFO_EN_BIT 2
#define MPU6050_SLV1_FIFO_EN_BIT 1
#define MPU6050_SLV0_FIFO_EN_BIT 0
#define MPU6050_MULT_MST_EN_BIT 7
#define MPU6050_WAIT_FOR_ES_BIT 6
#define MPU6050_SLV_3_FIFO_EN_BIT 5
#define MPU6050_I2C_MST_P_NSR_BIT 4
#define MPU6050_I2C_MST_CLK_BIT 3
#define MPU6050_I2C_MST_CLK_LENGTH 4
#define MPU6050_CLOCK_DIV_348 0x0
#define MPU6050_CLOCK_DIV_333 0x1
#define MPU6050_CLOCK_DIV_320 0x2
#define MPU6050_CLOCK_DIV_308 0x3
#define MPU6050_CLOCK_DIV_296 0x4
#define MPU6050_CLOCK_DIV_286 0x5
#define MPU6050_CLOCK_DIV_276 0x6
#define MPU6050_CLOCK_DIV_267 0x7
#define MPU6050_CLOCK_DIV_258 0x8
#define MPU6050_CLOCK_DIV_500 0x9
#define MPU6050_CLOCK_DIV_471 0xA
#define MPU6050_CLOCK_DIV_444 0xB
#define MPU6050_CLOCK_DIV_421 0xC
#define MPU6050_CLOCK_DIV_400 0xD
#define MPU6050_CLOCK_DIV_381 0xE
#define MPU6050_CLOCK_DIV_364 0xF
#define MPU6050_I2C_SLV_RW_BIT 7
#define MPU6050_I2C_SLV_ADDR_BIT 6
#define MPU6050_I2C_SLV_ADDR_LENGTH 7
#define MPU6050_I2C_SLV_EN_BIT 7
#define MPU6050_I2C_SLV_BYTE_SW_BIT 6
#define MPU6050_I2C_SLV_REG_DIS_BIT 5
#define MPU6050_I2C_SLV_GRP_BIT 4
#define MPU6050_I2C_SLV_LEN_BIT 3
#define MPU6050_I2C_SLV_LEN_LENGTH 4
#define MPU6050_I2C_SLV4_RW_BIT 7
#define MPU6050_I2C_SLV4_ADDR_BIT 6
#define MPU6050_I2C_SLV4_ADDR_LENGTH 7
#define MPU6050_I2C_SLV4_EN_BIT 7
#define MPU6050_I2C_SLV4_INT_EN_BIT 6
#define MPU6050_I2C_SLV4_REG_DIS_BIT 5
#define MPU6050_I2C_SLV4_MST_DLY_BIT 4
#define MPU6050_I2C_SLV4_MST_DLY_LENGTH 5
#define MPU6050_MST_PASS_THROUGH_BIT 7
#define MPU6050_MST_I2C_SLV4_DONE_BIT 6
#define MPU6050_MST_I2C_LOST_ARB_BIT 5
#define MPU6050_MST_I2C_SLV4_NACK_BIT 4
#define MPU6050_MST_I2C_SLV3_NACK_BIT 3
#define MPU6050_MST_I2C_SLV2_NACK_BIT 2
#define MPU6050_MST_I2C_SLV1_NACK_BIT 1
#define MPU6050_MST_I2C_SLV0_NACK_BIT 0
#define MPU6050_INTCFG_INT_LEVEL_BIT 7
#define MPU6050_INTCFG_INT_OPEN_BIT 6
#define MPU6050_INTCFG_LATCH_INT_EN_BIT 5
#define MPU6050_INTCFG_INT_RD_CLEAR_BIT 4
#define MPU6050_INTCFG_FSYNC_INT_LEVEL_BIT 3
#define MPU6050_INTCFG_FSYNC_INT_EN_BIT 2
#define MPU6050_INTCFG_I2C_BYPASS_EN_BIT 1
#define MPU6050_INTCFG_CLKOUT_EN_BIT 0
#define MPU6050_INTMODE_ACTIVEHIGH 0x00
#define MPU6050_INTMODE_ACTIVELOW 0x01
#define MPU6050_INTDRV_PUSHPULL 0x00
#define MPU6050_INTDRV_OPENDRAIN 0x01
#define MPU6050_INTLATCH_50USPULSE 0x00
#define MPU6050_INTLATCH_WAITCLEAR 0x01
#define MPU6050_INTCLEAR_STATUSREAD 0x00
#define MPU6050_INTCLEAR_ANYREAD 0x01
#define MPU6050_INTERRUPT_FF_BIT 7
#define MPU6050_INTERRUPT_MOT_BIT 6
#define MPU6050_INTERRUPT_ZMOT_BIT 5
#define MPU6050_INTERRUPT_FIFO_OFLOW_BIT 4
#define MPU6050_INTERRUPT_I2C_MST_INT_BIT 3
#define MPU6050_INTERRUPT_PLL_RDY_INT_BIT 2
#define MPU6050_INTERRUPT_DMP_INT_BIT 1
#define MPU6050_INTERRUPT_DATA_RDY_BIT 0
// TODO: figure out what these actually do
// UMPL source code is not very obivous
#define MPU6050_DMPINT_5_BIT 5
#define MPU6050_DMPINT_4_BIT 4
#define MPU6050_DMPINT_3_BIT 3
#define MPU6050_DMPINT_2_BIT 2
#define MPU6050_DMPINT_1_BIT 1
#define MPU6050_DMPINT_0_BIT 0
#define MPU6050_MOTION_MOT_XNEG_BIT 7
#define MPU6050_MOTION_MOT_XPOS_BIT 6
#define MPU6050_MOTION_MOT_YNEG_BIT 5
#define MPU6050_MOTION_MOT_YPOS_BIT 4
#define MPU6050_MOTION_MOT_ZNEG_BIT 3
#define MPU6050_MOTION_MOT_ZPOS_BIT 2
#define MPU6050_MOTION_MOT_ZRMOT_BIT 0
#define MPU6050_DELAYCTRL_DELAY_ES_SHADOW_BIT 7
#define MPU6050_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4
#define MPU6050_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3
#define MPU6050_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2
#define MPU6050_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1
#define MPU6050_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0
#define MPU6050_PATHRESET_GYRO_RESET_BIT 2
#define MPU6050_PATHRESET_ACCEL_RESET_BIT 1
#define MPU6050_PATHRESET_TEMP_RESET_BIT 0
#define MPU6050_DETECT_ACCEL_ON_DELAY_BIT 5
#define MPU6050_DETECT_ACCEL_ON_DELAY_LENGTH 2
#define MPU6050_DETECT_FF_COUNT_BIT 3
#define MPU6050_DETECT_FF_COUNT_LENGTH 2
#define MPU6050_DETECT_MOT_COUNT_BIT 1
#define MPU6050_DETECT_MOT_COUNT_LENGTH 2
#define MPU6050_DETECT_DECREMENT_RESET 0x0
#define MPU6050_DETECT_DECREMENT_1 0x1
#define MPU6050_DETECT_DECREMENT_2 0x2
#define MPU6050_DETECT_DECREMENT_4 0x3
#define MPU6050_USERCTRL_DMP_EN_BIT 7
#define MPU6050_USERCTRL_FIFO_EN_BIT 6
#define MPU6050_USERCTRL_I2C_MST_EN_BIT 5
#define MPU6050_USERCTRL_I2C_IF_DIS_BIT 4
#define MPU6050_USERCTRL_DMP_RESET_BIT 3
#define MPU6050_USERCTRL_FIFO_RESET_BIT 2
#define MPU6050_USERCTRL_I2C_MST_RESET_BIT 1
#define MPU6050_USERCTRL_SIG_COND_RESET_BIT 0
#define MPU6050_PWR1_DEVICE_RESET_BIT 7
#define MPU6050_PWR1_SLEEP_BIT 6
#define MPU6050_PWR1_CYCLE_BIT 5
#define MPU6050_PWR1_TEMP_DIS_BIT 3
#define MPU6050_PWR1_CLKSEL_BIT 2
#define MPU6050_PWR1_CLKSEL_LENGTH 3
#define MPU6050_CLOCK_INTERNAL 0x00
#define MPU6050_CLOCK_PLL_XGYRO 0x01
#define MPU6050_CLOCK_PLL_YGYRO 0x02
#define MPU6050_CLOCK_PLL_ZGYRO 0x03
#define MPU6050_CLOCK_PLL_EXT32K 0x04
#define MPU6050_CLOCK_PLL_EXT19M 0x05
#define MPU6050_CLOCK_KEEP_RESET 0x07
#define MPU6050_PWR2_LP_WAKE_CTRL_BIT 7
#define MPU6050_PWR2_LP_WAKE_CTRL_LENGTH 2
#define MPU6050_PWR2_STBY_XA_BIT 5
#define MPU6050_PWR2_STBY_YA_BIT 4
#define MPU6050_PWR2_STBY_ZA_BIT 3
#define MPU6050_PWR2_STBY_XG_BIT 2
#define MPU6050_PWR2_STBY_YG_BIT 1
#define MPU6050_PWR2_STBY_ZG_BIT 0
#define MPU6050_WAKE_FREQ_1P25 0x0
#define MPU6050_WAKE_FREQ_2P5 0x1
#define MPU6050_WAKE_FREQ_5 0x2
#define MPU6050_WAKE_FREQ_10 0x3
#define MPU6050_BANKSEL_PRFTCH_EN_BIT 6
#define MPU6050_BANKSEL_CFG_USER_BANK_BIT 5
#define MPU6050_BANKSEL_MEM_SEL_BIT 4
#define MPU6050_BANKSEL_MEM_SEL_LENGTH 5
#define MPU6050_WHO_AM_I_BIT 6
#define MPU6050_WHO_AM_I_LENGTH 6
#define MPU6050_DMP_MEMORY_BANKS 8
#define MPU6050_DMP_MEMORY_BANK_SIZE 256
#define MPU6050_DMP_MEMORY_CHUNK_SIZE 16
// note: DMP code memory blocks defined at end of header file
class MPU6050 {
public:
MPU6050();
MPU6050(uint8_t address);
void initialize();
bool testConnection();
// Patch for Tasmota
void setAddr(uint8_t address);
// AUX_VDDIO register
uint8_t getAuxVDDIOLevel();
void setAuxVDDIOLevel(uint8_t level);
// SMPLRT_DIV register
uint8_t getRate();
void setRate(uint8_t rate);
// CONFIG register
uint8_t getExternalFrameSync();
void setExternalFrameSync(uint8_t sync);
uint8_t getDLPFMode();
void setDLPFMode(uint8_t bandwidth);
// GYRO_CONFIG register
uint8_t getFullScaleGyroRange();
void setFullScaleGyroRange(uint8_t range);
// ACCEL_CONFIG register
bool getAccelXSelfTest();
void setAccelXSelfTest(bool enabled);
bool getAccelYSelfTest();
void setAccelYSelfTest(bool enabled);
bool getAccelZSelfTest();
void setAccelZSelfTest(bool enabled);
uint8_t getFullScaleAccelRange();
void setFullScaleAccelRange(uint8_t range);
uint8_t getDHPFMode();
void setDHPFMode(uint8_t mode);
// FF_THR register
uint8_t getFreefallDetectionThreshold();
void setFreefallDetectionThreshold(uint8_t threshold);
// FF_DUR register
uint8_t getFreefallDetectionDuration();
void setFreefallDetectionDuration(uint8_t duration);
// MOT_THR register
uint8_t getMotionDetectionThreshold();
void setMotionDetectionThreshold(uint8_t threshold);
// MOT_DUR register
uint8_t getMotionDetectionDuration();
void setMotionDetectionDuration(uint8_t duration);
// ZRMOT_THR register
uint8_t getZeroMotionDetectionThreshold();
void setZeroMotionDetectionThreshold(uint8_t threshold);
// ZRMOT_DUR register
uint8_t getZeroMotionDetectionDuration();
void setZeroMotionDetectionDuration(uint8_t duration);
// FIFO_EN register
bool getTempFIFOEnabled();
void setTempFIFOEnabled(bool enabled);
bool getXGyroFIFOEnabled();
void setXGyroFIFOEnabled(bool enabled);
bool getYGyroFIFOEnabled();
void setYGyroFIFOEnabled(bool enabled);
bool getZGyroFIFOEnabled();
void setZGyroFIFOEnabled(bool enabled);
bool getAccelFIFOEnabled();
void setAccelFIFOEnabled(bool enabled);
bool getSlave2FIFOEnabled();
void setSlave2FIFOEnabled(bool enabled);
bool getSlave1FIFOEnabled();
void setSlave1FIFOEnabled(bool enabled);
bool getSlave0FIFOEnabled();
void setSlave0FIFOEnabled(bool enabled);
// I2C_MST_CTRL register
bool getMultiMasterEnabled();
void setMultiMasterEnabled(bool enabled);
bool getWaitForExternalSensorEnabled();
void setWaitForExternalSensorEnabled(bool enabled);
bool getSlave3FIFOEnabled();
void setSlave3FIFOEnabled(bool enabled);
bool getSlaveReadWriteTransitionEnabled();
void setSlaveReadWriteTransitionEnabled(bool enabled);
uint8_t getMasterClockSpeed();
void setMasterClockSpeed(uint8_t speed);
// I2C_SLV* registers (Slave 0-3)
uint8_t getSlaveAddress(uint8_t num);
void setSlaveAddress(uint8_t num, uint8_t address);
uint8_t getSlaveRegister(uint8_t num);
void setSlaveRegister(uint8_t num, uint8_t reg);
bool getSlaveEnabled(uint8_t num);
void setSlaveEnabled(uint8_t num, bool enabled);
bool getSlaveWordByteSwap(uint8_t num);
void setSlaveWordByteSwap(uint8_t num, bool enabled);
bool getSlaveWriteMode(uint8_t num);
void setSlaveWriteMode(uint8_t num, bool mode);
bool getSlaveWordGroupOffset(uint8_t num);
void setSlaveWordGroupOffset(uint8_t num, bool enabled);
uint8_t getSlaveDataLength(uint8_t num);
void setSlaveDataLength(uint8_t num, uint8_t length);
// I2C_SLV* registers (Slave 4)
uint8_t getSlave4Address();
void setSlave4Address(uint8_t address);
uint8_t getSlave4Register();
void setSlave4Register(uint8_t reg);
void setSlave4OutputByte(uint8_t data);
bool getSlave4Enabled();
void setSlave4Enabled(bool enabled);
bool getSlave4InterruptEnabled();
void setSlave4InterruptEnabled(bool enabled);
bool getSlave4WriteMode();
void setSlave4WriteMode(bool mode);
uint8_t getSlave4MasterDelay();
void setSlave4MasterDelay(uint8_t delay);
uint8_t getSlate4InputByte();
// I2C_MST_STATUS register
bool getPassthroughStatus();
bool getSlave4IsDone();
bool getLostArbitration();
bool getSlave4Nack();
bool getSlave3Nack();
bool getSlave2Nack();
bool getSlave1Nack();
bool getSlave0Nack();
// INT_PIN_CFG register
bool getInterruptMode();
void setInterruptMode(bool mode);
bool getInterruptDrive();
void setInterruptDrive(bool drive);
bool getInterruptLatch();
void setInterruptLatch(bool latch);
bool getInterruptLatchClear();
void setInterruptLatchClear(bool clear);
bool getFSyncInterruptLevel();
void setFSyncInterruptLevel(bool level);
bool getFSyncInterruptEnabled();
void setFSyncInterruptEnabled(bool enabled);
bool getI2CBypassEnabled();
void setI2CBypassEnabled(bool enabled);
bool getClockOutputEnabled();
void setClockOutputEnabled(bool enabled);
// INT_ENABLE register
uint8_t getIntEnabled();
void setIntEnabled(uint8_t enabled);
bool getIntFreefallEnabled();
void setIntFreefallEnabled(bool enabled);
bool getIntMotionEnabled();
void setIntMotionEnabled(bool enabled);
bool getIntZeroMotionEnabled();
void setIntZeroMotionEnabled(bool enabled);
bool getIntFIFOBufferOverflowEnabled();
void setIntFIFOBufferOverflowEnabled(bool enabled);
bool getIntI2CMasterEnabled();
void setIntI2CMasterEnabled(bool enabled);
bool getIntDataReadyEnabled();
void setIntDataReadyEnabled(bool enabled);
// INT_STATUS register
uint8_t getIntStatus();
bool getIntFreefallStatus();
bool getIntMotionStatus();
bool getIntZeroMotionStatus();
bool getIntFIFOBufferOverflowStatus();
bool getIntI2CMasterStatus();
bool getIntDataReadyStatus();
// ACCEL_*OUT_* registers
void getMotion9(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz, int16_t* mx, int16_t* my, int16_t* mz);
void getMotion6(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, int16_t* gy, int16_t* gz);
void getAcceleration(int16_t* x, int16_t* y, int16_t* z);
int16_t getAccelerationX();
int16_t getAccelerationY();
int16_t getAccelerationZ();
// TEMP_OUT_* registers
int16_t getTemperature();
// GYRO_*OUT_* registers
void getRotation(int16_t* x, int16_t* y, int16_t* z);
int16_t getRotationX();
int16_t getRotationY();
int16_t getRotationZ();
// EXT_SENS_DATA_* registers
uint8_t getExternalSensorByte(int position);
uint16_t getExternalSensorWord(int position);
uint32_t getExternalSensorDWord(int position);
// MOT_DETECT_STATUS register
bool getXNegMotionDetected();
bool getXPosMotionDetected();
bool getYNegMotionDetected();
bool getYPosMotionDetected();
bool getZNegMotionDetected();
bool getZPosMotionDetected();
bool getZeroMotionDetected();
// I2C_SLV*_DO register
void setSlaveOutputByte(uint8_t num, uint8_t data);
// I2C_MST_DELAY_CTRL register
bool getExternalShadowDelayEnabled();
void setExternalShadowDelayEnabled(bool enabled);
bool getSlaveDelayEnabled(uint8_t num);
void setSlaveDelayEnabled(uint8_t num, bool enabled);
// SIGNAL_PATH_RESET register
void resetGyroscopePath();
void resetAccelerometerPath();
void resetTemperaturePath();
// MOT_DETECT_CTRL register
uint8_t getAccelerometerPowerOnDelay();
void setAccelerometerPowerOnDelay(uint8_t delay);
uint8_t getFreefallDetectionCounterDecrement();
void setFreefallDetectionCounterDecrement(uint8_t decrement);
uint8_t getMotionDetectionCounterDecrement();
void setMotionDetectionCounterDecrement(uint8_t decrement);
// USER_CTRL register
bool getFIFOEnabled();
void setFIFOEnabled(bool enabled);
bool getI2CMasterModeEnabled();
void setI2CMasterModeEnabled(bool enabled);
void switchSPIEnabled(bool enabled);
void resetFIFO();
void resetI2CMaster();
void resetSensors();
// PWR_MGMT_1 register
void reset();
bool getSleepEnabled();
void setSleepEnabled(bool enabled);
bool getWakeCycleEnabled();
void setWakeCycleEnabled(bool enabled);
bool getTempSensorEnabled();
void setTempSensorEnabled(bool enabled);
uint8_t getClockSource();
void setClockSource(uint8_t source);
// PWR_MGMT_2 register
uint8_t getWakeFrequency();
void setWakeFrequency(uint8_t frequency);
bool getStandbyXAccelEnabled();
void setStandbyXAccelEnabled(bool enabled);
bool getStandbyYAccelEnabled();
void setStandbyYAccelEnabled(bool enabled);
bool getStandbyZAccelEnabled();
void setStandbyZAccelEnabled(bool enabled);
bool getStandbyXGyroEnabled();
void setStandbyXGyroEnabled(bool enabled);
bool getStandbyYGyroEnabled();
void setStandbyYGyroEnabled(bool enabled);
bool getStandbyZGyroEnabled();
void setStandbyZGyroEnabled(bool enabled);
// FIFO_COUNT_* registers
uint16_t getFIFOCount();
// FIFO_R_W register
uint8_t getFIFOByte();
void setFIFOByte(uint8_t data);
void getFIFOBytes(uint8_t *data, uint8_t length);
// WHO_AM_I register
uint8_t getDeviceID();
void setDeviceID(uint8_t id);
// ======== UNDOCUMENTED/DMP REGISTERS/METHODS ========
// XG_OFFS_TC register
uint8_t getOTPBankValid();
void setOTPBankValid(bool enabled);
int8_t getXGyroOffsetTC();
void setXGyroOffsetTC(int8_t offset);
// YG_OFFS_TC register
int8_t getYGyroOffsetTC();
void setYGyroOffsetTC(int8_t offset);
// ZG_OFFS_TC register
int8_t getZGyroOffsetTC();
void setZGyroOffsetTC(int8_t offset);
// X_FINE_GAIN register
int8_t getXFineGain();
void setXFineGain(int8_t gain);
// Y_FINE_GAIN register
int8_t getYFineGain();
void setYFineGain(int8_t gain);
// Z_FINE_GAIN register
int8_t getZFineGain();
void setZFineGain(int8_t gain);
// XA_OFFS_* registers
int16_t getXAccelOffset();
void setXAccelOffset(int16_t offset);
// YA_OFFS_* register
int16_t getYAccelOffset();
void setYAccelOffset(int16_t offset);
// ZA_OFFS_* register
int16_t getZAccelOffset();
void setZAccelOffset(int16_t offset);
// XG_OFFS_USR* registers
int16_t getXGyroOffset();
void setXGyroOffset(int16_t offset);
// YG_OFFS_USR* register
int16_t getYGyroOffset();
void setYGyroOffset(int16_t offset);
// ZG_OFFS_USR* register
int16_t getZGyroOffset();
void setZGyroOffset(int16_t offset);
// INT_ENABLE register (DMP functions)
bool getIntPLLReadyEnabled();
void setIntPLLReadyEnabled(bool enabled);
bool getIntDMPEnabled();
void setIntDMPEnabled(bool enabled);
// DMP_INT_STATUS
bool getDMPInt5Status();
bool getDMPInt4Status();
bool getDMPInt3Status();
bool getDMPInt2Status();
bool getDMPInt1Status();
bool getDMPInt0Status();
// INT_STATUS register (DMP functions)
bool getIntPLLReadyStatus();
bool getIntDMPStatus();
// USER_CTRL register (DMP functions)
bool getDMPEnabled();
void setDMPEnabled(bool enabled);
void resetDMP();
// BANK_SEL register
void setMemoryBank(uint8_t bank, bool prefetchEnabled=false, bool userBank=false);
// MEM_START_ADDR register
void setMemoryStartAddress(uint8_t address);
// MEM_R_W register
uint8_t readMemoryByte();
void writeMemoryByte(uint8_t data);
void readMemoryBlock(uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0);
bool writeMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true, bool useProgMem=false);
bool writeProgMemoryBlock(const uint8_t *data, uint16_t dataSize, uint8_t bank=0, uint8_t address=0, bool verify=true);
bool writeDMPConfigurationSet(const uint8_t *data, uint16_t dataSize, bool useProgMem=false);
bool writeProgDMPConfigurationSet(const uint8_t *data, uint16_t dataSize);
// DMP_CFG_1 register
uint8_t getDMPConfig1();
void setDMPConfig1(uint8_t config);
// DMP_CFG_2 register
uint8_t getDMPConfig2();
void setDMPConfig2(uint8_t config);
// special methods for MotionApps 2.0 implementation
#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS20
uint8_t *dmpPacketBuffer;
uint16_t dmpPacketSize;
uint8_t dmpInitialize();
bool dmpPacketAvailable();
uint8_t dmpSetFIFORate(uint8_t fifoRate);
uint8_t dmpGetFIFORate();
uint8_t dmpGetSampleStepSizeMS();
uint8_t dmpGetSampleFrequency();
int32_t dmpDecodeTemperature(int8_t tempReg);
// Register callbacks after a packet of FIFO data is processed
//uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
//uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
uint8_t dmpRunFIFORateProcesses();
// Setup FIFO for various output
uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
// Get Fixed Point data from FIFO
uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetEuler(float *data, Quaternion *q);
uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
// Get Floating Point data from FIFO
uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
uint8_t dmpInitFIFOParam();
uint8_t dmpCloseFIFO();
uint8_t dmpSetGyroDataSource(uint8_t source);
uint8_t dmpDecodeQuantizedAccel();
uint32_t dmpGetGyroSumOfSquare();
uint32_t dmpGetAccelSumOfSquare();
void dmpOverrideQuaternion(long *q);
uint16_t dmpGetFIFOPacketSize();
#endif
// special methods for MotionApps 4.1 implementation
#ifdef MPU6050_INCLUDE_DMP_MOTIONAPPS41
uint8_t *dmpPacketBuffer;
uint16_t dmpPacketSize;
uint8_t dmpInitialize();
bool dmpPacketAvailable();
uint8_t dmpSetFIFORate(uint8_t fifoRate);
uint8_t dmpGetFIFORate();
uint8_t dmpGetSampleStepSizeMS();
uint8_t dmpGetSampleFrequency();
int32_t dmpDecodeTemperature(int8_t tempReg);
// Register callbacks after a packet of FIFO data is processed
//uint8_t dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
//uint8_t dmpUnregisterFIFORateProcess(inv_obj_func func);
uint8_t dmpRunFIFORateProcesses();
// Setup FIFO for various output
uint8_t dmpSendQuaternion(uint_fast16_t accuracy);
uint8_t dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendPacketNumber(uint_fast16_t accuracy);
uint8_t dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
// Get Fixed Point data from FIFO
uint8_t dmpGetAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternion(Quaternion *q, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGet6AxisQuaternion(Quaternion *q, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetRelativeQuaternion(Quaternion *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyro(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetMag(int16_t *data, const uint8_t* packet=0);
uint8_t dmpSetLinearAccelFilterCoefficient(float coef);
uint8_t dmpGetLinearAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity);
uint8_t dmpGetLinearAccelInWorld(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q);
uint8_t dmpGetGyroAndAccelSensor(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroAndAccelSensor(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroAndAccelSensor(VectorInt16 *g, VectorInt16 *a, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGyroSensor(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetControlData(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetTemperature(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetGravity(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetGravity(VectorFloat *v, Quaternion *q);
uint8_t dmpGetUnquantizedAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetUnquantizedAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetUnquantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(int16_t *data, const uint8_t* packet=0);
uint8_t dmpGetQuantizedAccel(VectorInt16 *v, const uint8_t* packet=0);
uint8_t dmpGetExternalSensorData(int32_t *data, uint16_t size, const uint8_t* packet=0);
uint8_t dmpGetEIS(int32_t *data, const uint8_t* packet=0);
uint8_t dmpGetEuler(float *data, Quaternion *q);
uint8_t dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity);
// Get Floating Point data from FIFO
uint8_t dmpGetAccelFloat(float *data, const uint8_t* packet=0);
uint8_t dmpGetQuaternionFloat(float *data, const uint8_t* packet=0);
uint8_t dmpProcessFIFOPacket(const unsigned char *dmpData);
uint8_t dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed=NULL);
uint8_t dmpSetFIFOProcessedCallback(void (*func) (void));
uint8_t dmpInitFIFOParam();
uint8_t dmpCloseFIFO();
uint8_t dmpSetGyroDataSource(uint8_t source);
uint8_t dmpDecodeQuantizedAccel();
uint32_t dmpGetGyroSumOfSquare();
uint32_t dmpGetAccelSumOfSquare();
void dmpOverrideQuaternion(long *q);
uint16_t dmpGetFIFOPacketSize();
#endif
private:
uint8_t devAddr;
uint8_t buffer[14];
};
#endif /* _MPU6050_H_ */

View File

@ -0,0 +1,743 @@
// I2Cdev library collection - MPU6050 I2C device class, 6-axis MotionApps 2.0 implementation
// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
// 5/20/2013 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Adapted for Sonoff-Tasmota by Oliver Welter <contact@verbotene.zone> 02-04-2018
//
// Changelog:
// ... - ongoing debug release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#ifndef _MPU6050_6AXIS_MOTIONAPPS20_H_
#define _MPU6050_6AXIS_MOTIONAPPS20_H_
#include "I2Cdev.h"
#include "helper_3dmath.h"
// MotionApps 2.0 DMP implementation, built using the MPU-6050EVB evaluation board
#define MPU6050_INCLUDE_DMP_MOTIONAPPS20
#include "MPU6050.h"
// Tom Carpenter's conditional PROGMEM code
// http://forum.arduino.cc/index.php?topic=129407.0
#ifndef __arm__
#include <avr/pgmspace.h>
#else
// Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
#define F(x) x
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcat_P(dest, src) strcat((dest), (src))
#define strcmp_P(a, b) strcmp((a), (b))
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#endif
#endif
/* Source is from the InvenSense MotionApps v2 demo code. Original source is
* unavailable, unless you happen to be amazing as decompiling binary by
* hand (in which case, please contact me, and I'm totally serious).
*
* Also, I'd like to offer many, many thanks to Noah Zerkin for all of the
* DMP reverse-engineering he did to help make this bit of wizardry
* possible.
*/
// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size.
// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno)
// after moving string constants to flash memory storage using the F()
// compiler macro (Arduino IDE 1.0+ required).
//#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTF(x, y) Serial.print(x, y)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define DEBUG_PRINTLNF(x, y) Serial.println(x, y)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTF(x, y)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTLNF(x, y)
#endif
#define MPU6050_DMP_CODE_SIZE 1929 // dmpMemory[]
#define MPU6050_DMP_CONFIG_SIZE 192 // dmpConfig[]
#define MPU6050_DMP_UPDATES_SIZE 47 // dmpUpdates[]
/* ================================================================================================ *
| Default MotionApps v2.0 42-byte FIFO packet structure: |
| |
| [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] |
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
| |
| [GYRO Z][ ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] |
| 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
* ================================================================================================ */
// this block of memory gets written to the MPU on start-up, and it seems
// to be volatile memory, so it has to be done each time (it only takes ~1
// second though)
const unsigned char dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = {
// bank 0, 256 bytes
0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82,
0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC,
0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4,
0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10,
// bank 1, 256 bytes
0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8,
0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C,
0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C,
0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0,
// bank 2, 256 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// bank 3, 256 bytes
0xD8, 0xDC, 0xBA, 0xA2, 0xF1, 0xDE, 0xB2, 0xB8, 0xB4, 0xA8, 0x81, 0x91, 0xF7, 0x4A, 0x90, 0x7F,
0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA, 0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2,
0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80, 0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF,
0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0, 0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C,
0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1, 0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1,
0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3, 0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01,
0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88, 0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80,
0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF, 0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C,
0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89, 0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80,
0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9, 0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E,
0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A, 0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9,
0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11, 0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24,
0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55, 0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xAF, 0xF0,
0x00, 0x28, 0x50, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xD9, 0xFA, 0xA3, 0x86,
0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1,
0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86,
// bank 4, 256 bytes
0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA,
0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C,
0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8,
0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3,
0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84,
0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5,
0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3,
0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1,
0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5,
0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D,
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D,
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A,
0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8,
0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87,
// bank 5, 256 bytes
0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8,
0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68,
0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D,
0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94,
0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA,
0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56,
0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9,
0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA,
0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0xA8, 0x8A,
0x9A, 0xF5, 0x20, 0xAA, 0xDA, 0xDF, 0xD8, 0xA8, 0x40, 0xAA, 0xD0, 0xDA, 0xDE, 0xD8, 0xA8, 0x60,
0xAA, 0xDA, 0xD0, 0xDF, 0xD8, 0xF1, 0x97, 0x86, 0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97,
0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40, 0xB8, 0xB0, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04,
0x28, 0x51, 0x79, 0x1D, 0x30, 0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78,
0x78, 0x9B, 0xF1, 0x1A, 0xB0, 0xF0, 0x8A, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x8B, 0x29, 0x51, 0x79,
0x8A, 0x24, 0x70, 0x59, 0x8B, 0x20, 0x58, 0x71, 0x8A, 0x44, 0x69, 0x38, 0x8B, 0x39, 0x40, 0x68,
0x8A, 0x64, 0x48, 0x31, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71, 0x58, 0x44, 0x68,
// bank 6, 256 bytes
0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0, 0x8C, 0xA8, 0x04,
0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02, 0x26, 0x46, 0x66,
0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31,
0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19, 0x31, 0x48, 0x60,
0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86, 0xA8, 0x6E, 0x76,
0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A, 0x6E, 0x8A, 0x56,
0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E, 0x9D, 0xB8, 0xAD,
0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0x81, 0x91,
0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8,
0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51, 0xD9, 0x04, 0xAE,
0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19, 0x81, 0xAD, 0xD9,
0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9, 0xAD, 0xAD, 0xAD,
0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76, 0xF3, 0xAC, 0x2E,
0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC, 0x30, 0x18, 0xA8,
0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24, 0xF2, 0xB0, 0x89,
0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9, 0xD8, 0xD8, 0x79,
// bank 7, 138 bytes (remainder)
0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D, 0xD9, 0x28, 0xD8,
0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D, 0x80, 0x25, 0xDA,
0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34, 0x3C, 0xF3, 0xAB,
0x8B, 0xF8, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xFA, 0xB0, 0x87, 0x9C, 0xB9, 0xA3,
0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3, 0xA3,
0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3, 0xA3,
0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3, 0xDC,
0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF
};
// thanks to Noah Zerkin for piecing this stuff together!
const unsigned char dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = {
// BANK OFFSET LENGTH [DATA]
0x03, 0x7B, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration
0x03, 0xAB, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration
0x00, 0x68, 0x04, 0x02, 0xCB, 0x47, 0xA2, // D_0_104 inv_set_gyro_calibration
0x02, 0x18, 0x04, 0x00, 0x05, 0x8B, 0xC1, // D_0_24 inv_set_gyro_calibration
0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration
0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_accel_calibration
0x03, 0x89, 0x03, 0x26, 0x46, 0x66, // FCFG_7 inv_set_accel_calibration
0x00, 0x6C, 0x02, 0x20, 0x00, // D_0_108 inv_set_accel_calibration
0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration
0x02, 0x44, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_01
0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02
0x02, 0x4C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_10
0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11
0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12
0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20
0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21
0x02, 0xBC, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_22
0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel
0x03, 0x7F, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors
0x04, 0x02, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion
0x04, 0x09, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update
0x00, 0xA3, 0x01, 0x00, // D_0_163 inv_set_dead_zone
// SPECIAL 0x01 = enable interrupts
0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE at i=22, SPECIAL INSTRUCTION
0x07, 0x86, 0x01, 0xFE, // CFG_6 inv_set_fifo_interupt
0x07, 0x41, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion
0x07, 0x7E, 0x01, 0x30, // CFG_16 inv_set_footer
0x07, 0x46, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro
0x07, 0x47, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo
0x07, 0x6C, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo
0x02, 0x16, 0x02, 0x00, 0x02 //(0x07 -> 16Mhz) D_0_22 inv_set_fifo_rate (0x06 for first 8mhz board) (0x09 for 8Mhz board from Binoy)
// This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
// 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
// DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))
// It is important to make sure the host processor can keep up with reading and processing
// the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.
};
const unsigned char dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = {
0x01, 0xB2, 0x02, 0xFF, 0xFF,
0x01, 0x90, 0x04, 0x09, 0x23, 0xA1, 0x35,
0x01, 0x6A, 0x02, 0x06, 0x00,
0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00,
0x01, 0x62, 0x02, 0x00, 0x00,
0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00
};
uint8_t MPU6050::dmpInitialize() {
// reset device
DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
reset();
delay(30); // wait after reset
// enable sleep mode and wake cycle
/*Serial.println(F("Enabling sleep mode..."));
setSleepEnabled(true);
Serial.println(F("Enabling wake cycle..."));
setWakeCycleEnabled(true);*/
// disable sleep mode
DEBUG_PRINTLN(F("Disabling sleep mode..."));
setSleepEnabled(false);
// get MPU hardware revision
DEBUG_PRINTLN(F("Selecting user bank 16..."));
setMemoryBank(0x10, true, true);
DEBUG_PRINTLN(F("Selecting memory byte 6..."));
setMemoryStartAddress(0x06);
DEBUG_PRINTLN(F("Checking hardware revision..."));
uint8_t hwRevision = readMemoryByte();
DEBUG_PRINT(F("Revision @ user[16][6] = "));
DEBUG_PRINTLNF(hwRevision, HEX);
DEBUG_PRINTLN(F("Resetting memory bank selection to 0..."));
setMemoryBank(0, false, false);
// check OTP bank valid
DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
uint8_t otpValid = getOTPBankValid();
DEBUG_PRINT(F("OTP bank is "));
DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!"));
// get X/Y/Z gyro offsets
DEBUG_PRINTLN(F("Reading gyro offset TC values..."));
int8_t xgOffsetTC = getXGyroOffsetTC();
int8_t ygOffsetTC = getYGyroOffsetTC();
int8_t zgOffsetTC = getZGyroOffsetTC();
DEBUG_PRINT(F("X gyro offset = "));
DEBUG_PRINTLN(xgOffset);
DEBUG_PRINT(F("Y gyro offset = "));
DEBUG_PRINTLN(ygOffset);
DEBUG_PRINT(F("Z gyro offset = "));
DEBUG_PRINTLN(zgOffset);
// setup weird slave stuff (?)
DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F..."));
setSlaveAddress(0, 0x7F);
DEBUG_PRINTLN(F("Disabling I2C Master mode..."));
setI2CMasterModeEnabled(false);
DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)..."));
setSlaveAddress(0, 0x68);
DEBUG_PRINTLN(F("Resetting I2C Master control..."));
resetI2CMaster();
delay(20);
// load DMP code into memory banks
DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
DEBUG_PRINTLN(F(" bytes)"));
if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) {
DEBUG_PRINTLN(F("Success! DMP code written and verified."));
// write DMP configuration
DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE);
DEBUG_PRINTLN(F(" bytes in config def)"));
if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) {
DEBUG_PRINTLN(F("Success! DMP configuration written and verified."));
DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
setClockSource(MPU6050_CLOCK_PLL_ZGYRO);
DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
setIntEnabled(0x12);
DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
setRate(4); // 1khz / (1 + 4) = 200 Hz
DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);
DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
setDLPFMode(MPU6050_DLPF_BW_42);
DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)..."));
setDMPConfig1(0x03);
setDMPConfig2(0x00);
DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
setOTPBankValid(false);
DEBUG_PRINTLN(F("Setting X/Y/Z gyro offset TCs to previous values..."));
setXGyroOffsetTC(xgOffsetTC);
setYGyroOffsetTC(ygOffsetTC);
setZGyroOffsetTC(zgOffsetTC);
//DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero..."));
//setXGyroOffset(0);
//setYGyroOffset(0);
//setZGyroOffset(0);
DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)..."));
uint8_t dmpUpdate[16], j;
uint16_t pos = 0;
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Resetting FIFO..."));
resetFIFO();
DEBUG_PRINTLN(F("Reading FIFO count..."));
uint16_t fifoCount = getFIFOCount();
uint8_t fifoBuffer[128];
DEBUG_PRINT(F("Current FIFO count="));
DEBUG_PRINTLN(fifoCount);
getFIFOBytes(fifoBuffer, fifoCount);
DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
setMotionDetectionThreshold(2);
DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
setZeroMotionDetectionThreshold(156);
DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
setMotionDetectionDuration(80);
DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
setZeroMotionDetectionDuration(0);
DEBUG_PRINTLN(F("Resetting FIFO..."));
resetFIFO();
DEBUG_PRINTLN(F("Enabling FIFO..."));
setFIFOEnabled(true);
DEBUG_PRINTLN(F("Enabling DMP..."));
setDMPEnabled(true);
DEBUG_PRINTLN(F("Resetting DMP..."));
resetDMP();
DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
while ((fifoCount = getFIFOCount()) < 3);
DEBUG_PRINT(F("Current FIFO count="));
DEBUG_PRINTLN(fifoCount);
DEBUG_PRINTLN(F("Reading FIFO data..."));
getFIFOBytes(fifoBuffer, fifoCount);
DEBUG_PRINTLN(F("Reading interrupt status..."));
uint8_t mpuIntStatus = getIntStatus();
DEBUG_PRINT(F("Current interrupt status="));
DEBUG_PRINTLNF(mpuIntStatus, HEX);
DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
while ((fifoCount = getFIFOCount()) < 3);
DEBUG_PRINT(F("Current FIFO count="));
DEBUG_PRINTLN(fifoCount);
DEBUG_PRINTLN(F("Reading FIFO data..."));
getFIFOBytes(fifoBuffer, fifoCount);
DEBUG_PRINTLN(F("Reading interrupt status..."));
mpuIntStatus = getIntStatus();
DEBUG_PRINT(F("Current interrupt status="));
DEBUG_PRINTLNF(mpuIntStatus, HEX);
DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("DMP is good to go! Finally."));
DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
setDMPEnabled(false);
DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer..."));
dmpPacketSize = 42;
/*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) {
return 3; // TODO: proper error code for no memory
}*/
DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
resetFIFO();
getIntStatus();
} else {
DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed."));
return 2; // configuration block loading failed
}
} else {
DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
return 1; // main binary block loading failed
}
return 0; // success
}
bool MPU6050::dmpPacketAvailable() {
return getFIFOCount() >= dmpGetFIFOPacketSize();
}
// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate);
// uint8_t MPU6050::dmpGetFIFORate();
// uint8_t MPU6050::dmpGetSampleStepSizeMS();
// uint8_t MPU6050::dmpGetSampleFrequency();
// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg);
//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func);
//uint8_t MPU6050::dmpRunFIFORateProcesses();
// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[28] << 24) + (packet[29] << 16) + (packet[30] << 8) + packet[31]);
data[1] = ((packet[32] << 24) + (packet[33] << 16) + (packet[34] << 8) + packet[35]);
data[2] = ((packet[36] << 24) + (packet[37] << 16) + (packet[38] << 8) + packet[39]);
return 0;
}
uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[28] << 8) + packet[29];
data[1] = (packet[32] << 8) + packet[33];
data[2] = (packet[36] << 8) + packet[37];
return 0;
}
uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
v -> x = (packet[28] << 8) + packet[29];
v -> y = (packet[32] << 8) + packet[33];
v -> z = (packet[36] << 8) + packet[37];
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]);
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]);
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]);
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]);
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[0] << 8) + packet[1]);
data[1] = ((packet[4] << 8) + packet[5]);
data[2] = ((packet[8] << 8) + packet[9]);
data[3] = ((packet[12] << 8) + packet[13]);
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
int16_t qI[4];
uint8_t status = dmpGetQuaternion(qI, packet);
if (status == 0) {
q -> w = (float)qI[0] / 16384.0f;
q -> x = (float)qI[1] / 16384.0f;
q -> y = (float)qI[2] / 16384.0f;
q -> z = (float)qI[3] / 16384.0f;
return 0;
}
return status; // int16 return value, indicates error if this line is reached
}
// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]);
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]);
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]);
return 0;
}
uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[16] << 8) + packet[17];
data[1] = (packet[20] << 8) + packet[21];
data[2] = (packet[24] << 8) + packet[25];
return 0;
}
// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef);
// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
// get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g)
v -> x = vRaw -> x - gravity -> x*8192;
v -> y = vRaw -> y - gravity -> y*8192;
v -> z = vRaw -> z - gravity -> z*8192;
return 0;
}
// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
// rotate measured 3D acceleration vector into original state
// frame of reference based on orientation quaternion
memcpy(v, vReal, sizeof(VectorInt16));
v -> rotate(q);
return 0;
}
// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
return 0;
}
// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet);
// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi
data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta
data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi
return 0;
}
uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
// yaw: (about Z axis)
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
// pitch: (nose up/down, about Y axis)
data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
// roll: (tilt left/right, about X axis)
data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
return 0;
}
// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet);
uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) {
/*for (uint8_t k = 0; k < dmpPacketSize; k++) {
if (dmpData[k] < 0x10) Serial.print("0");
Serial.print(dmpData[k], HEX);
Serial.print(" ");
}
Serial.print("\n");*/
//Serial.println((uint16_t)dmpPacketBuffer);
return 0;
}
uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) {
uint8_t status;
uint8_t buf[dmpPacketSize];
for (uint8_t i = 0; i < numPackets; i++) {
// read packet from FIFO
getFIFOBytes(buf, dmpPacketSize);
// process packet
if ((status = dmpProcessFIFOPacket(buf)) > 0) return status;
// increment external process count variable, if supplied
if (processed != 0) *processed++;
}
return 0;
}
// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void));
// uint8_t MPU6050::dmpInitFIFOParam();
// uint8_t MPU6050::dmpCloseFIFO();
// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source);
// uint8_t MPU6050::dmpDecodeQuantizedAccel();
// uint32_t MPU6050::dmpGetGyroSumOfSquare();
// uint32_t MPU6050::dmpGetAccelSumOfSquare();
// void MPU6050::dmpOverrideQuaternion(long *q);
uint16_t MPU6050::dmpGetFIFOPacketSize() {
return dmpPacketSize;
}
#endif /* _MPU6050_6AXIS_MOTIONAPPS20_H_ */

View File

@ -0,0 +1,854 @@
// I2Cdev library collection - MPU6050 I2C device class, 9-axis MotionApps 4.1 implementation
// Based on InvenSense MPU-6050 register map document rev. 2.0, 5/19/2011 (RM-MPU-6000A-00)
// 6/18/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Adapted for Sonoff-Tasmota by Oliver Welter <contact@verbotene.zone> 02-04-2018
//
// Changelog:
// ... - ongoing debug release
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#ifndef _MPU6050_9AXIS_MOTIONAPPS41_H_
#define _MPU6050_9AXIS_MOTIONAPPS41_H_
#include "I2Cdev.h"
#include "helper_3dmath.h"
// MotionApps 4.1 DMP implementation, built using the MPU-9150 "MotionFit" board
#define MPU6050_INCLUDE_DMP_MOTIONAPPS41
#include "MPU6050.h"
// Tom Carpenter's conditional PROGMEM code
// http://forum.arduino.cc/index.php?topic=129407.0
#ifndef __arm__
#include <avr/pgmspace.h>
#else
// Teensy 3.0 library conditional PROGMEM code from Paul Stoffregen
#ifndef __PGMSPACE_H_
#define __PGMSPACE_H_ 1
#include <inttypes.h>
#define PROGMEM
#define PGM_P const char *
#define PSTR(str) (str)
#define F(x) x
typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;
#define strcpy_P(dest, src) strcpy((dest), (src))
#define strcat_P(dest, src) strcat((dest), (src))
#define strcmp_P(a, b) strcmp((a), (b))
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#define pgm_read_float(addr) (*(const float *)(addr))
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
#define pgm_read_word_near(addr) pgm_read_word(addr)
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
#define pgm_read_float_near(addr) pgm_read_float(addr)
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
#define pgm_read_word_far(addr) pgm_read_word(addr)
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
#define pgm_read_float_far(addr) pgm_read_float(addr)
#endif
#endif
// NOTE! Enabling DEBUG adds about 3.3kB to the flash program size.
// Debug output is now working even on ATMega328P MCUs (e.g. Arduino Uno)
// after moving string constants to flash memory storage using the F()
// compiler macro (Arduino IDE 1.0+ required).
//#define DEBUG
#ifdef DEBUG
#define DEBUG_PRINT(x) Serial.print(x)
#define DEBUG_PRINTF(x, y) Serial.print(x, y)
#define DEBUG_PRINTLN(x) Serial.println(x)
#define DEBUG_PRINTLNF(x, y) Serial.println(x, y)
#else
#define DEBUG_PRINT(x)
#define DEBUG_PRINTF(x, y)
#define DEBUG_PRINTLN(x)
#define DEBUG_PRINTLNF(x, y)
#endif
#define MPU6050_DMP_CODE_SIZE 1962 // dmpMemory[]
#define MPU6050_DMP_CONFIG_SIZE 232 // dmpConfig[]
#define MPU6050_DMP_UPDATES_SIZE 140 // dmpUpdates[]
/* ================================================================================================ *
| Default MotionApps v4.1 48-byte FIFO packet structure: |
| |
| [QUAT W][ ][QUAT X][ ][QUAT Y][ ][QUAT Z][ ][GYRO X][ ][GYRO Y][ ] |
| 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
| |
| [GYRO Z][ ][MAG X ][MAG Y ][MAG Z ][ACC X ][ ][ACC Y ][ ][ACC Z ][ ][ ] |
| 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
* ================================================================================================ */
// this block of memory gets written to the MPU on start-up, and it seems
// to be volatile memory, so it has to be done each time (it only takes ~1
// second though)
const prog_uchar dmpMemory[MPU6050_DMP_CODE_SIZE] PROGMEM = {
// bank 0, 256 bytes
0xFB, 0x00, 0x00, 0x3E, 0x00, 0x0B, 0x00, 0x36, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0xFA, 0x80, 0x00, 0x0B, 0x12, 0x82, 0x00, 0x01,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x28, 0x00, 0x00, 0xFF, 0xFF, 0x45, 0x81, 0xFF, 0xFF, 0xFA, 0x72, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xE8, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7F, 0xFF, 0xFF, 0xFE, 0x80, 0x01,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3E, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xCA, 0xE3, 0x09, 0x3E, 0x80, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
0x41, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x2A, 0x00, 0x00, 0x16, 0x55, 0x00, 0x00, 0x21, 0x82,
0xFD, 0x87, 0x26, 0x50, 0xFD, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x6F, 0x00, 0x02, 0x65, 0x32, 0x00, 0x00, 0x5E, 0xC0,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFB, 0x8C, 0x6F, 0x5D, 0xFD, 0x5D, 0x08, 0xD9, 0x00, 0x7C, 0x73, 0x3B, 0x00, 0x6C, 0x12, 0xCC,
0x32, 0x00, 0x13, 0x9D, 0x32, 0x00, 0xD0, 0xD6, 0x32, 0x00, 0x08, 0x00, 0x40, 0x00, 0x01, 0xF4,
0xFF, 0xE6, 0x80, 0x79, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xD6, 0x00, 0x00, 0x27, 0x10,
// bank 1, 256 bytes
0xFB, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFA, 0x36, 0xFF, 0xBC, 0x30, 0x8E, 0x00, 0x05, 0xFB, 0xF0, 0xFF, 0xD9, 0x5B, 0xC8,
0xFF, 0xD0, 0x9A, 0xBE, 0x00, 0x00, 0x10, 0xA9, 0xFF, 0xF4, 0x1E, 0xB2, 0x00, 0xCE, 0xBB, 0xF7,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x0C,
0xFF, 0xC2, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0xCF, 0x80, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x3F, 0x68, 0xB6, 0x79, 0x35, 0x28, 0xBC, 0xC6, 0x7E, 0xD1, 0x6C,
0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0x6A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x30,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x25, 0x4D, 0x00, 0x2F, 0x70, 0x6D, 0x00, 0x00, 0x05, 0xAE, 0x00, 0x0C, 0x02, 0xD0,
// bank 2, 256 bytes
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x54, 0xFF, 0xEF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0xFF, 0xEF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x00, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x78, 0xA2,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// bank 3, 256 bytes
0xD8, 0xDC, 0xF4, 0xD8, 0xB9, 0xAB, 0xF3, 0xF8, 0xFA, 0xF1, 0xBA, 0xA2, 0xDE, 0xB2, 0xB8, 0xB4,
0xA8, 0x81, 0x98, 0xF7, 0x4A, 0x90, 0x7F, 0x91, 0x6A, 0xF3, 0xF9, 0xDB, 0xA8, 0xF9, 0xB0, 0xBA,
0xA0, 0x80, 0xF2, 0xCE, 0x81, 0xF3, 0xC2, 0xF1, 0xC1, 0xF2, 0xC3, 0xF3, 0xCC, 0xA2, 0xB2, 0x80,
0xF1, 0xC6, 0xD8, 0x80, 0xBA, 0xA7, 0xDF, 0xDF, 0xDF, 0xF2, 0xA7, 0xC3, 0xCB, 0xC5, 0xB6, 0xF0,
0x87, 0xA2, 0x94, 0x24, 0x48, 0x70, 0x3C, 0x95, 0x40, 0x68, 0x34, 0x58, 0x9B, 0x78, 0xA2, 0xF1,
0x83, 0x92, 0x2D, 0x55, 0x7D, 0xD8, 0xB1, 0xB4, 0xB8, 0xA1, 0xD0, 0x91, 0x80, 0xF2, 0x70, 0xF3,
0x70, 0xF2, 0x7C, 0x80, 0xA8, 0xF1, 0x01, 0xB0, 0x98, 0x87, 0xD9, 0x43, 0xD8, 0x86, 0xC9, 0x88,
0xBA, 0xA1, 0xF2, 0x0E, 0xB8, 0x97, 0x80, 0xF1, 0xA9, 0xDF, 0xDF, 0xDF, 0xAA, 0xDF, 0xDF, 0xDF,
0xF2, 0xAA, 0xC5, 0xCD, 0xC7, 0xA9, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, 0x97, 0xF1, 0xA9, 0x89,
0x26, 0x46, 0x66, 0xB0, 0xB4, 0xBA, 0x80, 0xAC, 0xDE, 0xF2, 0xCA, 0xF1, 0xB2, 0x8C, 0x02, 0xA9,
0xB6, 0x98, 0x00, 0x89, 0x0E, 0x16, 0x1E, 0xB8, 0xA9, 0xB4, 0x99, 0x2C, 0x54, 0x7C, 0xB0, 0x8A,
0xA8, 0x96, 0x36, 0x56, 0x76, 0xF1, 0xB9, 0xAF, 0xB4, 0xB0, 0x83, 0xC0, 0xB8, 0xA8, 0x97, 0x11,
0xB1, 0x8F, 0x98, 0xB9, 0xAF, 0xF0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xF1, 0xA3, 0x29, 0x55,
0x7D, 0xAF, 0x83, 0xB5, 0x93, 0xF0, 0x00, 0x28, 0x50, 0xF5, 0xBA, 0xAD, 0x8F, 0x9F, 0x28, 0x54,
0x7C, 0xB9, 0xF1, 0xA3, 0x86, 0x9F, 0x61, 0xA6, 0xDA, 0xDE, 0xDF, 0xDB, 0xB2, 0xB6, 0x8E, 0x9D,
0xAE, 0xF5, 0x60, 0x68, 0x70, 0xB1, 0xB5, 0xF1, 0xDA, 0xA6, 0xDF, 0xD9, 0xA6, 0xFA, 0xA3, 0x86,
// bank 4, 256 bytes
0x96, 0xDB, 0x31, 0xA6, 0xD9, 0xF8, 0xDF, 0xBA, 0xA6, 0x8F, 0xC2, 0xC5, 0xC7, 0xB2, 0x8C, 0xC1,
0xB8, 0xA2, 0xDF, 0xDF, 0xDF, 0xA3, 0xDF, 0xDF, 0xDF, 0xD8, 0xD8, 0xF1, 0xB8, 0xA8, 0xB2, 0x86,
0xB4, 0x98, 0x0D, 0x35, 0x5D, 0xB8, 0xAA, 0x98, 0xB0, 0x87, 0x2D, 0x35, 0x3D, 0xB2, 0xB6, 0xBA,
0xAF, 0x8C, 0x96, 0x19, 0x8F, 0x9F, 0xA7, 0x0E, 0x16, 0x1E, 0xB4, 0x9A, 0xB8, 0xAA, 0x87, 0x2C,
0x54, 0x7C, 0xB9, 0xA3, 0xDE, 0xDF, 0xDF, 0xA3, 0xB1, 0x80, 0xF2, 0xC4, 0xCD, 0xC9, 0xF1, 0xB8,
0xA9, 0xB4, 0x99, 0x83, 0x0D, 0x35, 0x5D, 0x89, 0xB9, 0xA3, 0x2D, 0x55, 0x7D, 0xB5, 0x93, 0xA3,
0x0E, 0x16, 0x1E, 0xA9, 0x2C, 0x54, 0x7C, 0xB8, 0xB4, 0xB0, 0xF1, 0x97, 0x83, 0xA8, 0x11, 0x84,
0xA5, 0x09, 0x98, 0xA3, 0x83, 0xF0, 0xDA, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xD8, 0xF1, 0xA5,
0x29, 0x55, 0x7D, 0xA5, 0x85, 0x95, 0x02, 0x1A, 0x2E, 0x3A, 0x56, 0x5A, 0x40, 0x48, 0xF9, 0xF3,
0xA3, 0xD9, 0xF8, 0xF0, 0x98, 0x83, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0x97, 0x82, 0xA8, 0xF1,
0x11, 0xF0, 0x98, 0xA2, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xDA, 0xF3, 0xDE, 0xD8, 0x83, 0xA5,
0x94, 0x01, 0xD9, 0xA3, 0x02, 0xF1, 0xA2, 0xC3, 0xC5, 0xC7, 0xD8, 0xF1, 0x84, 0x92, 0xA2, 0x4D,
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0x93, 0xA3, 0x4D,
0xDA, 0x2A, 0xD8, 0x48, 0x69, 0xD9, 0x2A, 0xD8, 0x68, 0x55, 0xDA, 0x32, 0xD8, 0x50, 0x71, 0xD9,
0x32, 0xD8, 0x70, 0x5D, 0xDA, 0x3A, 0xD8, 0x58, 0x79, 0xD9, 0x3A, 0xD8, 0x78, 0xA8, 0x8A, 0x9A,
// bank 5, 256 bytes
0xF0, 0x28, 0x50, 0x78, 0x9E, 0xF3, 0x88, 0x18, 0xF1, 0x9F, 0x1D, 0x98, 0xA8, 0xD9, 0x08, 0xD8,
0xC8, 0x9F, 0x12, 0x9E, 0xF3, 0x15, 0xA8, 0xDA, 0x12, 0x10, 0xD8, 0xF1, 0xAF, 0xC8, 0x97, 0x87,
0x34, 0xB5, 0xB9, 0x94, 0xA4, 0x21, 0xF3, 0xD9, 0x22, 0xD8, 0xF2, 0x2D, 0xF3, 0xD9, 0x2A, 0xD8,
0xF2, 0x35, 0xF3, 0xD9, 0x32, 0xD8, 0x81, 0xA4, 0x60, 0x60, 0x61, 0xD9, 0x61, 0xD8, 0x6C, 0x68,
0x69, 0xD9, 0x69, 0xD8, 0x74, 0x70, 0x71, 0xD9, 0x71, 0xD8, 0xB1, 0xA3, 0x84, 0x19, 0x3D, 0x5D,
0xA3, 0x83, 0x1A, 0x3E, 0x5E, 0x93, 0x10, 0x30, 0x81, 0x10, 0x11, 0xB8, 0xB0, 0xAF, 0x8F, 0x94,
0xF2, 0xDA, 0x3E, 0xD8, 0xB4, 0x9A, 0xA8, 0x87, 0x29, 0xDA, 0xF8, 0xD8, 0x87, 0x9A, 0x35, 0xDA,
0xF8, 0xD8, 0x87, 0x9A, 0x3D, 0xDA, 0xF8, 0xD8, 0xB1, 0xB9, 0xA4, 0x98, 0x85, 0x02, 0x2E, 0x56,
0xA5, 0x81, 0x00, 0x0C, 0x14, 0xA3, 0x97, 0xB0, 0x8A, 0xF1, 0x2D, 0xD9, 0x28, 0xD8, 0x4D, 0xD9,
0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x84, 0x0D, 0xDA, 0x0E, 0xD8, 0xA3, 0x29, 0x83, 0xDA,
0x2C, 0x0E, 0xD8, 0xA3, 0x84, 0x49, 0x83, 0xDA, 0x2C, 0x4C, 0x0E, 0xD8, 0xB8, 0xB0, 0x97, 0x86,
0xA8, 0x31, 0x9B, 0x06, 0x99, 0x07, 0xAB, 0x97, 0x28, 0x88, 0x9B, 0xF0, 0x0C, 0x20, 0x14, 0x40,
0xB9, 0xA3, 0x8A, 0xC3, 0xC5, 0xC7, 0x9A, 0xA3, 0x28, 0x50, 0x78, 0xF1, 0xB5, 0x93, 0x01, 0xD9,
0xDF, 0xDF, 0xDF, 0xD8, 0xB8, 0xB4, 0xA8, 0x8C, 0x9C, 0xF0, 0x04, 0x28, 0x51, 0x79, 0x1D, 0x30,
0x14, 0x38, 0xB2, 0x82, 0xAB, 0xD0, 0x98, 0x2C, 0x50, 0x50, 0x78, 0x78, 0x9B, 0xF1, 0x1A, 0xB0,
0xF0, 0xB1, 0x83, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0xB0, 0x8B, 0x29, 0x51, 0x79, 0xB1, 0x83, 0x24,
// bank 6, 256 bytes
0x70, 0x59, 0xB0, 0x8B, 0x20, 0x58, 0x71, 0xB1, 0x83, 0x44, 0x69, 0x38, 0xB0, 0x8B, 0x39, 0x40,
0x68, 0xB1, 0x83, 0x64, 0x48, 0x31, 0xB0, 0x8B, 0x30, 0x49, 0x60, 0xA5, 0x88, 0x20, 0x09, 0x71,
0x58, 0x44, 0x68, 0x11, 0x39, 0x64, 0x49, 0x30, 0x19, 0xF1, 0xAC, 0x00, 0x2C, 0x54, 0x7C, 0xF0,
0x8C, 0xA8, 0x04, 0x28, 0x50, 0x78, 0xF1, 0x88, 0x97, 0x26, 0xA8, 0x59, 0x98, 0xAC, 0x8C, 0x02,
0x26, 0x46, 0x66, 0xF0, 0x89, 0x9C, 0xA8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38,
0x64, 0x48, 0x31, 0xA9, 0x88, 0x09, 0x20, 0x59, 0x70, 0xAB, 0x11, 0x38, 0x40, 0x69, 0xA8, 0x19,
0x31, 0x48, 0x60, 0x8C, 0xA8, 0x3C, 0x41, 0x5C, 0x20, 0x7C, 0x00, 0xF1, 0x87, 0x98, 0x19, 0x86,
0xA8, 0x6E, 0x76, 0x7E, 0xA9, 0x99, 0x88, 0x2D, 0x55, 0x7D, 0x9E, 0xB9, 0xA3, 0x8A, 0x22, 0x8A,
0x6E, 0x8A, 0x56, 0x8A, 0x5E, 0x9F, 0xB1, 0x83, 0x06, 0x26, 0x46, 0x66, 0x0E, 0x2E, 0x4E, 0x6E,
0x9D, 0xB8, 0xAD, 0x00, 0x2C, 0x54, 0x7C, 0xF2, 0xB1, 0x8C, 0xB4, 0x99, 0xB9, 0xA3, 0x2D, 0x55,
0x7D, 0x81, 0x91, 0xAC, 0x38, 0xAD, 0x3A, 0xB5, 0x83, 0x91, 0xAC, 0x2D, 0xD9, 0x28, 0xD8, 0x4D,
0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0x8C, 0x9D, 0xAE, 0x29, 0xD9, 0x04, 0xAE, 0xD8, 0x51,
0xD9, 0x04, 0xAE, 0xD8, 0x79, 0xD9, 0x04, 0xD8, 0x81, 0xF3, 0x9D, 0xAD, 0x00, 0x8D, 0xAE, 0x19,
0x81, 0xAD, 0xD9, 0x01, 0xD8, 0xF2, 0xAE, 0xDA, 0x26, 0xD8, 0x8E, 0x91, 0x29, 0x83, 0xA7, 0xD9,
0xAD, 0xAD, 0xAD, 0xAD, 0xF3, 0x2A, 0xD8, 0xD8, 0xF1, 0xB0, 0xAC, 0x89, 0x91, 0x3E, 0x5E, 0x76,
0xF3, 0xAC, 0x2E, 0x2E, 0xF1, 0xB1, 0x8C, 0x5A, 0x9C, 0xAC, 0x2C, 0x28, 0x28, 0x28, 0x9C, 0xAC,
// bank 7, 170 bytes (remainder)
0x30, 0x18, 0xA8, 0x98, 0x81, 0x28, 0x34, 0x3C, 0x97, 0x24, 0xA7, 0x28, 0x34, 0x3C, 0x9C, 0x24,
0xF2, 0xB0, 0x89, 0xAC, 0x91, 0x2C, 0x4C, 0x6C, 0x8A, 0x9B, 0x2D, 0xD9, 0xD8, 0xD8, 0x51, 0xD9,
0xD8, 0xD8, 0x79, 0xD9, 0xD8, 0xD8, 0xF1, 0x9E, 0x88, 0xA3, 0x31, 0xDA, 0xD8, 0xD8, 0x91, 0x2D,
0xD9, 0x28, 0xD8, 0x4D, 0xD9, 0x48, 0xD8, 0x6D, 0xD9, 0x68, 0xD8, 0xB1, 0x83, 0x93, 0x35, 0x3D,
0x80, 0x25, 0xDA, 0xD8, 0xD8, 0x85, 0x69, 0xDA, 0xD8, 0xD8, 0xB4, 0x93, 0x81, 0xA3, 0x28, 0x34,
0x3C, 0xF3, 0xAB, 0x8B, 0xA3, 0x91, 0xB6, 0x09, 0xB4, 0xD9, 0xAB, 0xDE, 0xB0, 0x87, 0x9C, 0xB9,
0xA3, 0xDD, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x95, 0xF1, 0xA3, 0xA3, 0xA3, 0x9D, 0xF1, 0xA3, 0xA3,
0xA3, 0xA3, 0xF2, 0xA3, 0xB4, 0x90, 0x80, 0xF2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3,
0xA3, 0xA3, 0xB2, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xB0, 0x87, 0xB5, 0x99, 0xF1, 0xA3, 0xA3,
0xA3, 0x98, 0xF1, 0xA3, 0xA3, 0xA3, 0xA3, 0x97, 0xA3, 0xA3, 0xA3, 0xA3, 0xF3, 0x9B, 0xA3, 0xA3,
0xDC, 0xB9, 0xA7, 0xF1, 0x26, 0x26, 0x26, 0xD8, 0xD8, 0xFF
};
const prog_uchar dmpConfig[MPU6050_DMP_CONFIG_SIZE] PROGMEM = {
// BANK OFFSET LENGTH [DATA]
0x02, 0xEC, 0x04, 0x00, 0x47, 0x7D, 0x1A, // ?
0x03, 0x82, 0x03, 0x4C, 0xCD, 0x6C, // FCFG_1 inv_set_gyro_calibration
0x03, 0xB2, 0x03, 0x36, 0x56, 0x76, // FCFG_3 inv_set_gyro_calibration
0x00, 0x68, 0x04, 0x02, 0xCA, 0xE3, 0x09, // D_0_104 inv_set_gyro_calibration
0x01, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // D_1_152 inv_set_accel_calibration
0x03, 0x86, 0x03, 0x0C, 0xC9, 0x2C, // FCFG_2 inv_set_accel_calibration
0x03, 0x90, 0x03, 0x26, 0x46, 0x66, // (continued)...FCFG_2 inv_set_accel_calibration
0x00, 0x6C, 0x02, 0x40, 0x00, // D_0_108 inv_set_accel_calibration
0x02, 0x40, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_00 inv_set_compass_calibration
0x02, 0x44, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_01
0x02, 0x48, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_02
0x02, 0x4C, 0x04, 0x40, 0x00, 0x00, 0x00, // CPASS_MTX_10
0x02, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_11
0x02, 0x54, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_12
0x02, 0x58, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_20
0x02, 0x5C, 0x04, 0x00, 0x00, 0x00, 0x00, // CPASS_MTX_21
0x02, 0xBC, 0x04, 0xC0, 0x00, 0x00, 0x00, // CPASS_MTX_22
0x01, 0xEC, 0x04, 0x00, 0x00, 0x40, 0x00, // D_1_236 inv_apply_endian_accel
0x03, 0x86, 0x06, 0x0C, 0xC9, 0x2C, 0x97, 0x97, 0x97, // FCFG_2 inv_set_mpu_sensors
0x04, 0x22, 0x03, 0x0D, 0x35, 0x5D, // CFG_MOTION_BIAS inv_turn_on_bias_from_no_motion
0x00, 0xA3, 0x01, 0x00, // ?
0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D, // FCFG_5 inv_set_bias_update
0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // CFG_8 inv_send_quaternion
0x07, 0x9F, 0x01, 0x30, // CFG_16 inv_set_footer
0x07, 0x67, 0x01, 0x9A, // CFG_GYRO_SOURCE inv_send_gyro
0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_9 inv_send_gyro -> inv_construct3_fifo
0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ?
0x02, 0x0C, 0x04, 0x00, 0x00, 0x00, 0x00, // ?
0x07, 0x83, 0x06, 0xC2, 0xCA, 0xC4, 0xA3, 0xA3, 0xA3, // ?
// SPECIAL 0x01 = enable interrupts
0x00, 0x00, 0x00, 0x01, // SET INT_ENABLE, SPECIAL INSTRUCTION
0x07, 0xA7, 0x01, 0xFE, // ?
0x07, 0x62, 0x05, 0xF1, 0x20, 0x28, 0x30, 0x38, // ?
0x07, 0x67, 0x01, 0x9A, // ?
0x07, 0x68, 0x04, 0xF1, 0x28, 0x30, 0x38, // CFG_12 inv_send_accel -> inv_construct3_fifo
0x07, 0x8D, 0x04, 0xF1, 0x28, 0x30, 0x38, // ??? CFG_12 inv_send_mag -> inv_construct3_fifo
0x02, 0x16, 0x02, 0x00, 0x03 // D_0_22 inv_set_fifo_rate
// This very last 0x01 WAS a 0x09, which drops the FIFO rate down to 20 Hz. 0x07 is 25 Hz,
// 0x01 is 100Hz. Going faster than 100Hz (0x00=200Hz) tends to result in very noisy data.
// DMP output frequency is calculated easily using this equation: (200Hz / (1 + value))
// It is important to make sure the host processor can keep up with reading and processing
// the FIFO output at the desired rate. Handling FIFO overflow cleanly is also a good idea.
};
const prog_uchar dmpUpdates[MPU6050_DMP_UPDATES_SIZE] PROGMEM = {
0x01, 0xB2, 0x02, 0xFF, 0xF5,
0x01, 0x90, 0x04, 0x0A, 0x0D, 0x97, 0xC0,
0x00, 0xA3, 0x01, 0x00,
0x04, 0x29, 0x04, 0x87, 0x2D, 0x35, 0x3D,
0x01, 0x6A, 0x02, 0x06, 0x00,
0x01, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00,
0x02, 0x60, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x08, 0x02, 0x01, 0x20,
0x01, 0x0A, 0x02, 0x00, 0x4E,
0x01, 0x02, 0x02, 0xFE, 0xB3,
0x02, 0x6C, 0x04, 0x00, 0x00, 0x00, 0x00, // READ
0x02, 0x6C, 0x04, 0xFA, 0xFE, 0x00, 0x00,
0x02, 0x60, 0x0C, 0xFF, 0xFF, 0xCB, 0x4D, 0x00, 0x01, 0x08, 0xC1, 0xFF, 0xFF, 0xBC, 0x2C,
0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00,
0x02, 0xF8, 0x04, 0x00, 0x00, 0x00, 0x00,
0x02, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x04, 0x40, 0x00, 0x00, 0x00,
0x00, 0x60, 0x04, 0x00, 0x40, 0x00, 0x00
};
uint8_t MPU6050::dmpInitialize() {
// reset device
DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
reset();
delay(30); // wait after reset
// disable sleep mode
DEBUG_PRINTLN(F("Disabling sleep mode..."));
setSleepEnabled(false);
// get MPU product ID
DEBUG_PRINTLN(F("Getting product ID..."));
//uint8_t productID = 0; //getProductID();
DEBUG_PRINT(F("Product ID = "));
DEBUG_PRINT(productID);
// get MPU hardware revision
DEBUG_PRINTLN(F("Selecting user bank 16..."));
setMemoryBank(0x10, true, true);
DEBUG_PRINTLN(F("Selecting memory byte 6..."));
setMemoryStartAddress(0x06);
DEBUG_PRINTLN(F("Checking hardware revision..."));
uint8_t hwRevision = readMemoryByte();
DEBUG_PRINT(F("Revision @ user[16][6] = "));
DEBUG_PRINTLNF(hwRevision, HEX);
DEBUG_PRINTLN(F("Resetting memory bank selection to 0..."));
setMemoryBank(0, false, false);
// check OTP bank valid
DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
uint8_t otpValid = getOTPBankValid();
DEBUG_PRINT(F("OTP bank is "));
DEBUG_PRINTLN(otpValid ? F("valid!") : F("invalid!"));
// get X/Y/Z gyro offsets
DEBUG_PRINTLN(F("Reading gyro offset values..."));
int8_t xgOffset = getXGyroOffset();
int8_t ygOffset = getYGyroOffset();
int8_t zgOffset = getZGyroOffset();
DEBUG_PRINT(F("X gyro offset = "));
DEBUG_PRINTLN(xgOffset);
DEBUG_PRINT(F("Y gyro offset = "));
DEBUG_PRINTLN(ygOffset);
DEBUG_PRINT(F("Z gyro offset = "));
DEBUG_PRINTLN(zgOffset);
I2Cdev::readByte(devAddr, MPU6050_RA_USER_CTRL, buffer); // ?
DEBUG_PRINTLN(F("Enabling interrupt latch, clear on any read, AUX bypass enabled"));
I2Cdev::writeByte(devAddr, MPU6050_RA_INT_PIN_CFG, 0x32);
// enable MPU AUX I2C bypass mode
//DEBUG_PRINTLN(F("Enabling AUX I2C bypass mode..."));
//setI2CBypassEnabled(true);
DEBUG_PRINTLN(F("Setting magnetometer mode to power-down..."));
//mag -> setMode(0);
I2Cdev::writeByte(0x0E, 0x0A, 0x00);
DEBUG_PRINTLN(F("Setting magnetometer mode to fuse access..."));
//mag -> setMode(0x0F);
I2Cdev::writeByte(0x0E, 0x0A, 0x0F);
DEBUG_PRINTLN(F("Reading mag magnetometer factory calibration..."));
int8_t asax, asay, asaz;
//mag -> getAdjustment(&asax, &asay, &asaz);
I2Cdev::readBytes(0x0E, 0x10, 3, buffer);
asax = (int8_t)buffer[0];
asay = (int8_t)buffer[1];
asaz = (int8_t)buffer[2];
DEBUG_PRINT(F("Adjustment X/Y/Z = "));
DEBUG_PRINT(asax);
DEBUG_PRINT(F(" / "));
DEBUG_PRINT(asay);
DEBUG_PRINT(F(" / "));
DEBUG_PRINTLN(asaz);
DEBUG_PRINTLN(F("Setting magnetometer mode to power-down..."));
//mag -> setMode(0);
I2Cdev::writeByte(0x0E, 0x0A, 0x00);
// load DMP code into memory banks
DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
DEBUG_PRINTLN(F(" bytes)"));
if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) {
DEBUG_PRINTLN(F("Success! DMP code written and verified."));
DEBUG_PRINTLN(F("Configuring DMP and related settings..."));
// write DMP configuration
DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE);
DEBUG_PRINTLN(F(" bytes in config def)"));
if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) {
DEBUG_PRINTLN(F("Success! DMP configuration written and verified."));
DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
setIntEnabled(0x12);
DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
setRate(4); // 1khz / (1 + 4) = 200 Hz
DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
setClockSource(MPU6050_CLOCK_PLL_ZGYRO);
DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
setDLPFMode(MPU6050_DLPF_BW_42);
DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);
DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
DEBUG_PRINTLN(F("Setting DMP configuration bytes (function unknown)..."));
setDMPConfig1(0x03);
setDMPConfig2(0x00);
DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
setOTPBankValid(false);
DEBUG_PRINTLN(F("Setting X/Y/Z gyro offsets to previous values..."));
setXGyroOffset(xgOffset);
setYGyroOffset(ygOffset);
setZGyroOffset(zgOffset);
DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero..."));
setXGyroOffsetUser(0);
setYGyroOffsetUser(0);
setZGyroOffsetUser(0);
DEBUG_PRINTLN(F("Writing final memory update 1/19 (function unknown)..."));
uint8_t dmpUpdate[16], j;
uint16_t pos = 0;
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 2/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Resetting FIFO..."));
resetFIFO();
DEBUG_PRINTLN(F("Reading FIFO count..."));
uint8_t fifoCount = getFIFOCount();
DEBUG_PRINT(F("Current FIFO count="));
DEBUG_PRINTLN(fifoCount);
uint8_t fifoBuffer[128];
//getFIFOBytes(fifoBuffer, fifoCount);
DEBUG_PRINTLN(F("Writing final memory update 3/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 4/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Disabling all standby flags..."));
I2Cdev::writeByte(0x68, MPU6050_RA_PWR_MGMT_2, 0x00);
DEBUG_PRINTLN(F("Setting accelerometer sensitivity to +/- 2g..."));
I2Cdev::writeByte(0x68, MPU6050_RA_ACCEL_CONFIG, 0x00);
DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
setMotionDetectionThreshold(2);
DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
setZeroMotionDetectionThreshold(156);
DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
setMotionDetectionDuration(80);
DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
setZeroMotionDetectionDuration(0);
DEBUG_PRINTLN(F("Setting AK8975 to single measurement mode..."));
//mag -> setMode(1);
I2Cdev::writeByte(0x0E, 0x0A, 0x01);
// setup AK8975 (0x0E) as Slave 0 in read mode
DEBUG_PRINTLN(F("Setting up AK8975 read slave 0..."));
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_ADDR, 0x8E);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_REG, 0x01);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV0_CTRL, 0xDA);
// setup AK8975 (0x0E) as Slave 2 in write mode
DEBUG_PRINTLN(F("Setting up AK8975 write slave 2..."));
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_ADDR, 0x0E);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_REG, 0x0A);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_CTRL, 0x81);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV2_DO, 0x01);
// setup I2C timing/delay control
DEBUG_PRINTLN(F("Setting up slave access delay..."));
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_SLV4_CTRL, 0x18);
I2Cdev::writeByte(0x68, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x05);
// enable interrupts
DEBUG_PRINTLN(F("Enabling default interrupt behavior/no bypass..."));
I2Cdev::writeByte(0x68, MPU6050_RA_INT_PIN_CFG, 0x00);
// enable I2C master mode and reset DMP/FIFO
DEBUG_PRINTLN(F("Enabling I2C master mode..."));
I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20);
DEBUG_PRINTLN(F("Resetting FIFO..."));
I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x24);
DEBUG_PRINTLN(F("Rewriting I2C master mode enabled because...I don't know"));
I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0x20);
DEBUG_PRINTLN(F("Enabling and resetting DMP/FIFO..."));
I2Cdev::writeByte(0x68, MPU6050_RA_USER_CTRL, 0xE8);
DEBUG_PRINTLN(F("Writing final memory update 5/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 6/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 7/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 8/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 9/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 10/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 11/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Reading final memory update 12/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
#ifdef DEBUG
DEBUG_PRINT(F("Read bytes: "));
for (j = 0; j < 4; j++) {
DEBUG_PRINTF(dmpUpdate[3 + j], HEX);
DEBUG_PRINT(" ");
}
DEBUG_PRINTLN("");
#endif
DEBUG_PRINTLN(F("Writing final memory update 13/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 14/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 15/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 16/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Writing final memory update 17/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Waiting for FIRO count >= 46..."));
while ((fifoCount = getFIFOCount()) < 46);
DEBUG_PRINTLN(F("Reading FIFO..."));
getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
DEBUG_PRINTLN(F("Reading interrupt status..."));
getIntStatus();
DEBUG_PRINTLN(F("Writing final memory update 18/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Waiting for FIRO count >= 48..."));
while ((fifoCount = getFIFOCount()) < 48);
DEBUG_PRINTLN(F("Reading FIFO..."));
getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
DEBUG_PRINTLN(F("Reading interrupt status..."));
getIntStatus();
DEBUG_PRINTLN(F("Waiting for FIRO count >= 48..."));
while ((fifoCount = getFIFOCount()) < 48);
DEBUG_PRINTLN(F("Reading FIFO..."));
getFIFOBytes(fifoBuffer, min(fifoCount, 128)); // safeguard only 128 bytes
DEBUG_PRINTLN(F("Reading interrupt status..."));
getIntStatus();
DEBUG_PRINTLN(F("Writing final memory update 19/19 (function unknown)..."));
for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);
DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
setDMPEnabled(false);
DEBUG_PRINTLN(F("Setting up internal 48-byte (default) DMP packet buffer..."));
dmpPacketSize = 48;
/*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) {
return 3; // TODO: proper error code for no memory
}*/
DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
resetFIFO();
getIntStatus();
} else {
DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed."));
return 2; // configuration block loading failed
}
} else {
DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
return 1; // main binary block loading failed
}
return 0; // success
}
bool MPU6050::dmpPacketAvailable() {
return getFIFOCount() >= dmpGetFIFOPacketSize();
}
// uint8_t MPU6050::dmpSetFIFORate(uint8_t fifoRate);
// uint8_t MPU6050::dmpGetFIFORate();
// uint8_t MPU6050::dmpGetSampleStepSizeMS();
// uint8_t MPU6050::dmpGetSampleFrequency();
// int32_t MPU6050::dmpDecodeTemperature(int8_t tempReg);
//uint8_t MPU6050::dmpRegisterFIFORateProcess(inv_obj_func func, int16_t priority);
//uint8_t MPU6050::dmpUnregisterFIFORateProcess(inv_obj_func func);
//uint8_t MPU6050::dmpRunFIFORateProcesses();
// uint8_t MPU6050::dmpSendQuaternion(uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendGyro(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendLinearAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendLinearAccelInWorld(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendControlData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendExternalSensorData(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendGravity(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendPacketNumber(uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendQuantizedAccel(uint_fast16_t elements, uint_fast16_t accuracy);
// uint8_t MPU6050::dmpSendEIS(uint_fast16_t elements, uint_fast16_t accuracy);
uint8_t MPU6050::dmpGetAccel(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[34] << 24) + (packet[35] << 16) + (packet[36] << 8) + packet[37]);
data[1] = ((packet[38] << 24) + (packet[39] << 16) + (packet[40] << 8) + packet[41]);
data[2] = ((packet[42] << 24) + (packet[43] << 16) + (packet[44] << 8) + packet[45]);
return 0;
}
uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[34] << 8) + packet[35];
data[1] = (packet[38] << 8) + packet[39];
data[2] = (packet[42] << 8) + packet[43];
return 0;
}
uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
v -> x = (packet[34] << 8) + packet[35];
v -> y = (packet[38] << 8) + packet[39];
v -> z = (packet[42] << 8) + packet[43];
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[0] << 24) + (packet[1] << 16) + (packet[2] << 8) + packet[3]);
data[1] = ((packet[4] << 24) + (packet[5] << 16) + (packet[6] << 8) + packet[7]);
data[2] = ((packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11]);
data[3] = ((packet[12] << 24) + (packet[13] << 16) + (packet[14] << 8) + packet[15]);
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[0] << 8) + packet[1]);
data[1] = ((packet[4] << 8) + packet[5]);
data[2] = ((packet[8] << 8) + packet[9]);
data[3] = ((packet[12] << 8) + packet[13]);
return 0;
}
uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
int16_t qI[4];
uint8_t status = dmpGetQuaternion(qI, packet);
if (status == 0) {
q -> w = (float)qI[0] / 16384.0f;
q -> x = (float)qI[1] / 16384.0f;
q -> y = (float)qI[2] / 16384.0f;
q -> z = (float)qI[3] / 16384.0f;
return 0;
}
return status; // int16 return value, indicates error if this line is reached
}
// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = ((packet[16] << 24) + (packet[17] << 16) + (packet[18] << 8) + packet[19]);
data[1] = ((packet[20] << 24) + (packet[21] << 16) + (packet[22] << 8) + packet[23]);
data[2] = ((packet[24] << 24) + (packet[25] << 16) + (packet[26] << 8) + packet[27]);
return 0;
}
uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[16] << 8) + packet[17];
data[1] = (packet[20] << 8) + packet[21];
data[2] = (packet[24] << 8) + packet[25];
return 0;
}
uint8_t MPU6050::dmpGetMag(int16_t *data, const uint8_t* packet) {
// TODO: accommodate different arrangements of sent data (ONLY default supported now)
if (packet == 0) packet = dmpPacketBuffer;
data[0] = (packet[28] << 8) + packet[29];
data[1] = (packet[30] << 8) + packet[31];
data[2] = (packet[32] << 8) + packet[33];
return 0;
}
// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef);
// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
// get rid of the gravity component (+1g = +4096 in standard DMP FIFO packet)
v -> x = vRaw -> x - gravity -> x*4096;
v -> y = vRaw -> y - gravity -> y*4096;
v -> z = vRaw -> z - gravity -> z*4096;
return 0;
}
// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
// rotate measured 3D acceleration vector into original state
// frame of reference based on orientation quaternion
memcpy(v, vReal, sizeof(VectorInt16));
v -> rotate(q);
return 0;
}
// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
return 0;
}
// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet);
// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1); // psi
data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y); // theta
data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1); // phi
return 0;
}
uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
// yaw: (about Z axis)
data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
// pitch: (nose up/down, about Y axis)
data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
// roll: (tilt left/right, about X axis)
data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
return 0;
}
// uint8_t MPU6050::dmpGetAccelFloat(float *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetQuaternionFloat(float *data, const uint8_t* packet);
uint8_t MPU6050::dmpProcessFIFOPacket(const unsigned char *dmpData) {
/*for (uint8_t k = 0; k < dmpPacketSize; k++) {
if (dmpData[k] < 0x10) Serial.print("0");
Serial.print(dmpData[k], HEX);
Serial.print(" ");
}
Serial.print("\n");*/
//Serial.println((uint16_t)dmpPacketBuffer);
return 0;
}
uint8_t MPU6050::dmpReadAndProcessFIFOPacket(uint8_t numPackets, uint8_t *processed) {
uint8_t status;
uint8_t buf[dmpPacketSize];
for (uint8_t i = 0; i < numPackets; i++) {
// read packet from FIFO
getFIFOBytes(buf, dmpPacketSize);
// process packet
if ((status = dmpProcessFIFOPacket(buf)) > 0) return status;
// increment external process count variable, if supplied
if (processed != 0) *processed++;
}
return 0;
}
// uint8_t MPU6050::dmpSetFIFOProcessedCallback(void (*func) (void));
// uint8_t MPU6050::dmpInitFIFOParam();
// uint8_t MPU6050::dmpCloseFIFO();
// uint8_t MPU6050::dmpSetGyroDataSource(uint_fast8_t source);
// uint8_t MPU6050::dmpDecodeQuantizedAccel();
// uint32_t MPU6050::dmpGetGyroSumOfSquare();
// uint32_t MPU6050::dmpGetAccelSumOfSquare();
// void MPU6050::dmpOverrideQuaternion(long *q);
uint16_t MPU6050::dmpGetFIFOPacketSize() {
return dmpPacketSize;
}
#endif /* _MPU6050_9AXIS_MOTIONAPPS41_H_ */

218
lib/MPU6050/helper_3dmath.h Normal file
View File

@ -0,0 +1,218 @@
// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class, 3D math helper
// 6/5/2012 by Jeff Rowberg <jeff@rowberg.net>
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
//
// Adapted for Sonoff-Tasmota by Oliver Welter <contact@verbotene.zone> 02-04-2018
//
// Changelog:
// 2012-06-05 - add 3D math helper file to DMP6 example sketch
/* ============================================
I2Cdev device library code is placed under the MIT license
Copyright (c) 2012 Jeff Rowberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================
*/
#ifndef _HELPER_3DMATH_H_
#define _HELPER_3DMATH_H_
class Quaternion {
public:
float w;
float x;
float y;
float z;
Quaternion() {
w = 1.0f;
x = 0.0f;
y = 0.0f;
z = 0.0f;
}
Quaternion(float nw, float nx, float ny, float nz) {
w = nw;
x = nx;
y = ny;
z = nz;
}
Quaternion getProduct(Quaternion q) {
// Quaternion multiplication is defined by:
// (Q1 * Q2).w = (w1w2 - x1x2 - y1y2 - z1z2)
// (Q1 * Q2).x = (w1x2 + x1w2 + y1z2 - z1y2)
// (Q1 * Q2).y = (w1y2 - x1z2 + y1w2 + z1x2)
// (Q1 * Q2).z = (w1z2 + x1y2 - y1x2 + z1w2
return Quaternion(
w*q.w - x*q.x - y*q.y - z*q.z, // new w
w*q.x + x*q.w + y*q.z - z*q.y, // new x
w*q.y - x*q.z + y*q.w + z*q.x, // new y
w*q.z + x*q.y - y*q.x + z*q.w); // new z
}
Quaternion getConjugate() {
return Quaternion(w, -x, -y, -z);
}
float getMagnitude() {
return sqrt(w*w + x*x + y*y + z*z);
}
void normalize() {
float m = getMagnitude();
w /= m;
x /= m;
y /= m;
z /= m;
}
Quaternion getNormalized() {
Quaternion r(w, x, y, z);
r.normalize();
return r;
}
};
class VectorInt16 {
public:
int16_t x;
int16_t y;
int16_t z;
VectorInt16() {
x = 0;
y = 0;
z = 0;
}
VectorInt16(int16_t nx, int16_t ny, int16_t nz) {
x = nx;
y = ny;
z = nz;
}
float getMagnitude() {
return sqrt(x*x + y*y + z*z);
}
void normalize() {
float m = getMagnitude();
x /= m;
y /= m;
z /= m;
}
VectorInt16 getNormalized() {
VectorInt16 r(x, y, z);
r.normalize();
return r;
}
void rotate(Quaternion *q) {
// http://www.cprogramming.com/tutorial/3d/quaternions.html
// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/index.htm
// http://content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation
// ^ or: http://webcache.googleusercontent.com/search?q=cache:xgJAp3bDNhQJ:content.gpwiki.org/index.php/OpenGL:Tutorials:Using_Quaternions_to_represent_rotation&hl=en&gl=us&strip=1
// P_out = q * P_in * conj(q)
// - P_out is the output vector
// - q is the orientation quaternion
// - P_in is the input vector (a*aReal)
// - conj(q) is the conjugate of the orientation quaternion (q=[w,x,y,z], q*=[w,-x,-y,-z])
Quaternion p(0, x, y, z);
// quaternion multiplication: q * p, stored back in p
p = q -> getProduct(p);
// quaternion multiplication: p * conj(q), stored back in p
p = p.getProduct(q -> getConjugate());
// p quaternion is now [0, x', y', z']
x = p.x;
y = p.y;
z = p.z;
}
VectorInt16 getRotated(Quaternion *q) {
VectorInt16 r(x, y, z);
r.rotate(q);
return r;
}
};
class VectorFloat {
public:
float x;
float y;
float z;
VectorFloat() {
x = 0;
y = 0;
z = 0;
}
VectorFloat(float nx, float ny, float nz) {
x = nx;
y = ny;
z = nz;
}
float getMagnitude() {
return sqrt(x*x + y*y + z*z);
}
void normalize() {
float m = getMagnitude();
x /= m;
y /= m;
z /= m;
}
VectorFloat getNormalized() {
VectorFloat r(x, y, z);
r.normalize();
return r;
}
void rotate(Quaternion *q) {
Quaternion p(0, x, y, z);
// quaternion multiplication: q * p, stored back in p
p = q -> getProduct(p);
// quaternion multiplication: p * conj(q), stored back in p
p = p.getProduct(q -> getConjugate());
// p quaternion is now [0, x', y', z']
x = p.x;
y = p.y;
z = p.z;
}
VectorFloat getRotated(Quaternion *q) {
VectorFloat r(x, y, z);
r.rotate(q);
return r;
}
};
#endif /* _HELPER_3DMATH_H_ */

View File

@ -1,4 +1,14 @@
/* 6.1.1c
* Fix sonoff-minimal from using default settings
* Add option + to command Rule to concatenate new rule with existing rules (#3365)
* Add initial support for sensor MPU6050 (#3352)
* Add command SerialSend4 to send binary serial data (#3345)
* Add rule triggers Wifi#Connected and Wifi#Disconnected (#3359)
* Fix unsecure main webpage update
* Add Turkish language file (#3332)
* Fix command TimeDst/TimeStd invalid JSON (#3322)
* Fix possible WDT due to long MQTT publish handling (#3313)
* Fix CCS811 temperature and humidity compensation
* Add support for CCS811 sensor (#3309)
* Add command Timers 0/1 to globally disable or enable armed timers (#3270)
*

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Подтвърдете рестартирането"
#define D_CONFIGURE_MODULE "Конфигурация на модула"
#define D_CONFIGURE_MCP230XX "Конфигурация на MCP230xx"
#define D_CONFIGURE_WIFI "Конфигурация на WiFi"
#define D_CONFIGURE_MQTT "Конфигурация на MQTT"
#define D_CONFIGURE_DOMOTICZ "Конфигурация на Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Potvrzení restartu"
#define D_CONFIGURE_MODULE "Nastavení modulu"
#define D_CONFIGURE_MCP230XX "Nastavení MCP230xx"
#define D_CONFIGURE_WIFI "Nastavení WiFi"
#define D_CONFIGURE_MQTT "Nastavení MQTT"
#define D_CONFIGURE_DOMOTICZ "Nastavení Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Wirklich neustarten?"
#define D_CONFIGURE_MODULE "Gerät konfigurieren"
#define D_CONFIGURE_MCP230XX "MCP230xx konfigurieren"
#define D_CONFIGURE_WIFI "WLAN konfigurieren"
#define D_CONFIGURE_MQTT "MQTT konfigurieren"
#define D_CONFIGURE_DOMOTICZ "Domoticz konfigurieren"
@ -437,6 +436,14 @@
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
#define D_PARTICALS_BEYOND "Particals"
// xsns_32_mpu6050.ino
#define D_AX_AXIS "Beschl. X-Achse"
#define D_AY_AXIS "Beschl. Y-Achse"
#define D_AZ_AXIS "Beschl. Z-Achse"
#define D_GX_AXIS "Gyroskop X-Achse"
#define D_GY_AXIS "Gyroskop Y-Achse"
#define D_GZ_AXIS "Gyroskop Z-Achse"
// sonoff_template.h
#define D_SENSOR_NONE "None"
#define D_SENSOR_DHT11 "DHT11"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Επιβεβαίωση Επανεκκίνησης"
#define D_CONFIGURE_MODULE "Ρύθμιση Module"
#define D_CONFIGURE_MCP230XX "Ρύθμιση MCP230xx"
#define D_CONFIGURE_WIFI "Ρύθμιση WiFi"
#define D_CONFIGURE_MQTT "Ρύθμιση MQTT"
#define D_CONFIGURE_DOMOTICZ "Ρύθμιση Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Confirm Restart"
#define D_CONFIGURE_MODULE "Configure Module"
#define D_CONFIGURE_MCP230XX "Configure MCP230xx"
#define D_CONFIGURE_WIFI "Configure WiFi"
#define D_CONFIGURE_MQTT "Configure MQTT"
#define D_CONFIGURE_DOMOTICZ "Configure Domoticz"
@ -437,6 +436,14 @@
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
#define D_PARTICALS_BEYOND "Particals"
// xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis"
#define D_AY_AXIS "Accel. Y-Axis"
#define D_AZ_AXIS "Accel. Z-Axis"
#define D_GX_AXIS "Gyro X-Axis"
#define D_GY_AXIS "Gyro Y-Axis"
#define D_GZ_AXIS "Gyro Z-Axis"
// sonoff_template.h
#define D_SENSOR_NONE "None"
#define D_SENSOR_DHT11 "DHT11"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Confirmar Reinicio"
#define D_CONFIGURE_MODULE "Configuración del Módulo"
#define D_CONFIGURE_MCP230XX "Configuración MCP230xx"
#define D_CONFIGURE_WIFI "Configuración WiFi"
#define D_CONFIGURE_MQTT "Configuración MQTT"
#define D_CONFIGURE_DOMOTICZ "Configuración Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Confirmer redémarrage"
#define D_CONFIGURE_MODULE "Configuration du Module"
#define D_CONFIGURE_MCP230XX "Configuration MCP230xx"
#define D_CONFIGURE_WIFI "Configuration WiFi"
#define D_CONFIGURE_MQTT "Configuration MQTT"
#define D_CONFIGURE_DOMOTICZ "Configuration Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Újraindítás megerősítése"
#define D_CONFIGURE_MODULE "Eszköz konfiguráció"
#define D_CONFIGURE_MCP230XX "MCP230xx konfiguráció"
#define D_CONFIGURE_WIFI "WiFi konfiguráció"
#define D_CONFIGURE_MQTT "MQTT konfiguráció"
#define D_CONFIGURE_DOMOTICZ "Domoticz konfiguráció"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Conferma Riavvio"
#define D_CONFIGURE_MODULE "Configurazione Modulo"
#define D_CONFIGURE_MCP230XX "Configurazione MCP230xx"
#define D_CONFIGURE_WIFI "Configurazione WiFi"
#define D_CONFIGURE_MQTT "Configurazione MQTT"
#define D_CONFIGURE_DOMOTICZ "Configurazione Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Bevestig herstart"
#define D_CONFIGURE_MODULE "Configureer Module"
#define D_CONFIGURE_MCP230XX "Configureer MCP230xx"
#define D_CONFIGURE_WIFI "Configureer WiFi"
#define D_CONFIGURE_MQTT "Configureer MQTT"
#define D_CONFIGURE_DOMOTICZ "Configureer Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Potwierdź restart"
#define D_CONFIGURE_MODULE "Konfiguruj moduł"
#define D_CONFIGURE_MCP230XX "Konfiguruj MCP230xx"
#define D_CONFIGURE_WIFI "Konfiguruj WiFi"
#define D_CONFIGURE_MQTT "Konfiguruj MQTT"
#define D_CONFIGURE_DOMOTICZ "Konfiguruj Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Confirmar o reinicio"
#define D_CONFIGURE_MODULE "Configurar Módulo"
#define D_CONFIGURE_MCP230XX "Configurar MCP230xx"
#define D_CONFIGURE_WIFI "Configurar WiFi"
#define D_CONFIGURE_MQTT "Configurar MQTT"
#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Confirmar o reinicio"
#define D_CONFIGURE_MODULE "Configurar Módulo"
#define D_CONFIGURE_MCP230XX "Configurar MCP230xx"
#define D_CONFIGURE_WIFI "Configurar WiFi"
#define D_CONFIGURE_MQTT "Configurar MQTT"
#define D_CONFIGURE_DOMOTICZ "Configurar Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Подтвердить перезагрузку"
#define D_CONFIGURE_MODULE "Конфигурация Модуля"
#define D_CONFIGURE_MCP230XX "Конфигурация MCP230xx"
#define D_CONFIGURE_WIFI "Конфигурация WiFi"
#define D_CONFIGURE_MQTT "Конфигурация MQTT"
#define D_CONFIGURE_DOMOTICZ "Конфигурация Domoticz"

530
sonoff/language/tr-TR.h Executable file
View File

@ -0,0 +1,530 @@
/*
tr-TR.h - localization for Turkish - Turkey for Sonoff-Tasmota
Copyright (C) 2018 Ali Sait Teke and Theo Arends
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/>.
*/
#ifndef _LANGUAGE_TR_TR_H_
#define _LANGUAGE_TR_TR_H_
/*************************** ATTENTION *******************************\
*
* Due to memory constraints only UTF-8 is supported.
* To save code space keep text as short as possible.
* Time and Date provided by SDK can not be localized (yet).
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v6.1.1
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
#define LANGUAGE_LCID 1055
// HTML (ISO 639-1) Language Code
#define D_HTML_LANGUAGE "tr"
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "."
#define D_MONTH_DAY_SEPARATOR "."
#define D_DATE_TIME_SEPARATOR "T"
#define D_HOUR_MINUTE_SEPARATOR ":"
#define D_MINUTE_SECOND_SEPARATOR ":"
#define D_DAY3LIST "PazPztSalCarPerCumCmt"
#define D_MONTH3LIST "OckSubMarNisMayHazTemAguEylEkmKasAra"
// Non JSON decimal separator
#define D_DECIMAL_SEPARATOR "."
// Common
#define D_ADMIN "Admin"
#define D_AIR_QUALITY "Hava Kalitesi"
#define D_AP "AP" // Access Point
#define D_AS "as"
#define D_AUTO "OTOMATIK"
#define D_BLINK "Blink"
#define D_BLINKOFF "BlinkOff"
#define D_BOOT_COUNT "Yeniden başlama sayısı"
#define D_BRIGHTLIGHT "Işık"
#define D_BUTTON "Buton"
#define D_BY "by" // Written by me
#define D_BYTES "Bayt"
#define D_CELSIUS "Derece"
#define D_CO2 "Karbon dioksit"
#define D_CODE "kod" // Button code
#define D_COLDLIGHT "Soğuk"
#define D_COMMAND "Komut"
#define D_CONNECTED "Bağlandı"
#define D_COUNT "Sayı"
#define D_COUNTER "Sayaç"
#define D_CURRENT "Current" // As in Voltage and Current
#define D_DATA "Data"
#define D_DARKLIGHT "Karanlık"
#define D_DEBUG "Hata Ayıklama"
#define D_DISABLED "Etkin Değil"
#define D_DISTANCE "Mesage"
#define D_DNS_SERVER "DNS Sunucu"
#define D_DONE "Tamam"
#define D_DST_TIME "DST"
#define D_ECO2 "eCO2"
#define D_EMULATION "Emülasyon"
#define D_ENABLED "Etkin"
#define D_ERASE "Temizle"
#define D_ERROR "Hata"
#define D_FAHRENHEIT "Fahrenayt"
#define D_FAILED "Başlarısız"
#define D_FALLBACK "Geri iletim"
#define D_FALLBACK_TOPIC "Geri İletim Topiği"
#define D_FALSE "False"
#define D_FILE "Dosya"
#define D_FREE_MEMORY "Boş Hafıza"
#define D_FREQUENCY "Frekans"
#define D_GAS "Gas"
#define D_GATEWAY "Geçit"
#define D_GROUP "Grup"
#define D_HOST "Host"
#define D_HOSTNAME "Host Adresi"
#define D_HUMIDITY "Nem"
#define D_ILLUMINANCE "Aydınlık"
#define D_IMMEDIATE "derhal" // Button immediate
#define D_INDEX "Index"
#define D_INFO "Bilgi"
#define D_INFRARED "Kızılötesi"
#define D_INITIALIZED "Başlatıldı"
#define D_IP_ADDRESS "IP Adresi"
#define D_LIGHT "Işık"
#define D_LWT "LWT"
#define D_MODULE "Modül"
#define D_MQTT "MQTT"
#define D_MULTI_PRESS "multi-press"
#define D_NOISE "Noise"
#define D_NONE "None"
#define D_OFF "Off"
#define D_OFFLINE "Çevirimdışı"
#define D_OK "Tamam"
#define D_ON "On"
#define D_ONLINE "Çevirimiçi"
#define D_PASSWORD "Şifre"
#define D_PORT "Port"
#define D_POWER_FACTOR "Güç Faktörü"
#define D_POWERUSAGE "Güç"
#define D_POWERUSAGE_ACTIVE "Aktif Güç"
#define D_POWERUSAGE_APPARENT "Görünen Güç"
#define D_POWERUSAGE_REACTIVE "Reaktif Güç"
#define D_PRESSURE "Basınç"
#define D_PRESSUREATSEALEVEL "Deniz Seviyesi Basıncı"
#define D_PROGRAM_FLASH_SIZE "Yazılım Flash Boyutu"
#define D_PROGRAM_SIZE "Yazılım Boyutu"
#define D_PROJECT "Proje"
#define D_RECEIVED "Alınan"
#define D_RESTART "Yeniden Başlat"
#define D_RESTARTING "Yeniden Başlatılıyor"
#define D_RESTART_REASON "Yeniden Başlatma Sebebi"
#define D_RESTORE "restore"
#define D_RETAINED "tutulan"
#define D_RULE "Kural"
#define D_SAVE "Kaydet"
#define D_SENSOR "Sensör"
#define D_SSID "SSId"
#define D_START "Başlat"
#define D_STD_TIME "STD"
#define D_STOP "Durdur"
#define D_SUBNET_MASK "Altağ Geçidi Maskesi"
#define D_SUBSCRIBE_TO "Abone olunan"
#define D_SUCCESSFUL "Başarıyla Tamamlandı"
#define D_SUNRISE "Gün doğumu"
#define D_SUNSET "Gün batımı"
#define D_TEMPERATURE "Sıcaklık"
#define D_TO "den"
#define D_TOGGLE "Geçiş Tuşu"
#define D_TOPIC "Başlık"
#define D_TRANSMIT "İletim"
#define D_TRUE "True"
#define D_TVOC "TVOC"
#define D_UPGRADE "yükseltme"
#define D_UPLOAD "Yükleme"
#define D_UPTIME "Açık Kalma Süresi"
#define D_USER "Kullanıcı"
#define D_UTC_TIME "UTC"
#define D_UV_INDEX "UV Indeksi"
#define D_UV_LEVEL "UV Seviyesi"
#define D_VERSION "Versiyon"
#define D_VOLTAGE "Voltaj"
#define D_WARMLIGHT "Sıcak"
#define D_WEB_SERVER "Web Sunucusu"
// sonoff.ino
#define D_WARNING_MINIMAL_VERSION "UYARI Bu versiyon ayarların kalıcı olarak kaydedilmesine olanak sağlamıyor"
#define D_LEVEL_10 "seviye 1-0"
#define D_LEVEL_01 "seviye 0-1"
#define D_SERIAL_LOGGING_DISABLED "Seri port loglaması kapalı"
#define D_SYSLOG_LOGGING_REENABLED "Sistem loglaması tekrar aktif"
#define D_SET_BAUDRATE_TO "Baud hızını şu şekilde değiştir"
#define D_RECEIVED_TOPIC "Alınan Başlık"
#define D_DATA_SIZE "Veri Büyüklüğü"
#define D_ANALOG_INPUT "Analog"
// support.ino
#define D_OSWATCH "osWatch"
#define D_BLOCKED_LOOP "Döngü bloke edildi"
#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status"
#define D_ACTIVE_FOR_3_MINUTES "3 dakika aktif"
#define D_FAILED_TO_START "başlatma başarılı olamadı"
#define D_PATCH_ISSUE_2186 "Patch issue 2186"
#define D_CONNECTING_TO_AP "AP'ye bağlan"
#define D_IN_MODE "modunda"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP adresi alınamadığı için bağlantı kurulamadı"
#define D_CONNECT_FAILED_AP_NOT_REACHED "Ap'ye ulaşılamadı"
#define D_CONNECT_FAILED_WRONG_PASSWORD "Girilen parolayı AP kabul etmedi"
#define D_CONNECT_FAILED_AP_TIMEOUT "AP'ye bağlanılırken süre aşımı oluştu"
#define D_ATTEMPTING_CONNECTION "Yeniden bağlanılıyor..."
#define D_CHECKING_CONNECTION "Bağlantı kontrol ediliyor..."
#define D_QUERY_DONE "Soru tamamlandı. MQTT servisleri bulundu"
#define D_MQTT_SERVICE_FOUND "Üzerinden MQTT serivisi tespit edildi"
#define D_FOUND_AT "(bulundu)"
#define D_SYSLOG_HOST_NOT_FOUND "Syslog hostu bulunamadı"
// settings.ino
#define D_SAVED_TO_FLASH_AT "Bellekten (Flash) kaydedidi:"
#define D_LOADED_FROM_FLASH_AT "Bellekten (Flash) okundu"
#define D_USE_DEFAULTS "Varsayılanları Kullan"
#define D_ERASED_SECTOR "Sektör temizlendi"
// xdrv_02_webserver.ino
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük, lütfen yükseltin"
#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif"
#define D_WITH_IP_ADDRESS "IP adres ile"
#define D_WEBSERVER_STOPPED "Web sunucusu durdu"
#define D_FILE_NOT_FOUND "Dosya Bulunamadı"
#define D_REDIRECTED "Portala yönlendirildiniz"
#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifi yöneticisi AP olarak ayarlandı ve istasyon olarak bekletiliyor"
#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifi yöneticisi AP olarak ayarlandı"
#define D_TRYING_TO_CONNECT "Cihaz ağa bağlanmaya çalışıyor"
#define D_RESTART_IN "Burada tekrar başlat"
#define D_SECONDS "saniye"
#define D_DEVICE_WILL_RESTART "Birkaç saniye içerisinde cihaz tekrar başlatılacak"
#define D_BUTTON_TOGGLE "Toggle"
#define D_CONFIGURATION "Konfigürasyon"
#define D_INFORMATION "Bilgi"
#define D_FIRMWARE_UPGRADE "Cihaz yazılımını Güncelle"
#define D_CONSOLE "Konsol"
#define D_CONFIRM_RESTART "Yeniden Başlatmayı Onayla"
#define D_CONFIGURE_MODULE "Modül Ayarlarını Değiştir"
#define D_CONFIGURE_WIFI "WiFi'i Ayarlarını Değiştir"
#define D_CONFIGURE_MQTT "MQTT'yi Ayarlarını Değiştir"
#define D_CONFIGURE_DOMOTICZ "Domoticz Ayarlarını Değiştir"
#define D_CONFIGURE_LOGGING "Loglama Ayarlarını Değiştir"
#define D_CONFIGURE_OTHER "Diğer Ayarları Değiştir"
#define D_CONFIRM_RESET_CONFIGURATION "Resetleme Ayarlarını Onayla"
#define D_RESET_CONFIGURATION "Tüm Ayarları Resetle"
#define D_BACKUP_CONFIGURATION "Ayarları Yedekle"
#define D_RESTORE_CONFIGURATION "Ayarları Geri Yükle"
#define D_MAIN_MENU "Ana Menü"
#define D_MODULE_PARAMETERS "Modül parametreleri"
#define D_MODULE_TYPE "Modul türü"
#define D_GPIO "GPIO"
#define D_SERIAL_IN "Serial In"
#define D_SERIAL_OUT "Serial Out"
#define D_WIFI_PARAMETERS "Wifi parametreleri"
#define D_SCAN_FOR_WIFI_NETWORKS "Çevredeki Wifi Networklerini Tara"
#define D_SCAN_DONE "Tarama tamamladı"
#define D_NO_NETWORKS_FOUND "Herhangi wifi ağı bulunamadı"
#define D_REFRESH_TO_SCAN_AGAIN "Tekrar tarama - yenile"
#define D_DUPLICATE_ACCESSPOINT "AP'yi çoğalt"
#define D_SKIPPING_LOW_QUALITY "Düşük kalitedekileri dikkate alma"
#define D_RSSI "RSSI"
#define D_WEP "WEP"
#define D_WPA_PSK "WPA PSK"
#define D_WPA2_PSK "WPA2 PSK"
#define D_AP1_SSID "AP1 SSId"
#define D_AP1_PASSWORD "AP1 Password"
#define D_AP2_SSID "AP2 SSId"
#define D_AP2_PASSWORD "AP2 Password"
#define D_MQTT_PARAMETERS "MQTT parametreleri"
#define D_CLIENT "İstemci"
#define D_FULL_TOPIC "Tüm Başlık"
#define D_LOGGING_PARAMETERS "Loglama parametreleri"
#define D_SERIAL_LOG_LEVEL "Serial log seviyesi"
#define D_WEB_LOG_LEVEL "Web log seviyesi"
#define D_SYS_LOG_LEVEL "Syslog seviyesi"
#define D_MORE_DEBUG "Hata ayıklama devamı"
#define D_SYSLOG_HOST "Syslog host"
#define D_SYSLOG_PORT "Syslog port"
#define D_TELEMETRY_PERIOD "Telemetri peryodu"
#define D_OTHER_PARAMETERS "Diğer parametreler"
#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi"
#define D_MQTT_ENABLE "MQTT aktif"
#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim"
#define D_BELKIN_WEMO "Belkin WeMo"
#define D_HUE_BRIDGE "Hue Bridge"
#define D_SINGLE_DEVICE "tekli cihaz"
#define D_MULTI_DEVICE "çoklu cihaz"
#define D_SAVE_CONFIGURATION "Ayarları Kaydet"
#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi"
#define D_CONFIGURATION_RESET "Ayarlar resetlendi"
#define D_PROGRAM_VERSION "Yazılım versiyonu"
#define D_BUILD_DATE_AND_TIME "Derleme Tarihi ve Saati"
#define D_CORE_AND_SDK_VERSION "Core/SDK Versiyonu"
#define D_FLASH_WRITE_COUNT "Belleğe (flash) Yazma Sayısı"
#define D_MAC_ADDRESS "MAC Adresi"
#define D_MQTT_HOST "MQTT Host"
#define D_MQTT_PORT "MQTT Port"
#define D_MQTT_CLIENT "MQTT İstemcisi"
#define D_MQTT_USER "MQTT Kullanıcısı"
#define D_MQTT_TOPIC "MQTT Topiği"
#define D_MQTT_GROUP_TOPIC "MQTT Grup Topiği"
#define D_MQTT_FULL_TOPIC "MQTT Full Topik"
#define D_MDNS_DISCOVERY "mDNS Keşfi"
#define D_MDNS_ADVERTISE "mDNS Yayını"
#define D_ESP_CHIP_ID "ESP Chip Id"
#define D_FLASH_CHIP_ID "Flash Chip Id"
#define D_FLASH_CHIP_SIZE "Flash Boyutu"
#define D_FREE_PROGRAM_SPACE "Boşta Yazılım Alanı Boyutu"
#define D_UPGRADE_BY_WEBSERVER "Web server kullanarak yükselt"
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "Yükseltmeyi başlat"
#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset"
#define D_UPLOAD_STARTED "Yükleme başlatıldı"
#define D_UPGRADE_STARTED "YÜkestlme başlatıldı"
#define D_UPLOAD_DONE "Yükleme Tamamlandı"
#define D_UPLOAD_ERR_1 "Dosya seçilmedi"
#define D_UPLOAD_ERR_2 "Boş yer yok"
#define D_UPLOAD_ERR_3 "Magic byte is not 0xE9"
#define D_UPLOAD_ERR_4 "Yazılımın boyutu gerçek boyutundan fazla"
#define D_UPLOAD_ERR_5 "Upload buffer miscompare"
#define D_UPLOAD_ERR_6 "Upload failed. Enable logging 3"
#define D_UPLOAD_ERR_7 "Upload aborted"
#define D_UPLOAD_ERR_8 "File invalid"
#define D_UPLOAD_ERR_9 "File too large"
#define D_UPLOAD_ERR_10 "Failed to init RF chip"
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
#define D_UPLOAD_ERROR_CODE "Upload error code"
#define D_ENTER_COMMAND "Enter command"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Enable weblog 2 if response expected"
#define D_NEED_USER_AND_PASSWORD "Need user=<username>&password=<password>"
// xdrv_01_mqtt.ino
#define D_FINGERPRINT "Verify TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to"
#define D_RETRY_IN "Retry in"
#define D_VERIFIED "Verified using Fingerprint"
#define D_INSECURE "Insecure connection due to invalid Fingerprint"
#define D_CONNECT_FAILED_TO "Connect failed to"
// xplg_wemohue.ino
#define D_MULTICAST_DISABLED "Multicast disabled"
#define D_MULTICAST_REJOINED "Multicast (re)joined"
#define D_MULTICAST_JOIN_FAILED "Multicast join failed"
#define D_FAILED_TO_SEND_RESPONSE "Failed to send response"
#define D_WEMO "WeMo"
#define D_WEMO_BASIC_EVENT "WeMo basic event"
#define D_WEMO_EVENT_SERVICE "WeMo event service"
#define D_WEMO_META_SERVICE "WeMo meta service"
#define D_WEMO_SETUP "WeMo setup"
#define D_RESPONSE_SENT "Response sent"
#define D_HUE "Hue"
#define D_HUE_BRIDGE_SETUP "Hue setup"
#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented"
#define D_HUE_API "Hue API"
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent"
// xdrv_07_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_IDX "Idx"
#define D_DOMOTICZ_KEY_IDX "Key idx"
#define D_DOMOTICZ_SWITCH_IDX "Switch idx"
#define D_DOMOTICZ_SENSOR_IDX "Sensor idx"
#define D_DOMOTICZ_TEMP "Temp"
#define D_DOMOTICZ_TEMP_HUM "Temp,Hum"
#define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro"
#define D_DOMOTICZ_POWER_ENERGY "Power,Energy"
#define D_DOMOTICZ_ILLUMINANCE "Illuminance"
#define D_DOMOTICZ_COUNT "Count/PM1"
#define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5"
#define D_DOMOTICZ_CURRENT "Current/PM10"
#define D_DOMOTICZ_AIRQUALITY "AirQuality"
#define D_DOMOTICZ_UPDATE_TIMER "Update timer"
// xdrv_09_timers.ino
#define D_CONFIGURE_TIMER "Configure Timer"
#define D_TIMER_PARAMETERS "Timer parameters"
#define D_TIMER_ENABLE "Enable Timers"
#define D_TIMER_ARM "Arm"
#define D_TIMER_TIME "Time"
#define D_TIMER_DAYS "Days"
#define D_TIMER_REPEAT "Repeat"
#define D_TIMER_OUTPUT "Output"
#define D_TIMER_ACTION "Action"
// xdrv_10_knx.ino
#define D_CONFIGURE_KNX "Configure KNX"
#define D_KNX_PARAMETERS "KNX Parameters"
#define D_KNX_GENERAL_CONFIG "General"
#define D_KNX_PHYSICAL_ADDRESS "Physical Address"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )"
#define D_KNX_ENABLE "Enable KNX"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses"
#define D_ADD "Add"
#define D_DELETE "Delete"
#define D_REPLY "Reply"
#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from"
#define D_LOG_KNX "KNX: "
#define D_RECEIVED_FROM "Received from"
#define D_KNX_COMMAND_WRITE "Yaz"
#define D_KNX_COMMAND_READ "Oku"
#define D_KNX_COMMAND_OTHER "Diğer"
#define D_SENT_TO "gönder"
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
#define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX"
// xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energy Today"
#define D_ENERGY_YESTERDAY "Energy Yesterday"
#define D_ENERGY_TOTAL "Energy Total"
// xsns_05_ds18b20.ino
#define D_SENSOR_BUSY "Sensör başgül"
#define D_SENSOR_CRC_ERROR "Sensor CRC hatası"
#define D_SENSORS_FOUND "Sensörler bulundu"
// xsns_06_dht.ino
#define D_TIMEOUT_WAITING_FOR "Timeout waiting for"
#define D_START_SIGNAL_LOW "düşük sinyal başlat"
#define D_START_SIGNAL_HIGH "yüksek sinyal başlat"
#define D_PULSE "pulse"
#define D_CHECKSUM_FAILURE "Checksum failure"
// xsns_07_sht1x.ino
#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command"
#define D_SHT1X_FOUND "SHT1X found"
// xsns_18_pms5003.ino
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
#define D_PARTICALS_BEYOND "Particals"
// sonoff_template.h
#define D_SENSOR_NONE "None"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
#define D_SENSOR_DS18X20 "DS18x20"
#define D_SENSOR_I2C_SCL "I2C SCL"
#define D_SENSOR_I2C_SDA "I2C SDA"
#define D_SENSOR_WS2812 "WS2812"
#define D_SENSOR_IRSEND "IRsend"
#define D_SENSOR_SWITCH "Switch" // Suffix "1"
#define D_SENSOR_BUTTON "Button" // Suffix "1"
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
#define D_SENSOR_LED "Led" // Suffix "1i"
#define D_SENSOR_PWM "PWM" // Suffix "1"
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1 "SDS0X1"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
#define D_SENSOR_SR04_ECHO "SR04 Ech"
#define D_SENSOR_SDM120_TX "SDM120 Tx"
#define D_SENSOR_SDM120_RX "SDM120 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_KILOOHM "kOhm"
#define D_UNIT_KILOWATTHOUR "kWh"
#define D_UNIT_LUX "lx"
#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3"
#define D_UNIT_MICROMETER "um"
#define D_UNIT_MICROSECOND "us"
#define D_UNIT_MILLIAMPERE "mA"
#define D_UNIT_MILLISECOND "ms"
#define D_UNIT_MINUTE "Min"
#define D_UNIT_PARTS_PER_BILLION "ppb"
#define D_UNIT_PARTS_PER_DECILITER "ppd"
#define D_UNIT_PARTS_PER_MILLION "ppm"
#define D_UNIT_PRESSURE "hPa"
#define D_UNIT_SECOND "sec"
#define D_UNIT_SECTORS "sectors"
#define D_UNIT_VA "VA"
#define D_UNIT_VAR "VAr"
#define D_UNIT_VOLT "V"
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_HERTZ "Hz"
// Log message prefix
#define D_LOG_APPLICATION "APP: " // Application
#define D_LOG_BRIDGE "BRG: " // Bridge
#define D_LOG_CONFIG "CFG: " // Settings
#define D_LOG_COMMAND "CMD: " // Command
#define D_LOG_DEBUG "DBG: " // Debug
#define D_LOG_DHT "DHT: " // DHT sensor
#define D_LOG_DOMOTICZ "DOM: " // Domoticz
#define D_LOG_DSB "DSB: " // DS18xB20 sensor
#define D_LOG_HTTP "HTP: " // HTTP webserver
#define D_LOG_I2C "I2C: " // I2C
#define D_LOG_IRR "IRR: " // Infra Red Received
#define D_LOG_LOG "LOG: " // Logging
#define D_LOG_MODULE "MOD: " // Module
#define D_LOG_MDNS "DNS: " // mDNS
#define D_LOG_MQTT "MQT: " // MQTT
#define D_LOG_OTHER "OTH: " // Other
#define D_LOG_RESULT "RSL: " // Result
#define D_LOG_RFR "RFR: " // RF Received
#define D_LOG_SERIAL "SER: " // Serial
#define D_LOG_SHT1 "SHT: " // SHT1x sensor
#define D_LOG_UPLOAD "UPL: " // Upload
#define D_LOG_UPNP "UPP: " // UPnP
#define D_LOG_WIFI "WIF: " // Wifi
#endif // _LANGUAGE_TR_TR_H_

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "Підтвердити перезавантаження"
#define D_CONFIGURE_MODULE "Конфігурація модуля"
#define D_CONFIGURE_MCP230XX "Конфігурація MCP230xx"
#define D_CONFIGURE_WIFI "Конфігурація WiFi"
#define D_CONFIGURE_MQTT "Конфігурація MQTT"
#define D_CONFIGURE_DOMOTICZ "Конфігурація Domoticz"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "确认重启"
#define D_CONFIGURE_MODULE "模块设置"
#define D_CONFIGURE_MCP230XX "MCP230xx设置"
#define D_CONFIGURE_WIFI "WiFi设置"
#define D_CONFIGURE_MQTT "MQTT设置"
#define D_CONFIGURE_DOMOTICZ "Domoticz设置"

View File

@ -227,7 +227,6 @@
#define D_CONFIRM_RESTART "確認重啟"
#define D_CONFIGURE_MODULE "模塊設置"
#define D_CONFIGURE_MCP230XX "MCP230xx設置"
#define D_CONFIGURE_WIFI "WiFi設置"
#define D_CONFIGURE_MQTT "MQTT設置"
#define D_CONFIGURE_DOMOTICZ "Domoticz設置"

View File

@ -48,7 +48,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t not_power_linked : 1; // bit 20 (v5.11.1f)
uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i)
uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f)
uint32_t rules_enabled : 1; // bit 23 (v5.12.0j) - free since v5.14.0b
uint32_t mqtt_serial_raw : 1; // bit 23 (v6.1.1c)
uint32_t rules_once : 1; // bit 24 (v5.12.0k) - free since v5.14.0b
uint32_t knx_enabled : 1; // bit 25 (v5.12.0l) KNX
uint32_t device_index_enable : 1; // bit 26 (v5.13.1a)
@ -114,8 +114,7 @@ typedef union {
uint32_t spare10 : 1;
uint32_t spare11 : 1;
uint32_t spare12 : 1;
uint32_t spare13 : 1;
uint32_t spare14 : 1;
uint32_t axis_resolution : 2;
uint32_t current_resolution : 2;
uint32_t voltage_resolution : 2;
uint32_t wattage_resolution : 2;
@ -155,7 +154,7 @@ typedef union {
typedef union {
uint8_t data;
struct {
uint8_t pinmode : 3; // Enable INPUT
uint8_t pinmode : 3; // Enable INPUT
uint8_t pullup : 1; // Enable internal weak pull-up resistor
uint8_t b4 : 1;
uint8_t b5 : 1;
@ -369,7 +368,7 @@ struct XDRVMAILBOX {
char *data;
} XdrvMailbox;
#define MAX_RULES_FLAG 5 // Number of bits used in RulesBitfield (tricky I know...)
#define MAX_RULES_FLAG 7 // Number of bits used in RulesBitfield (tricky I know...)
typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull...
uint16_t data; // Allow bit manipulation
struct {
@ -378,8 +377,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint16_t time_set : 1;
uint16_t mqtt_connected : 1;
uint16_t mqtt_disconnected : 1;
uint16_t spare05 : 1;
uint16_t spare06 : 1;
uint16_t wifi_connected : 1;
uint16_t wifi_disconnected : 1;
uint16_t spare07 : 1;
uint16_t spare08 : 1;
uint16_t spare09 : 1;

View File

@ -286,8 +286,10 @@ void SettingsLoad()
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag);
AddLog(LOG_LEVEL_DEBUG);
#ifndef BE_MINIMAL
if (bad_crc || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { SettingsDefault(); }
settings_crc = GetSettingsCrc();
#endif // BE_MINIMAL
RtcSettingsLoad();
}
@ -756,7 +758,7 @@ void SettingsDelta()
}
if (Settings.version < 0x050E0002) {
for (byte i = 1; i < MAX_RULE_SETS; i++) { Settings.rules[i][0] = '\0'; }
Settings.rule_enabled = Settings.flag.rules_enabled;
Settings.rule_enabled = Settings.flag.mqtt_serial_raw;
Settings.rule_once = Settings.flag.rules_once;
}
if (Settings.version < 0x06000000) {
@ -778,7 +780,7 @@ void SettingsDelta()
}
}
if (Settings.version < 0x06000003) {
Settings.flag.rules_enabled = 0;
Settings.flag.mqtt_serial_raw = 0;
Settings.flag.rules_once = 0;
Settings.flag3.data = 0;
}

View File

@ -68,6 +68,7 @@ typedef unsigned long power_t; // Power (Relay) type
#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A
#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection
#define GLOBAL_VALUES_VALID 300 // Max number of seconds to keep last received values
#define APP_POWER 0 // Default saved power state Off
#define WS2812_MAX_LEDS 512 // Max number of LEDs

View File

@ -188,8 +188,9 @@ uint8_t ntp_force_sync = 0; // Force NTP sync
StateBitfield global_state;
RulesBitfield rules_flag;
uint8_t glob_humidity = 0;
sint16_t glob_temperature = -9999;
uint32_t global_update = 0;
float global_temperature = 0;
float global_humidity = 0;
char my_version[33]; // Composed version string
char my_hostname[33]; // Composed Wifi hostname
@ -677,6 +678,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
case 7: // mqtt_switch_retain (CMND_SWITCHRETAIN)
case 9: // mqtt_sensor_retain (CMND_SENSORRETAIN)
case 22: // mqtt_serial (SerialSend and SerialLog)
case 23: // mqtt_serial_raw (SerialSend)
case 25: // knx_enabled (Web config)
case 27: // knx_enable_enhancement (Web config)
ptype = 99; // Command Error
@ -914,15 +916,18 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200);
}
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 3)) {
else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 4)) {
SetSeriallog(LOG_LEVEL_NONE);
Settings.flag.mqtt_serial = 1;
Settings.flag.mqtt_serial_raw = (4 == index) ? 1 : 0;
if (data_len > 0) {
if (1 == index) {
Serial.printf("%s\n", dataBuf);
}
else if (2 == index) {
Serial.printf("%s", dataBuf);
else if (2 == index || 4 == index) {
for (int i = 0; i < data_len; i++) {
Serial.write(dataBuf[i]);
}
}
else if (3 == index) {
uint16_t dat_len = data_len;
@ -1116,7 +1121,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len)
ntp_force_sync = 1;
}
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d\"}}"),
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"),
command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]);
}
else if (CMND_ALTITUDE == command_code) {
@ -1370,8 +1375,8 @@ void PublishStatus(uint8_t payload)
}
if ((0 == payload) || (3 == payload)) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_CMND_SETOPTION "\":[\"%08X\",\"%08X\"]}}"),
Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag.data, Settings.flag2.data);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_CMND_SETOPTION "\":[\"%08X\",\"%08X\",\"%08X\"]}}"),
Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag.data, Settings.flag2.data, Settings.flag3.data);
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3"));
}
@ -1544,6 +1549,8 @@ void PerformEverySecond()
}
}
ResetGlobalValues();
if (Settings.tele_period) {
tele_period++;
if (tele_period == Settings.tele_period -1) {
@ -2173,7 +2180,7 @@ void SerialInput()
#endif // USE_ENERGY_SENSOR
/*-------------------------------------------------------------------------------------------*/
if (serial_in_byte > 127) { // binary data...
if (serial_in_byte > 127 && !Settings.flag.mqtt_serial_raw) { // binary data...
serial_in_byte_counter = 0;
Serial.flush();
return;
@ -2187,8 +2194,9 @@ void SerialInput()
}
}
} else {
if (serial_in_byte) {
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) && (serial_in_byte != Settings.serial_delimiter)) { // add char to string if it still fits
if (serial_in_byte || Settings.flag.mqtt_serial_raw) {
if ((serial_in_byte_counter < INPUT_BUFFER_SIZE -1) &&
((serial_in_byte != Settings.serial_delimiter) || Settings.flag.mqtt_serial_raw)) { // add char to string if it still fits
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
serial_polling_window = millis();
} else {
@ -2228,7 +2236,15 @@ void SerialInput()
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
if (!Settings.flag.mqtt_serial_raw) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
} else {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\""));
for (int i = 0; i < serial_in_byte_counter; i++) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data);
}
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
// XdrvRulesProcess();
serial_in_byte_counter = 0;

View File

@ -414,6 +414,22 @@ char TempUnit()
return (Settings.flag.temperature_conversion) ? 'F' : 'C';
}
void SetGlobalValues(float temperature, float humidity)
{
global_update = uptime;
global_temperature = temperature;
global_humidity = humidity;
}
void ResetGlobalValues()
{
if ((uptime - global_update) > GLOBAL_VALUES_VALID) { // Reset after 5 minutes
global_update = 0;
global_temperature = 0;
global_humidity = 0;
}
}
double FastPrecisePow(double a, double b)
{
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
@ -903,6 +919,19 @@ void GetFeatures()
/*********************************************************************************************/
feature_sns2 = 0x00000000;
#ifdef USE_MCP230xx
feature_sns2 |= 0x00000001; // xsns_29_mcp230xx.ino
#endif
#ifdef USE_MPR121
feature_sns2 |= 0x00000002; // xsns_30_mpr121.ino
#endif
#ifdef USE_CCS811
feature_sns2 |= 0x00000004; // xsns_31_ccs811.ino
#endif
#ifdef USE_MPU6050
feature_sns2 |= 0x00000008; // xsns_32_mpu6050.ino
#endif
}
/*********************************************************************************************\
@ -1080,10 +1109,22 @@ void WifiBegin(uint8_t flag)
AddLog(LOG_LEVEL_INFO);
}
void WifiState(uint8_t state)
{
if (state == global_state.wifi_down) {
if (state) {
rules_flag.wifi_connected = 1;
} else {
rules_flag.wifi_disconnected = 1;
}
}
global_state.wifi_down = state ^1;
}
void WifiCheckIp()
{
if ((WL_CONNECTED == WiFi.status()) && (static_cast<uint32_t>(WiFi.localIP()) != 0)) {
global_state.wifi_down = 0;
WifiState(1);
wifi_counter = WIFI_CHECK_SEC;
wifi_retry = wifi_retry_init;
AddLog_P((wifi_status != WL_CONNECTED) ? LOG_LEVEL_INFO : LOG_LEVEL_DEBUG_MORE, S_LOG_WIFI, PSTR(D_CONNECTED));
@ -1095,7 +1136,7 @@ void WifiCheckIp()
}
wifi_status = WL_CONNECTED;
} else {
global_state.wifi_down = 1;
WifiState(0);
uint8_t wifi_config_tool = Settings.sta_config;
wifi_status = WiFi.status();
switch (wifi_status) {
@ -1206,7 +1247,7 @@ void WifiCheck(uint8_t param)
WifiCheckIp();
}
if ((WL_CONNECTED == WiFi.status()) && (static_cast<uint32_t>(WiFi.localIP()) != 0) && !wifi_config_type) {
global_state.wifi_down = 0;
WifiState(1);
#ifdef BE_MINIMAL
if (1 == RtcSettings.ota_loader) {
RtcSettings.ota_loader = 0;
@ -1242,7 +1283,7 @@ void WifiCheck(uint8_t param)
}
#endif // USE_KNX
} else {
global_state.wifi_down = 1;
WifiState(0);
#if defined(USE_WEBSERVER) && defined(USE_EMULATION)
UdpDisconnect();
#endif // USE_EMULATION

View File

@ -199,6 +199,7 @@
//#define MY_LANGUAGE pt-BR // Portuguese in Brazil
//#define MY_LANGUAGE pt-PT // Portuguese in Portugal
//#define MY_LANGUAGE ru-RU // Russian in Russia
//#define MY_LANGUAGE tr-TR // Turkish in Turkey
//#define MY_LANGUAGE uk-UK // Ukrainian in Ukrain
//#define MY_LANGUAGE zh-CN // Chinese (Simplified) in China
//#define MY_LANGUAGE zh-TW // Chinese (Traditional) in Taiwan
@ -274,7 +275,7 @@
#define USE_SHT // Enable SHT1X sensor (+1k4 code)
#define USE_HTU // Enable HTU21/SI7013/SI7020/SI7021 sensor (I2C address 0x40) (+1k5 code)
#define USE_BMP // Enable BMP085/BMP180/BMP280/BME280 sensor (I2C address 0x76 or 0x77) (+4k code)
#define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code)
// #define USE_BME680 // Enable support for BME680 sensor using Bosch BME680 library (+4k code)
#define USE_BH1750 // Enable BH1750 sensor (I2C address 0x23 or 0x5C) (+0k5 code)
// #define USE_VEML6070 // Enable VEML6070 sensor (I2C addresses 0x38 and 0x39) (+0k5 code)
// #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
@ -291,6 +292,7 @@
// #define USE_MCP230xx // Enable MCP23008/MCP23017 for GP INPUT ONLY (I2C addresses 0x20 - 0x27) providing command Sensor29 for configuration (+2k2 code)
// #define USE_MPR121 // Enable MPR121 controller (I2C addresses 0x5A, 0x5B, 0x5C and 0x5D) in input mode for touch buttons (+1k3 code)
// #define USE_CCS811 // Enable CCS811 sensor (I2C address 0x5A) (+2k2 code)
// #define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code)
#endif // USE_I2C
// -- SPI sensors ---------------------------------

View File

@ -92,7 +92,9 @@ void MqttSubscribeLib(char *topic)
bool MqttPublishLib(const char* topic, boolean retained)
{
return MqttClient.publish(topic, mqtt_data, retained);
bool result = MqttClient.publish(topic, mqtt_data, retained);
yield(); // #3313
return result;
}
void MqttLoop()

View File

@ -29,6 +29,8 @@
uint8_t *efm8bb1_update = NULL;
#endif // USE_RF_FLASH
#define D_TASMOTA_TOKEN "Tasmota-Token"
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 };
const char HTTP_HEAD[] PROGMEM =
@ -39,7 +41,7 @@ const char HTTP_HEAD[] PROGMEM =
"<title>{h} - {v}</title>"
"<script>"
"var cn,x,lt;"
"var cn,x,lt,to,tp,pc='';"
"cn=180;"
"x=null;" // Allow for abortion
"function eb(s){"
@ -56,13 +58,17 @@ const char HTTP_HEAD[] PROGMEM =
"eb('s1').value=l.innerText||l.textContent;"
"eb('p1').focus();"
"}"
"function la(p){"
"var a='';"
"if(la.arguments.length==1){"
"a=p;"
"clearTimeout(lt);"
"function lx(){"
"if(to==1){"
"if(tp<30){"
"tp++;"
"lt=setTimeout(lx,33);" // Wait for token from server
"}else{"
"lt=setTimeout(la,1355);" // Discard action and retry
"}"
"return;"
"}"
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
"x=new XMLHttpRequest();"
"x.onreadystatechange=function(){"
"if(x.readyState==4&&x.status==200){"
@ -70,15 +76,32 @@ const char HTTP_HEAD[] PROGMEM =
"eb('l1').innerHTML=s;"
"}"
"};"
"x.open('GET','ay'+a,true);"
"x.send();"
"lt=setTimeout(la,2345);"
"x.open('GET','ay'+pc,true);" // Async request
"x.setRequestHeader('" D_TASMOTA_TOKEN "',to);"
"x.send();" // Perform command if available and get updated information
"pc='';"
"lt=setTimeout(la,2345-(tp*33));"
"}"
"function la(p){"
"if(la.arguments.length==1){"
"pc='?'+p;"
"clearTimeout(lt);"
"}else{pc='';}"
"to=1;tp=0;"
"if(x!=null){x.abort();}" // Abort if no response within 2 seconds (happens on restart 1)
"x=new XMLHttpRequest();"
"x.onreadystatechange=function(){"
"if(x.readyState==4&&x.status==200){to=x.getResponseHeader('" D_TASMOTA_TOKEN "');}else{to=1;}"
"};"
"x.open('GET','az',true);" // Async request
"x.send();" // Get token from server
"lx();"
"}"
"function lb(p){"
"la('?d='+p);"
"la('d='+p);"
"}"
"function lc(p){"
"la('?t='+p);"
"la('c='+p);"
"}";
const char HTTP_HEAD_STYLE[] PROGMEM =
@ -315,7 +338,7 @@ const char HTTP_END[] PROGMEM =
"</body>"
"</html>";
const char HTTP_DEVICE_CONTROL[] PROGMEM = "<td style='width:%d%%'><button onclick='la(\"?o=%d\");'>%s%s</button></td>";
const char HTTP_DEVICE_CONTROL[] PROGMEM = "<td style='width:%d%%'><button onclick='la(\"o=%d\");'>%s%s</button></td>";
const char HTTP_DEVICE_STATE[] PROGMEM = "%s<td style='width:%d{c}%s;font-size:%dpx'>%s</div></td>"; // {c} = %'><div style='text-align:center;font-weight:
const char HDR_CTYPE_PLAIN[] PROGMEM = "text/plain";
@ -324,6 +347,8 @@ const char HDR_CTYPE_XML[] PROGMEM = "text/xml";
const char HDR_CTYPE_JSON[] PROGMEM = "application/json";
const char HDR_CTYPE_STREAM[] PROGMEM = "application/octet-stream";
const char HDR_TASMOTA_TOKEN[] PROGMEM = D_TASMOTA_TOKEN;
#define DNS_PORT 53
enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER};
@ -339,6 +364,7 @@ uint8_t upload_progress_dot_count;
uint8_t config_block_count = 0;
uint8_t config_xor_on = 0;
uint8_t config_xor_on_set = CONFIG_FILE_XOR;
long ajax_token = 1;
// Helper function to avoid code duplication (saves 4k Flash)
static void WebGetArg(const char* arg, char* out, size_t max)
@ -375,6 +401,7 @@ void StartWebserver(int type, IPAddress ipweb)
WebServer->on("/cs", HandleConsole);
WebServer->on("/ax", HandleAjaxConsoleRefresh);
WebServer->on("/ay", HandleAjaxStatusRefresh);
WebServer->on("/az", HandleToken);
WebServer->on("/u2", HTTP_OPTIONS, HandlePreflightRequest);
WebServer->on("/cm", HandleHttpCommand);
WebServer->on("/rb", HandleRestart);
@ -590,7 +617,7 @@ void HandleRoot()
if (idx > 0) { page += F("</tr><tr>"); }
for (byte j = 0; j < 4; j++) {
idx++;
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:25%'><button onclick='la(\"?k=%d\");'>%d</button></td>"), idx, idx);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<td style='width:25%'><button onclick='la(\"k=%d\");'>%d</button></td>"), idx, idx);
page += mqtt_data;
}
}
@ -605,11 +632,34 @@ void HandleRoot()
}
}
void HandleToken()
{
char token[11];
ajax_token = random(2, 0x7FFFFFFF);
snprintf_P(token, sizeof(token), PSTR("%u"), ajax_token);
SetHeader();
WebServer->sendHeader(FPSTR(HDR_TASMOTA_TOKEN), token);
snprintf_P(token, sizeof(token), PSTR("%u"), random(0x7FFFFFFF));
WebServer->send(200, FPSTR(HDR_CTYPE_HTML), token);
const char* header_key[] = { D_TASMOTA_TOKEN };
WebServer->collectHeaders(header_key, 1);
}
void HandleAjaxStatusRefresh()
{
char svalue[80];
char tmp[100];
if (WebServer->header(FPSTR(HDR_TASMOTA_TOKEN)).toInt() != ajax_token) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND));
SetHeader();
WebServer->send(404, FPSTR(HDR_CTYPE_PLAIN), mqtt_data);
return;
}
ajax_token = 1;
WebGetArg("o", tmp, sizeof(tmp));
if (strlen(tmp)) {
ShowWebSource(SRC_WEBGUI);
@ -630,7 +680,7 @@ void HandleAjaxStatusRefresh()
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_DIMMER " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
}
WebGetArg("t", tmp, sizeof(tmp));
WebGetArg("c", tmp, sizeof(tmp));
if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
@ -1944,7 +1994,7 @@ int WebSend(char *buffer)
/*********************************************************************************************/
enum WebCommands { CMND_WEBSERVER, CMND_WEBPASSWORD, CMND_WEBLOG, CMND_WEBSEND, CMND_EMULATION };
const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ;
const char kWebCommands[] PROGMEM = D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBSEND "|" D_CMND_EMULATION ;
const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ;
bool WebCommand()

View File

@ -432,6 +432,8 @@ void RulesEvery50ms()
case 2: snprintf_P(json_event, sizeof(json_event), PSTR("{\"Time\":{\"Set\":%d}}"), GetMinutesPastMidnight()); break;
case 3: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(json_event)); break;
case 4: strncpy_P(json_event, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
case 5: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Connected\":1}}"), sizeof(json_event)); break;
case 6: strncpy_P(json_event, PSTR("{\"WIFI\":{\"Disconnected\":1}}"), sizeof(json_event)); break;
}
if (json_event[0]) {
RulesProcessEvent(json_event);
@ -525,7 +527,18 @@ boolean RulesCommand()
break;
}
} else {
strlcpy(Settings.rules[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1]));
int offset = 0;
if ('+' == XdrvMailbox.data[0]) {
offset = strlen(Settings.rules[index -1]);
if (XdrvMailbox.data_len < (sizeof(Settings.rules[index -1]) - offset -1)) { // Check free space
XdrvMailbox.data[0] = ' '; // Remove + and make sure at least one space is inserted
} else {
offset = -1; // Not enough space so skip it
}
}
if (offset != -1) {
strlcpy(Settings.rules[index -1] + offset, ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1]));
}
}
rules_triggers[index -1] = 0; // Reset once flag
}

View File

@ -147,6 +147,8 @@ boolean ShtRead()
sht_humidity = (sht_temperature - 25) * (t1 + t2 * humRaw) + rhLinear;
sht_temperature = ConvertTemp(sht_temperature);
SetGlobalValues(sht_temperature, sht_humidity);
sht_valid = SENSOR_MAX_MISS;
return true;
}

View File

@ -185,6 +185,8 @@ boolean HtuRead()
htu_humidity = (-0.15) * (25 - htu_temperature) + htu_humidity;
}
SetGlobalValues(htu_temperature, htu_humidity);
htu_valid = SENSOR_MAX_MISS;
return true;
}

View File

@ -460,8 +460,7 @@ void BmpRead()
}
if (bmp_temperature != 0.0) { bmp_temperature = ConvertTemp(bmp_temperature); }
glob_humidity = bmp_humidity;
glob_temperature = bmp_temperature;
SetGlobalValues(bmp_temperature, bmp_humidity);
}
void BmpEverySecond()

View File

@ -102,10 +102,7 @@ void Sht3xShow(boolean json)
for (byte i = 0; i < sht3x_count; i++) {
if (Sht3xRead(t, h, sht3x_sensors[i].address)) {
if (0 == i) {
glob_humidity = h;
glob_temperature = t;
}
if (0 == i) { SetGlobalValues(t, h); }
dtostrfd(t, Settings.flag2.temperature_resolution, temperature);
dtostrfd(h, Settings.flag2.humidity_resolution, humidity);

View File

@ -58,61 +58,38 @@ uint8_t mcp230xx_addresses[] = { MCP230xx_ADDRESS1, MCP230xx_ADDRESS2, MCP230xx_
uint8_t mcp230xx_pincount = 0;
uint8_t mcp230xx_int_en = 0;
const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29\":{\"D\":%i,\"MODE\":%i,\"PULL-UP\":%i}}";
const char MCP230XX_SENSOR_RESPONSE[] PROGMEM = "{\"Sensor29\":{\"D\":%i,\"MODE\":%i,\"PULL-UP\":%i,\"STATE\":%i}}";
uint8_t MCP230xx_readGPIO(uint8_t port) {
return I2cRead8(mcp230xx_address, MCP230xx_GPIO + port);
}
void MCP230xx_ApplySettings(void) {
uint8_t reg_gppu = 0;
uint8_t reg_gpinten = 0;
uint8_t reg_iodir = 0xFF;
uint8_t int_en = 0;
for (uint8_t idx = 0; idx < 8; idx++) {
switch (Settings.mcp230xx_config[idx].pinmode) {
case 0 ... 1:
reg_iodir |= (1 << idx);
break;
case 2 ... 4:
reg_iodir |= (1 << idx);
reg_gpinten |= (1 << idx);
int_en=1;
break;
default:
break;
}
if (Settings.mcp230xx_config[idx].pullup) {
reg_gppu |= (1 << idx);
}
}
I2cWrite8(mcp230xx_address, MCP230xx_GPPU, reg_gppu);
I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN, reg_gpinten);
I2cWrite8(mcp230xx_address, MCP230xx_IODIR, reg_iodir);
if (mcp230xx_type == 2) { // We have a MCP23017
reg_gppu = 0;
reg_gpinten = 0;
reg_iodir = 0xFF;
for (uint8_t idx = 8; idx < 16; idx++) {
switch (Settings.mcp230xx_config[idx].pinmode) {
for (uint8_t mcp230xx_port=0;mcp230xx_port<mcp230xx_type;mcp230xx_port++) {
uint8_t reg_gppu = 0;
uint8_t reg_gpinten = 0;
uint8_t reg_iodir = 0xFF;
for (uint8_t idx = 0; idx < 8; idx++) {
switch (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pinmode) {
case 0 ... 1:
reg_iodir |= (1 << idx - 8);
reg_iodir |= (1 << idx);
break;
case 2 ... 4:
reg_iodir |= (1 << idx - 8);
reg_gpinten |= (1 << idx - 8);
reg_iodir |= (1 << idx);
reg_gpinten |= (1 << idx);
int_en=1;
break;
default:
break;
}
if (Settings.mcp230xx_config[idx].pullup) {
reg_gppu |= (1 << idx - 8);
if (Settings.mcp230xx_config[idx+(mcp230xx_port*8)].pullup) {
reg_gppu |= (1 << idx);
}
}
I2cWrite8(mcp230xx_address, MCP230xx_GPPU + 1, reg_gppu);
I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN + 1, reg_gpinten);
I2cWrite8(mcp230xx_address, MCP230xx_IODIR + 1, reg_iodir);
I2cWrite8(mcp230xx_address, MCP230xx_GPPU+mcp230xx_port, reg_gppu);
I2cWrite8(mcp230xx_address, MCP230xx_GPINTEN+mcp230xx_port, reg_gpinten);
I2cWrite8(mcp230xx_address, MCP230xx_IODIR+mcp230xx_port, reg_iodir);
}
mcp230xx_int_en=int_en;
}
@ -161,48 +138,15 @@ bool MCP230xx_CheckForInterrupt(void) {
uint8_t intf;
uint8_t mcp230xx_intcap = 0;
uint8_t report_int;
if (I2cValidRead8(&intf, mcp230xx_address, MCP230xx_INTF)) {
if (intf > 0) {
if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP)) {
for (uint8_t intp = 0; intp < 8; intp++) {
if ((intf >> intp) & 0x01) { // we know which pin caused interrupt
report_int = 0;
if (Settings.mcp230xx_config[intp].pinmode > 1) {
switch (Settings.mcp230xx_config[intp].pinmode) {
case 2:
report_int = 1;
break;
case 3:
if (((mcp230xx_intcap >> intp) & 0x01) == 0) report_int = 1; // Int on LOW
break;
case 4:
if (((mcp230xx_intcap >> intp) & 0x01) == 1) report_int = 1; // Int on HIGH
break;
default:
break;
}
if (report_int) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"Pin\":\"D%i\", \"State\":%i}"), mqtt_data, intp, ((mcp230xx_intcap >> intp) & 0x01));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
}
}
}
}
}
}
}
if (mcp230xx_type == 2) { // We have a MCP23017 so we need to check the other 8 bits also
if (I2cValidRead8(&intf, mcp230xx_address, MCP230xx_INTF+1)) {
for (uint8_t mcp230xx_port=0;mcp230xx_port<mcp230xx_type;mcp230xx_port++) {
if (I2cValidRead8(&intf,mcp230xx_address,MCP230xx_INTF+mcp230xx_port)) {
if (intf > 0) {
if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP+1)) {
if (I2cValidRead8(&mcp230xx_intcap, mcp230xx_address, MCP230xx_INTCAP+mcp230xx_port)) {
for (uint8_t intp = 0; intp < 8; intp++) {
if ((intf >> intp) & 0x01) { // we know which pin caused interrupt
report_int = 0;
if (Settings.mcp230xx_config[intp+8].pinmode > 1) { // change on INT
switch (Settings.mcp230xx_config[intp+8].pinmode) {
if (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode > 1) {
switch (Settings.mcp230xx_config[intp+(mcp230xx_port*8)].pinmode) {
case 2:
report_int = 1;
break;
@ -215,12 +159,12 @@ bool MCP230xx_CheckForInterrupt(void) {
default:
break;
}
}
if (report_int) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"Pin\":\"D%i\", \"State\":%i}"), mqtt_data, intp+8, ((mcp230xx_intcap >> intp) & 0x01));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
if (report_int) {
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01));
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data);
}
}
}
}
@ -234,16 +178,16 @@ void MCP230xx_Show(boolean json)
{
if (mcp230xx_type) {
if (json) {
if (mcp230xx_type == 1) {
if (mcp230xx_type > 0) { // we have at least 8 pins
uint8_t gpio = MCP230xx_readGPIO(0);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP23008\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i}"),
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"),
mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1);
}
if (mcp230xx_type == 2) {
uint8_t gpio1 = MCP230xx_readGPIO(0);
uint8_t gpio2 = MCP230xx_readGPIO(1);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP23017\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i,\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i}"),
mqtt_data, (gpio1>>0)&1,(gpio1>>1)&1,(gpio1>>2)&1,(gpio1>>3)&1,(gpio1>>4)&1,(gpio1>>5)&1,(gpio1>>6)&1,(gpio1>>7)&1,(gpio2>>0)&1,(gpio2>>1)&1,(gpio2>>2)&1,(gpio2>>3)&1,(gpio2>>4)&1,(gpio2>>5)&1,(gpio2>>6)&1,(gpio2>>7)&1);
if (mcp230xx_type == 2) {
gpio = MCP230xx_readGPIO(1);
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"),
mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1);
}
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"),mqtt_data,"}");
}
}
}
@ -265,7 +209,7 @@ bool MCP230xx_Command(void) {
Settings.mcp230xx_config[pinx].b7=0;
}
MCP230xx_ApplySettings();
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,99,99);
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,99,99,99);
return serviced;
}
_a = data.indexOf(",");
@ -273,7 +217,10 @@ bool MCP230xx_Command(void) {
if (pin < mcp230xx_pincount) {
String cmnd = data.substring(_a+1);
if (cmnd == "?") {
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,Settings.mcp230xx_config[pin].pullup);
uint8_t port = 0;
if (pin > 7) port = 1;
uint8_t portdata = MCP230xx_readGPIO(port);
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,Settings.mcp230xx_config[pin].pullup,portdata>>(pin-(port*8))&1);
return serviced;
}
}
@ -286,7 +233,10 @@ bool MCP230xx_Command(void) {
Settings.mcp230xx_config[pin].pinmode=pinmode;
Settings.mcp230xx_config[pin].pullup=pullup;
MCP230xx_ApplySettings();
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pullup);
uint8_t port = 0;
if (pin > 7) port = 1;
uint8_t portdata = MCP230xx_readGPIO(port);
snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pullup,portdata>>(pin-(port*8))&1);
} else {
serviced = false;
}
@ -334,3 +284,4 @@ boolean Xsns29(byte function)
#endif // USE_MCP230xx
#endif // USE_I2C

View File

@ -62,10 +62,7 @@ void CCS811Update() // Perform every n second
TVOC = ccs.getTVOC();
eCO2 = ccs.geteCO2();
CCS811_ready = 1;
if ((glob_humidity != 0) && (glob_temperature != -9999)) {
double gtmp = glob_temperature * 4;
ccs.setEnvironmentalData(glob_humidity, gtmp / 4);
}
if (global_update) { ccs.setEnvironmentalData((uint8_t)global_humidity, global_temperature); }
ecnt = 0;
}
} else {

207
sonoff/xsns_32_mpu6050.ino Normal file
View File

@ -0,0 +1,207 @@
/*
xsns_32_MPU_6050.ino - MPU_6050 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
/*********************************************************************************************\
* MPU_6050 3 axis gyroscope and temperature sensor
*
* Source: Oliver Welter, with special thanks to Jeff Rowberg
*
* I2C Address: 0x68 or 0x69 with AD0 HIGH
\*********************************************************************************************/
#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()
{
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()
{
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
\*********************************************************************************************/
#define XSNS_32
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

View File

@ -48,11 +48,11 @@ from StringIO import StringIO
a_on_off = ["OFF","ON "]
a_setoption = [
a_setoption = [[
"Save power state and use after restart",
"Restrict button actions to single, double and hold",
"Show value units in JSON messages",
"MQTT",
"MQTT enabled",
"Respond as Command topic instead of RESULT",
"MQTT retain on Power",
"MQTT retain on Button",
@ -72,15 +72,26 @@ a_setoption = [
"Do not control Power with Dimmer",
"Energy monitoring while powered off",
"MQTT serial",
"Rules until 5.14.0b",
"MQTT serial binary",
"Rules once mode until 5.14.0b",
"KNX",
"KNX enabled",
"Use Power device index on single relay devices",
"KNX enhancement",
"RF receive decimal",
"IR receive decimal",
"Enforce HASS light group",
"Do not show Wifi and Mqtt state using Led"]
"Do not show Wifi and Mqtt state using Led"
],[
"Timers enabled",
"","","",
"","","","",
"","","","",
"","","","",
"","","","",
"","","","",
"","","","",
"","","",""
]]
a_features = [[
"","","USE_I2C","USE_SPI",
@ -110,7 +121,7 @@ a_features = [[
"USE_SGP30","USE_SR04","USE_SDM120","USE_SI1145",
"USE_SDM630","USE_LM75AD","USE_APDS9960","USE_TM1638"
],[
"","","","",
"USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050",
"","","","",
"","","","",
"","","","",
@ -144,6 +155,8 @@ else:
fp.close()
def StartDecode():
print ("\n*** decode-status.py v20180730 by Theo Arends ***")
# print("Decoding\n{}".format(obj))
if ("StatusSNS" in obj):
@ -152,17 +165,29 @@ def StartDecode():
if ("Status" in obj):
if ("FriendlyName" in obj["Status"]):
print("\nDecoding information for device {}{}".format(obj["Status"]["FriendlyName"][0], time))
print("Decoding information for device {}{}".format(obj["Status"]["FriendlyName"][0], time))
if ("StatusLOG" in obj):
if ("SetOption" in obj["StatusLOG"]):
options = []
option = obj["StatusLOG"]["SetOption"][0]
i_option = int(option,16)
for i in range(len(a_setoption)):
if (a_setoption[i]):
state = (i_option >> i) & 1
options.append(str("{0:2d} ({1}) {2}".format(i, a_on_off[state], a_setoption[i])))
o = 0
p = 0
r = 1
if (len(obj["StatusLOG"]["SetOption"]) == 3):
r = 2
for f in range(r):
if (f == 1):
o = 2
p = 50
option = obj["StatusLOG"]["SetOption"][o]
i_option = int(option,16)
for i in range(len(a_setoption[f])):
if (a_setoption[f][i]):
state = (i_option >> i) & 1
options.append(str("{0:2d} ({1}) {2}".format(i + p, a_on_off[state], a_setoption[f][i])))
print("\nOptions")
for i in range(len(options)):