mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 02:36:35 +00:00
Add support for MPU6686 on primary or secondary I2C bus
This commit is contained in:
parent
3555b9e5f9
commit
95e696075e
@ -18,6 +18,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- ESP32 Extent BLE (#11212)
|
- ESP32 Extent BLE (#11212)
|
||||||
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
- ESP32 support for WS2812 hardware driver via RMT or I2S
|
||||||
- ESP32 support for secondary I2C controller
|
- ESP32 support for secondary I2C controller
|
||||||
|
- Add support for MPU6686 on primary or secondary I2C bus
|
||||||
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -91,3 +91,4 @@ Index | Define | Driver | Device | Address(es) | Description
|
|||||||
55 | USE_EZOPMP | xsns_78 | EZOPMP | 0x61 - 0x70 | Peristaltic Pump
|
55 | USE_EZOPMP | xsns_78 | EZOPMP | 0x61 - 0x70 | Peristaltic Pump
|
||||||
56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor
|
56 | USE_SEESAW_SOIL | xsns_81 | SEESOIL | 0x36 - 0x39 | Adafruit seesaw soil moisture sensor
|
||||||
57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor
|
57 | USE_TOF10120 | xsns_84 | TOF10120 | 0x52 | Time-of-flight (ToF) distance sensor
|
||||||
|
58 | USE_MPU6886 | xsns_85 | MPU6886 | 0x68 | MPU6886 M5Stack
|
9
lib/lib_i2c/MFRC522_I2C/library.properties
Normal file
9
lib/lib_i2c/MFRC522_I2C/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=MFRC522_I2C
|
||||||
|
version=
|
||||||
|
author=AROZCAN, COOQROBOT
|
||||||
|
maintainer=
|
||||||
|
sentence=I2C port of MFRC522 SPI
|
||||||
|
paragraph=Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS I2C, Based on ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI Library BY COOQROBOT.
|
||||||
|
category=Communication
|
||||||
|
url=https://github.com/m5stack/M5StickC/blob/master/examples/Unit/RFID/
|
||||||
|
architectures=esp8266,esp32
|
1752
lib/lib_i2c/MFRC522_I2C/src/MFRC522_I2C.cpp
Normal file
1752
lib/lib_i2c/MFRC522_I2C/src/MFRC522_I2C.cpp
Normal file
File diff suppressed because it is too large
Load Diff
407
lib/lib_i2c/MFRC522_I2C/src/MFRC522_I2C.h
Normal file
407
lib/lib_i2c/MFRC522_I2C/src/MFRC522_I2C.h
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
/**
|
||||||
|
* MFRC522_I2C.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS I2C BY AROZCAN
|
||||||
|
* MFRC522_I2C.h - Based on ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI Library BY COOQROBOT.
|
||||||
|
* Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
|
||||||
|
* Created by Miguel Balboa (circuitito.com), Jan, 2012.
|
||||||
|
* Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
|
||||||
|
* Extended by Tom Clement with functionality to write to sector 0 of UID changeable Mifare cards.
|
||||||
|
* Extended by Ahmet Remzi Ozcan with I2C functionality.
|
||||||
|
* Author: arozcan @ https://github.com/arozcan/MFRC522-I2C-Library
|
||||||
|
* Released into the public domain.
|
||||||
|
*
|
||||||
|
* Please read this file for an overview and then MFRC522.cpp for comments on the specific functions.
|
||||||
|
* Search for "mf-rc522" on ebay.com to purchase the MF-RC522 board.
|
||||||
|
*
|
||||||
|
* There are three hardware components involved:
|
||||||
|
* 1) The micro controller: An Arduino
|
||||||
|
* 2) The PCD (short for Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
|
||||||
|
* 3) The PICC (short for Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
|
||||||
|
*
|
||||||
|
* The microcontroller and card reader uses I2C for communication.
|
||||||
|
* The protocol is described in the MFRC522 datasheet: http://www.nxp.com/documents/data_sheet/MFRC522.pdf
|
||||||
|
*
|
||||||
|
* The card reader and the tags communicate using a 13.56MHz electromagnetic field.
|
||||||
|
* The protocol is defined in ISO/IEC 14443-3 Identification cards -- Contactless integrated circuit cards -- Proximity cards -- Part 3: Initialization and anticollision".
|
||||||
|
* A free version of the final draft can be found at http://wg8.de/wg8n1496_17n3613_Ballot_FCD14443-3.pdf
|
||||||
|
* Details are found in chapter 6, Type A – Initialization and anticollision.
|
||||||
|
*
|
||||||
|
* If only the PICC UID is wanted, the above documents has all the needed information.
|
||||||
|
* To read and write from MIFARE PICCs, the MIFARE protocol is used after the PICC has been selected.
|
||||||
|
* The MIFARE Classic chips and protocol is described in the datasheets:
|
||||||
|
* 1K: http://www.nxp.com/documents/data_sheet/MF1S503x.pdf
|
||||||
|
* 4K: http://www.nxp.com/documents/data_sheet/MF1S703x.pdf
|
||||||
|
* Mini: http://www.idcardmarket.com/download/mifare_S20_datasheet.pdf
|
||||||
|
* The MIFARE Ultralight chip and protocol is described in the datasheets:
|
||||||
|
* Ultralight: http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf
|
||||||
|
* Ultralight C: http://www.nxp.com/documents/short_data_sheet/MF0ICU2_SDS.pdf
|
||||||
|
*
|
||||||
|
* MIFARE Classic 1K (MF1S503x):
|
||||||
|
* Has 16 sectors * 4 blocks/sector * 16 bytes/block = 1024 bytes.
|
||||||
|
* The blocks are numbered 0-63.
|
||||||
|
* Block 3 in each sector is the Sector Trailer. See http://www.nxp.com/documents/data_sheet/MF1S503x.pdf sections 8.6 and 8.7:
|
||||||
|
* Bytes 0-5: Key A
|
||||||
|
* Bytes 6-8: Access Bits
|
||||||
|
* Bytes 9: User data
|
||||||
|
* Bytes 10-15: Key B (or user data)
|
||||||
|
* Block 0 is read-only manufacturer data.
|
||||||
|
* To access a block, an authentication using a key from the block's sector must be performed first.
|
||||||
|
* Example: To read from block 10, first authenticate using a key from sector 3 (blocks 8-11).
|
||||||
|
* All keys are set to FFFFFFFFFFFFh at chip delivery.
|
||||||
|
* Warning: Please read section 8.7 "Memory Access". It includes this text: if the PICC detects a format violation the whole sector is irreversibly blocked.
|
||||||
|
* To use a block in "value block" mode (for Increment/Decrement operations) you need to change the sector trailer. Use PICC_SetAccessBits() to calculate the bit patterns.
|
||||||
|
* MIFARE Classic 4K (MF1S703x):
|
||||||
|
* Has (32 sectors * 4 blocks/sector + 8 sectors * 16 blocks/sector) * 16 bytes/block = 4096 bytes.
|
||||||
|
* The blocks are numbered 0-255.
|
||||||
|
* The last block in each sector is the Sector Trailer like above.
|
||||||
|
* MIFARE Classic Mini (MF1 IC S20):
|
||||||
|
* Has 5 sectors * 4 blocks/sector * 16 bytes/block = 320 bytes.
|
||||||
|
* The blocks are numbered 0-19.
|
||||||
|
* The last block in each sector is the Sector Trailer like above.
|
||||||
|
*
|
||||||
|
* MIFARE Ultralight (MF0ICU1):
|
||||||
|
* Has 16 pages of 4 bytes = 64 bytes.
|
||||||
|
* Pages 0 + 1 is used for the 7-byte UID.
|
||||||
|
* Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
|
||||||
|
* Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
|
||||||
|
* Pages 4-15 are read/write unless blocked by the lock bytes in page 2.
|
||||||
|
* MIFARE Ultralight C (MF0ICU2):
|
||||||
|
* Has 48 pages of 4 bytes = 192 bytes.
|
||||||
|
* Pages 0 + 1 is used for the 7-byte UID.
|
||||||
|
* Page 2 contains the last check digit for the UID, one byte manufacturer internal data, and the lock bytes (see http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf section 8.5.2)
|
||||||
|
* Page 3 is OTP, One Time Programmable bits. Once set to 1 they cannot revert to 0.
|
||||||
|
* Pages 4-39 are read/write unless blocked by the lock bytes in page 2.
|
||||||
|
* Page 40 Lock bytes
|
||||||
|
* Page 41 16 bit one way counter
|
||||||
|
* Pages 42-43 Authentication configuration
|
||||||
|
* Pages 44-47 Authentication key
|
||||||
|
*/
|
||||||
|
#ifndef MFRC522_h
|
||||||
|
#define MFRC522_h
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
// Firmware data for self-test
|
||||||
|
// Reference values based on firmware version
|
||||||
|
// Hint: if needed, you can remove unused self-test data to save flash memory
|
||||||
|
//
|
||||||
|
// Version 0.0 (0x90)
|
||||||
|
// Philips Semiconductors; Preliminary Specification Revision 2.0 - 01 August 2005; 16.1 Sefttest
|
||||||
|
const byte MFRC522_firmware_referenceV0_0[] PROGMEM = {
|
||||||
|
0x00, 0x87, 0x98, 0x0f, 0x49, 0xFF, 0x07, 0x19,
|
||||||
|
0xBF, 0x22, 0x30, 0x49, 0x59, 0x63, 0xAD, 0xCA,
|
||||||
|
0x7F, 0xE3, 0x4E, 0x03, 0x5C, 0x4E, 0x49, 0x50,
|
||||||
|
0x47, 0x9A, 0x37, 0x61, 0xE7, 0xE2, 0xC6, 0x2E,
|
||||||
|
0x75, 0x5A, 0xED, 0x04, 0x3D, 0x02, 0x4B, 0x78,
|
||||||
|
0x32, 0xFF, 0x58, 0x3B, 0x7C, 0xE9, 0x00, 0x94,
|
||||||
|
0xB4, 0x4A, 0x59, 0x5B, 0xFD, 0xC9, 0x29, 0xDF,
|
||||||
|
0x35, 0x96, 0x98, 0x9E, 0x4F, 0x30, 0x32, 0x8D
|
||||||
|
};
|
||||||
|
// Version 1.0 (0x91)
|
||||||
|
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
|
||||||
|
const byte MFRC522_firmware_referenceV1_0[] PROGMEM = {
|
||||||
|
0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C,
|
||||||
|
0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73,
|
||||||
|
0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A,
|
||||||
|
0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E,
|
||||||
|
0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC,
|
||||||
|
0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41,
|
||||||
|
0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02,
|
||||||
|
0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79
|
||||||
|
};
|
||||||
|
// Version 2.0 (0x92)
|
||||||
|
// NXP Semiconductors; Rev. 3.8 - 17 September 2014; 16.1.1 Self test
|
||||||
|
const byte MFRC522_firmware_referenceV2_0[] PROGMEM = {
|
||||||
|
0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95,
|
||||||
|
0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE,
|
||||||
|
0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82,
|
||||||
|
0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49,
|
||||||
|
0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81,
|
||||||
|
0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9,
|
||||||
|
0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D,
|
||||||
|
0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
|
||||||
|
};
|
||||||
|
// Clone
|
||||||
|
// Fudan Semiconductor FM17522 (0x88)
|
||||||
|
const byte FM17522_firmware_reference[] PROGMEM = {
|
||||||
|
0x00, 0xD6, 0x78, 0x8C, 0xE2, 0xAA, 0x0C, 0x18,
|
||||||
|
0x2A, 0xB8, 0x7A, 0x7F, 0xD3, 0x6A, 0xCF, 0x0B,
|
||||||
|
0xB1, 0x37, 0x63, 0x4B, 0x69, 0xAE, 0x91, 0xC7,
|
||||||
|
0xC3, 0x97, 0xAE, 0x77, 0xF4, 0x37, 0xD7, 0x9B,
|
||||||
|
0x7C, 0xF5, 0x3C, 0x11, 0x8F, 0x15, 0xC3, 0xD7,
|
||||||
|
0xC1, 0x5B, 0x00, 0x2A, 0xD0, 0x75, 0xDE, 0x9E,
|
||||||
|
0x51, 0x64, 0xAB, 0x3E, 0xE9, 0x15, 0xB5, 0xAB,
|
||||||
|
0x56, 0x9A, 0x98, 0x82, 0x26, 0xEA, 0x2A, 0x62
|
||||||
|
};
|
||||||
|
|
||||||
|
class MFRC522 {
|
||||||
|
public:
|
||||||
|
// MFRC522 registers. Described in chapter 9 of the datasheet.
|
||||||
|
enum PCD_Register {
|
||||||
|
// Page 0: Command and status
|
||||||
|
// 0x00 // reserved for future use
|
||||||
|
CommandReg = 0x01 , // starts and stops command execution
|
||||||
|
ComIEnReg = 0x02 , // enable and disable interrupt request control bits
|
||||||
|
DivIEnReg = 0x03 , // enable and disable interrupt request control bits
|
||||||
|
ComIrqReg = 0x04 , // interrupt request bits
|
||||||
|
DivIrqReg = 0x05 , // interrupt request bits
|
||||||
|
ErrorReg = 0x06 , // error bits showing the error status of the last command executed
|
||||||
|
Status1Reg = 0x07 , // communication status bits
|
||||||
|
Status2Reg = 0x08 , // receiver and transmitter status bits
|
||||||
|
FIFODataReg = 0x09 , // input and output of 64 byte FIFO buffer
|
||||||
|
FIFOLevelReg = 0x0A , // number of bytes stored in the FIFO buffer
|
||||||
|
WaterLevelReg = 0x0B , // level for FIFO underflow and overflow warning
|
||||||
|
ControlReg = 0x0C , // miscellaneous control registers
|
||||||
|
BitFramingReg = 0x0D , // adjustments for bit-oriented frames
|
||||||
|
CollReg = 0x0E , // bit position of the first bit-collision detected on the RF interface
|
||||||
|
// 0x0F // reserved for future use
|
||||||
|
|
||||||
|
// Page 1: Command
|
||||||
|
// 0x10 // reserved for future use
|
||||||
|
ModeReg = 0x11 , // defines general modes for transmitting and receiving
|
||||||
|
TxModeReg = 0x12 , // defines transmission data rate and framing
|
||||||
|
RxModeReg = 0x13 , // defines reception data rate and framing
|
||||||
|
TxControlReg = 0x14 , // controls the logical behavior of the antenna driver pins TX1 and TX2
|
||||||
|
TxASKReg = 0x15 , // controls the setting of the transmission modulation
|
||||||
|
TxSelReg = 0x16 , // selects the internal sources for the antenna driver
|
||||||
|
RxSelReg = 0x17 , // selects internal receiver settings
|
||||||
|
RxThresholdReg = 0x18 , // selects thresholds for the bit decoder
|
||||||
|
DemodReg = 0x19 , // defines demodulator settings
|
||||||
|
// 0x1A // reserved for future use
|
||||||
|
// 0x1B // reserved for future use
|
||||||
|
MfTxReg = 0x1C , // controls some MIFARE communication transmit parameters
|
||||||
|
MfRxReg = 0x1D , // controls some MIFARE communication receive parameters
|
||||||
|
// 0x1E // reserved for future use
|
||||||
|
SerialSpeedReg = 0x1F , // selects the speed of the serial UART interface
|
||||||
|
|
||||||
|
// Page 2: Configuration
|
||||||
|
// 0x20 // reserved for future use
|
||||||
|
CRCResultRegH = 0x21 , // shows the MSB and LSB values of the CRC calculation
|
||||||
|
CRCResultRegL = 0x22 ,
|
||||||
|
// 0x23 // reserved for future use
|
||||||
|
ModWidthReg = 0x24 , // controls the ModWidth setting?
|
||||||
|
// 0x25 // reserved for future use
|
||||||
|
RFCfgReg = 0x26 , // configures the receiver gain
|
||||||
|
GsNReg = 0x27 , // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
|
||||||
|
CWGsPReg = 0x28 , // defines the conductance of the p-driver output during periods of no modulation
|
||||||
|
ModGsPReg = 0x29 , // defines the conductance of the p-driver output during periods of modulation
|
||||||
|
TModeReg = 0x2A , // defines settings for the internal timer
|
||||||
|
TPrescalerReg = 0x2B , // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
|
||||||
|
TReloadRegH = 0x2C , // defines the 16-bit timer reload value
|
||||||
|
TReloadRegL = 0x2D ,
|
||||||
|
TCounterValueRegH = 0x2E , // shows the 16-bit timer value
|
||||||
|
TCounterValueRegL = 0x2F ,
|
||||||
|
|
||||||
|
// Page 3: Test Registers
|
||||||
|
// 0x30 // reserved for future use
|
||||||
|
TestSel1Reg = 0x31 , // general test signal configuration
|
||||||
|
TestSel2Reg = 0x32 , // general test signal configuration
|
||||||
|
TestPinEnReg = 0x33 , // enables pin output driver on pins D1 to D7
|
||||||
|
TestPinValueReg = 0x34 , // defines the values for D1 to D7 when it is used as an I/O bus
|
||||||
|
TestBusReg = 0x35 , // shows the status of the internal test bus
|
||||||
|
AutoTestReg = 0x36 , // controls the digital self test
|
||||||
|
VersionReg = 0x37 , // shows the software version
|
||||||
|
AnalogTestReg = 0x38 , // controls the pins AUX1 and AUX2
|
||||||
|
TestDAC1Reg = 0x39 , // defines the test value for TestDAC1
|
||||||
|
TestDAC2Reg = 0x3A , // defines the test value for TestDAC2
|
||||||
|
TestADCReg = 0x3B // shows the value of ADC I and Q channels
|
||||||
|
// 0x3C // reserved for production tests
|
||||||
|
// 0x3D // reserved for production tests
|
||||||
|
// 0x3E // reserved for production tests
|
||||||
|
// 0x3F // reserved for production tests
|
||||||
|
};
|
||||||
|
|
||||||
|
// MFRC522 commands. Described in chapter 10 of the datasheet.
|
||||||
|
enum PCD_Command {
|
||||||
|
PCD_Idle = 0x00, // no action, cancels current command execution
|
||||||
|
PCD_Mem = 0x01, // stores 25 bytes into the internal buffer
|
||||||
|
PCD_GenerateRandomID = 0x02, // generates a 10-byte random ID number
|
||||||
|
PCD_CalcCRC = 0x03, // activates the CRC coprocessor or performs a self test
|
||||||
|
PCD_Transmit = 0x04, // transmits data from the FIFO buffer
|
||||||
|
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
|
||||||
|
PCD_Receive = 0x08, // activates the receiver circuits
|
||||||
|
PCD_Transceive = 0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
|
||||||
|
PCD_MFAuthent = 0x0E, // performs the MIFARE standard authentication as a reader
|
||||||
|
PCD_SoftReset = 0x0F // resets the MFRC522
|
||||||
|
};
|
||||||
|
|
||||||
|
// MFRC522 RxGain[2:0] masks, defines the receiver's signal voltage gain factor (on the PCD).
|
||||||
|
// Described in 9.3.3.6 / table 98 of the datasheet at http://www.nxp.com/documents/data_sheet/MFRC522.pdf
|
||||||
|
enum PCD_RxGain {
|
||||||
|
RxGain_18dB = 0x00 << 4, // 000b - 18 dB, minimum
|
||||||
|
RxGain_23dB = 0x01 << 4, // 001b - 23 dB
|
||||||
|
RxGain_18dB_2 = 0x02 << 4, // 010b - 18 dB, it seems 010b is a duplicate for 000b
|
||||||
|
RxGain_23dB_2 = 0x03 << 4, // 011b - 23 dB, it seems 011b is a duplicate for 001b
|
||||||
|
RxGain_33dB = 0x04 << 4, // 100b - 33 dB, average, and typical default
|
||||||
|
RxGain_38dB = 0x05 << 4, // 101b - 38 dB
|
||||||
|
RxGain_43dB = 0x06 << 4, // 110b - 43 dB
|
||||||
|
RxGain_48dB = 0x07 << 4, // 111b - 48 dB, maximum
|
||||||
|
RxGain_min = 0x00 << 4, // 000b - 18 dB, minimum, convenience for RxGain_18dB
|
||||||
|
RxGain_avg = 0x04 << 4, // 100b - 33 dB, average, convenience for RxGain_33dB
|
||||||
|
RxGain_max = 0x07 << 4 // 111b - 48 dB, maximum, convenience for RxGain_48dB
|
||||||
|
};
|
||||||
|
|
||||||
|
// Commands sent to the PICC.
|
||||||
|
enum PICC_Command {
|
||||||
|
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
|
||||||
|
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
|
||||||
|
PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
|
||||||
|
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
|
||||||
|
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
|
||||||
|
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
|
||||||
|
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
|
||||||
|
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
|
||||||
|
// The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
|
||||||
|
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
|
||||||
|
// The read/write commands can also be used for MIFARE Ultralight.
|
||||||
|
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
|
||||||
|
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
|
||||||
|
PICC_CMD_MF_READ = 0x30, // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
|
||||||
|
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
|
||||||
|
PICC_CMD_MF_DECREMENT = 0xC0, // Decrements the contents of a block and stores the result in the internal data register.
|
||||||
|
PICC_CMD_MF_INCREMENT = 0xC1, // Increments the contents of a block and stores the result in the internal data register.
|
||||||
|
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
|
||||||
|
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
|
||||||
|
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
|
||||||
|
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
|
||||||
|
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 byte page to the PICC.
|
||||||
|
};
|
||||||
|
|
||||||
|
// MIFARE constants that does not fit anywhere else
|
||||||
|
enum MIFARE_Misc {
|
||||||
|
MF_ACK = 0xA, // The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
|
||||||
|
MF_KEY_SIZE = 6 // A Mifare Crypto1 key is 6 bytes.
|
||||||
|
};
|
||||||
|
|
||||||
|
// PICC types we can detect. Remember to update PICC_GetTypeName() if you add more.
|
||||||
|
enum PICC_Type {
|
||||||
|
PICC_TYPE_UNKNOWN = 0,
|
||||||
|
PICC_TYPE_ISO_14443_4 = 1, // PICC compliant with ISO/IEC 14443-4
|
||||||
|
PICC_TYPE_ISO_18092 = 2, // PICC compliant with ISO/IEC 18092 (NFC)
|
||||||
|
PICC_TYPE_MIFARE_MINI = 3, // MIFARE Classic protocol, 320 bytes
|
||||||
|
PICC_TYPE_MIFARE_1K = 4, // MIFARE Classic protocol, 1KB
|
||||||
|
PICC_TYPE_MIFARE_4K = 5, // MIFARE Classic protocol, 4KB
|
||||||
|
PICC_TYPE_MIFARE_UL = 6, // MIFARE Ultralight or Ultralight C
|
||||||
|
PICC_TYPE_MIFARE_PLUS = 7, // MIFARE Plus
|
||||||
|
PICC_TYPE_TNP3XXX = 8, // Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
|
||||||
|
PICC_TYPE_NOT_COMPLETE = 255 // SAK indicates UID is not complete.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
|
||||||
|
enum StatusCode {
|
||||||
|
STATUS_OK = 1, // Success
|
||||||
|
STATUS_ERROR = 2, // Error in communication
|
||||||
|
STATUS_COLLISION = 3, // Collission detected
|
||||||
|
STATUS_TIMEOUT = 4, // Timeout in communication.
|
||||||
|
STATUS_NO_ROOM = 5, // A buffer is not big enough.
|
||||||
|
STATUS_INTERNAL_ERROR = 6, // Internal error in the code. Should not happen ;-)
|
||||||
|
STATUS_INVALID = 7, // Invalid argument.
|
||||||
|
STATUS_CRC_WRONG = 8, // The CRC_A does not match
|
||||||
|
STATUS_MIFARE_NACK = 9 // A MIFARE PICC responded with NAK.
|
||||||
|
};
|
||||||
|
|
||||||
|
// A struct used for passing the UID of a PICC.
|
||||||
|
typedef struct {
|
||||||
|
byte size; // Number of bytes in the UID. 4, 7 or 10.
|
||||||
|
byte uidByte[10];
|
||||||
|
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
|
||||||
|
} Uid;
|
||||||
|
|
||||||
|
// A struct used for passing a MIFARE Crypto1 key
|
||||||
|
typedef struct {
|
||||||
|
byte keyByte[MF_KEY_SIZE];
|
||||||
|
} MIFARE_Key;
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
Uid uid; // Used by PICC_ReadCardSerial().
|
||||||
|
|
||||||
|
// Size of the MFRC522 FIFO
|
||||||
|
static const byte FIFO_SIZE = 64; // The FIFO is 64 bytes.
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for setting up the Arduino
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
MFRC522(byte chipAddress);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Basic interface functions for communicating with the MFRC522
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void PCD_WriteRegister(byte reg, byte value);
|
||||||
|
void PCD_WriteRegister(byte reg, byte count, byte *values);
|
||||||
|
byte PCD_ReadRegister(byte reg);
|
||||||
|
void PCD_ReadRegister(byte reg, byte count, byte *values, byte rxAlign = 0);
|
||||||
|
void setBitMask(unsigned char reg, unsigned char mask);
|
||||||
|
void PCD_SetRegisterBitMask(byte reg, byte mask);
|
||||||
|
void PCD_ClearRegisterBitMask(byte reg, byte mask);
|
||||||
|
byte PCD_CalculateCRC(byte *data, byte length, byte *result);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for manipulating the MFRC522
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void PCD_Init();
|
||||||
|
void PCD_Reset();
|
||||||
|
void PCD_AntennaOn();
|
||||||
|
void PCD_AntennaOff();
|
||||||
|
byte PCD_GetAntennaGain();
|
||||||
|
void PCD_SetAntennaGain(byte mask);
|
||||||
|
bool PCD_PerformSelfTest();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for communicating with PICCs
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
|
||||||
|
byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
|
||||||
|
byte PICC_RequestA(byte *bufferATQA, byte *bufferSize);
|
||||||
|
byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
|
||||||
|
byte PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
|
||||||
|
byte PICC_Select(Uid *uid, byte validBits = 0);
|
||||||
|
byte PICC_HaltA();
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Functions for communicating with MIFARE PICCs
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
|
||||||
|
void PCD_StopCrypto1();
|
||||||
|
byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
|
||||||
|
byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
|
||||||
|
byte MIFARE_Decrement(byte blockAddr, long delta);
|
||||||
|
byte MIFARE_Increment(byte blockAddr, long delta);
|
||||||
|
byte MIFARE_Restore(byte blockAddr);
|
||||||
|
byte MIFARE_Transfer(byte blockAddr);
|
||||||
|
byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
|
||||||
|
byte MIFARE_GetValue(byte blockAddr, long *value);
|
||||||
|
byte MIFARE_SetValue(byte blockAddr, long value);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Support functions
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
byte PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout = false);
|
||||||
|
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
|
||||||
|
//const char *GetStatusCodeName(byte code);
|
||||||
|
const __FlashStringHelper *GetStatusCodeName(byte code);
|
||||||
|
byte PICC_GetType(byte sak);
|
||||||
|
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
|
||||||
|
//const char *PICC_GetTypeName(byte type);
|
||||||
|
const __FlashStringHelper *PICC_GetTypeName(byte type);
|
||||||
|
void PICC_DumpToSerial(Uid *uid);
|
||||||
|
void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType, MIFARE_Key *key);
|
||||||
|
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
|
||||||
|
void PICC_DumpMifareUltralightToSerial();
|
||||||
|
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
|
||||||
|
bool MIFARE_OpenUidBackdoor(bool logErrors);
|
||||||
|
bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors);
|
||||||
|
bool MIFARE_UnbrickUidSector(bool logErrors);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convenience functions - does not add extra functionality
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool PICC_IsNewCardPresent();
|
||||||
|
bool PICC_ReadCardSerial();
|
||||||
|
|
||||||
|
private:
|
||||||
|
byte _chipAddress;
|
||||||
|
byte _resetPowerDownPin; // Arduino pin connected to MFRC522's reset and power down input (Pin 6, NRSTPD, active low)
|
||||||
|
byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
9
lib/lib_i2c/MPU6886/library.properties
Normal file
9
lib/lib_i2c/MPU6886/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=MPU6886
|
||||||
|
version=
|
||||||
|
author=M5StickC
|
||||||
|
maintainer=Stephan Hadinger
|
||||||
|
sentence=Support for MPU6886
|
||||||
|
paragraph=Support for MPU6886
|
||||||
|
category=
|
||||||
|
url=https://github.com/m5stack/M5StickC/blob/master/src/utility/
|
||||||
|
architectures=esp32,esp8266
|
@ -2,39 +2,33 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
MPU6886::MPU6886(){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
|
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
|
||||||
|
|
||||||
Wire1.beginTransmission(driver_Addr);
|
myWire.beginTransmission(driver_Addr);
|
||||||
Wire1.write(start_Addr);
|
myWire.write(start_Addr);
|
||||||
Wire1.endTransmission(false);
|
myWire.endTransmission(false);
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
Wire1.requestFrom(driver_Addr,number_Bytes);
|
myWire.requestFrom(driver_Addr,number_Bytes);
|
||||||
|
|
||||||
//! Put read results in the Rx buffer
|
//! Put read results in the Rx buffer
|
||||||
while (Wire1.available()) {
|
while (myWire.available()) {
|
||||||
read_Buffer[i++] = Wire1.read();
|
read_Buffer[i++] = myWire.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer){
|
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer){
|
||||||
|
|
||||||
Wire1.beginTransmission(driver_Addr);
|
myWire.beginTransmission(driver_Addr);
|
||||||
Wire1.write(start_Addr);
|
myWire.write(start_Addr);
|
||||||
Wire1.write(*write_Buffer);
|
myWire.write(*write_Buffer);
|
||||||
Wire1.endTransmission();
|
myWire.endTransmission();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPU6886::Init(void){
|
int MPU6886::Init(void){
|
||||||
unsigned char tempdata[1];
|
unsigned char tempdata[1];
|
||||||
unsigned char regdata;
|
unsigned char regdata;
|
||||||
|
|
||||||
Wire1.begin(21,22);
|
|
||||||
|
|
||||||
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
|
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
|
||||||
if(tempdata[0] != 0x19)
|
if(tempdata[0] != 0x19)
|
||||||
return -1;
|
return -1;
|
||||||
@ -52,11 +46,11 @@ int MPU6886::Init(void){
|
|||||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||||
delay(10);
|
delay(10);
|
||||||
|
|
||||||
regdata = 0x10;
|
regdata = 0x10; // AFS_8G
|
||||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
||||||
delay(1);
|
delay(1);
|
||||||
|
|
||||||
regdata = 0x18;
|
regdata = 0x18; // GFS_2000DPS
|
||||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
||||||
delay(1);
|
delay(1);
|
||||||
|
|
||||||
@ -128,24 +122,24 @@ void MPU6886::getTempAdc(int16_t *t){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。
|
// //!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。
|
||||||
void MPU6886::getAhrsData(float *pitch,float *roll,float *yaw){
|
// void MPU6886::getAhrsData(float *pitch,float *roll,float *yaw){
|
||||||
|
|
||||||
float accX = 0;
|
// float accX = 0;
|
||||||
float accY = 0;
|
// float accY = 0;
|
||||||
float accZ = 0;
|
// float accZ = 0;
|
||||||
|
|
||||||
float gyroX = 0;
|
// float gyroX = 0;
|
||||||
float gyroY = 0;
|
// float gyroY = 0;
|
||||||
float gyroZ = 0;
|
// float gyroZ = 0;
|
||||||
|
|
||||||
|
|
||||||
getGyroData(&gyroX,&gyroY,&gyroZ);
|
// getGyroData(&gyroX,&gyroY,&gyroZ);
|
||||||
getAccelData(&accX,&accY,&accZ);
|
// getAccelData(&accX,&accY,&accZ);
|
||||||
|
|
||||||
MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, gyroZ * DEG_TO_RAD, accX, accY, accZ,pitch,roll,yaw);
|
// MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, gyroZ * DEG_TO_RAD, accX, accY, accZ,pitch,roll,yaw);
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|
||||||
void MPU6886::getGres(){
|
void MPU6886::getGres(){
|
||||||
|
|
||||||
@ -153,16 +147,20 @@ void MPU6886::getGres(){
|
|||||||
{
|
{
|
||||||
// Possible gyro scales (and their register bit settings) are:
|
// Possible gyro scales (and their register bit settings) are:
|
||||||
case GFS_250DPS:
|
case GFS_250DPS:
|
||||||
gRes = 250.0/32768.0;
|
gRes = 250.0f/32768.0f;
|
||||||
|
gyRange = 250;
|
||||||
break;
|
break;
|
||||||
case GFS_500DPS:
|
case GFS_500DPS:
|
||||||
gRes = 500.0/32768.0;
|
gRes = 500.0f/32768.0f;
|
||||||
|
gyRange = 500;
|
||||||
break;
|
break;
|
||||||
case GFS_1000DPS:
|
case GFS_1000DPS:
|
||||||
gRes = 1000.0/32768.0;
|
gRes = 1000.0f/32768.0f;
|
||||||
|
gyRange = 1000;
|
||||||
break;
|
break;
|
||||||
case GFS_2000DPS:
|
case GFS_2000DPS:
|
||||||
gRes = 2000.0/32768.0;
|
gRes = 2000.0f/32768.0f;
|
||||||
|
gyRange = 2000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,15 +175,19 @@ void MPU6886::getAres(){
|
|||||||
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
|
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
|
||||||
case AFS_2G:
|
case AFS_2G:
|
||||||
aRes = 2.0/32768.0;
|
aRes = 2.0/32768.0;
|
||||||
|
acRange = 2000;
|
||||||
break;
|
break;
|
||||||
case AFS_4G:
|
case AFS_4G:
|
||||||
aRes = 4.0/32768.0;
|
aRes = 4.0/32768.0;
|
||||||
|
acRange = 4000;
|
||||||
break;
|
break;
|
||||||
case AFS_8G:
|
case AFS_8G:
|
||||||
aRes = 8.0/32768.0;
|
aRes = 8.0/32768.0;
|
||||||
|
acRange = 8000;
|
||||||
break;
|
break;
|
||||||
case AFS_16G:
|
case AFS_16G:
|
||||||
aRes = 16.0/32768.0;
|
aRes = 16.0/32768.0;
|
||||||
|
acRange = 16000;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +217,19 @@ void MPU6886::SetAccelFsr(Ascale scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// x/y/z are in 1/1000 if g
|
||||||
|
// avoiding costly float calculations
|
||||||
|
void MPU6886::getAccelDataInt(int16_t* ax, int16_t* ay, int16_t* az) {
|
||||||
|
int16_t accX = 0;
|
||||||
|
int16_t accY = 0;
|
||||||
|
int16_t accZ = 0;
|
||||||
|
getAccelAdc(&accX, &accY, &accZ);
|
||||||
|
|
||||||
|
if (ax != nullptr) { *ax = ((int32_t)accX * acRange) / 0x7FFFL; }
|
||||||
|
if (ay != nullptr) { *ay = ((int32_t)accY * acRange) / 0x7FFFL; }
|
||||||
|
if (az != nullptr) { *az = ((int32_t)accZ * acRange) / 0x7FFFL; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MPU6886::getAccelData(float* ax, float* ay, float* az){
|
void MPU6886::getAccelData(float* ax, float* ay, float* az){
|
||||||
|
|
||||||
@ -232,6 +246,20 @@ void MPU6886::getAccelData(float* ax, float* ay, float* az){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// x/y/z are in dps - degrees per second
|
||||||
|
// avoiding costly float calculations
|
||||||
|
void MPU6886::getGyroDataInt(int16_t* ax, int16_t* ay, int16_t* az) {
|
||||||
|
int16_t gyX = 0;
|
||||||
|
int16_t gyY = 0;
|
||||||
|
int16_t gyZ = 0;
|
||||||
|
getGyroAdc(&gyX, &gyY, &gyZ);
|
||||||
|
|
||||||
|
if (ax != nullptr) { *ax = ((int32_t)gyX * gyRange) / 0x7FFFL; }
|
||||||
|
if (ay != nullptr) { *ay = ((int32_t)gyY * gyRange) / 0x7FFFL; }
|
||||||
|
if (az != nullptr) { *az = ((int32_t)gyZ * gyRange) / 0x7FFFL; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MPU6886::getGyroData(float* gx, float* gy, float* gz){
|
void MPU6886::getGyroData(float* gx, float* gy, float* gz){
|
||||||
int16_t gyroX = 0;
|
int16_t gyroX = 0;
|
||||||
int16_t gyroY = 0;
|
int16_t gyroY = 0;
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "MahonyAHRS.h"
|
|
||||||
|
|
||||||
#define MPU6886_ADDRESS 0x68
|
#define MPU6886_ADDRESS 0x68
|
||||||
#define MPU6886_WHOAMI 0x75
|
#define MPU6886_WHOAMI 0x75
|
||||||
@ -67,8 +66,15 @@ class MPU6886 {
|
|||||||
|
|
||||||
Gscale Gyscale = GFS_2000DPS;
|
Gscale Gyscale = GFS_2000DPS;
|
||||||
Ascale Acscale = AFS_8G;
|
Ascale Acscale = AFS_8G;
|
||||||
|
int16_t acRange = 8000; // 1/1000 of g
|
||||||
|
int16_t gyRange = 2000; // dps - degree per second
|
||||||
public:
|
public:
|
||||||
MPU6886();
|
MPU6886(void) {};
|
||||||
|
#ifdef ESP32
|
||||||
|
void setBus(uint32_t _bus) { myWire = _bus ? Wire1 : Wire; };
|
||||||
|
#else
|
||||||
|
void setBus(uint32_t _bus) { myWire = Wire; };
|
||||||
|
#endif
|
||||||
int Init(void);
|
int Init(void);
|
||||||
void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az);
|
void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az);
|
||||||
void getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz);
|
void getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz);
|
||||||
@ -77,13 +83,17 @@ class MPU6886 {
|
|||||||
void getAccelData(float* ax, float* ay, float* az);
|
void getAccelData(float* ax, float* ay, float* az);
|
||||||
void getGyroData(float* gx, float* gy, float* gz);
|
void getGyroData(float* gx, float* gy, float* gz);
|
||||||
void getTempData(float *t);
|
void getTempData(float *t);
|
||||||
|
// int variants
|
||||||
|
void getAccelDataInt(int16_t* ax, int16_t* ay, int16_t* az);
|
||||||
|
void getGyroDataInt(int16_t* gx, int16_t* gy, int16_t* gz);
|
||||||
|
|
||||||
void SetGyroFsr(Gscale scale);
|
void SetGyroFsr(Gscale scale);
|
||||||
void SetAccelFsr(Ascale scale);
|
void SetAccelFsr(Ascale scale);
|
||||||
|
|
||||||
void getAhrsData(float *pitch,float *roll,float *yaw);
|
// void getAhrsData(float *pitch,float *roll,float *yaw);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
TwoWire & myWire = Wire; // default to Wire (bus 0)
|
||||||
float aRes, gRes;
|
float aRes, gRes;
|
||||||
|
|
||||||
private:
|
private:
|
@ -1,254 +0,0 @@
|
|||||||
//=====================================================================================================
|
|
||||||
// MahonyAHRS.c
|
|
||||||
//=====================================================================================================
|
|
||||||
//
|
|
||||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
|
||||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
|
||||||
//
|
|
||||||
// Date Author Notes
|
|
||||||
// 29/09/2011 SOH Madgwick Initial release
|
|
||||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
|
||||||
//
|
|
||||||
//=====================================================================================================
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Header files
|
|
||||||
|
|
||||||
#include "MahonyAHRS.h"
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include <math.h>
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Definitions
|
|
||||||
|
|
||||||
#define sampleFreq 25.0f // sample frequency in Hz
|
|
||||||
#define twoKpDef (2.0f * 1.0f) // 2 * proportional gain
|
|
||||||
#define twoKiDef (2.0f * 0.0f) // 2 * integral gain
|
|
||||||
|
|
||||||
//#define twoKiDef (0.0f * 0.0f)
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Variable definitions
|
|
||||||
|
|
||||||
volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp)
|
|
||||||
volatile float twoKi = twoKiDef; // 2 * integral gain (Ki)
|
|
||||||
volatile float q0 = 1.0, q1 = 0.0, q2 = 0.0, q3 = 0.0; // quaternion of sensor frame relative to auxiliary frame
|
|
||||||
volatile float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Function declarations
|
|
||||||
|
|
||||||
//float invSqrt(float x);
|
|
||||||
|
|
||||||
//====================================================================================================
|
|
||||||
// Functions
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// AHRS algorithm update
|
|
||||||
|
|
||||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
|
|
||||||
float recipNorm;
|
|
||||||
float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
|
|
||||||
float hx, hy, bx, bz;
|
|
||||||
float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
|
|
||||||
float halfex, halfey, halfez;
|
|
||||||
float qa, qb, qc;
|
|
||||||
|
|
||||||
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
|
|
||||||
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
|
|
||||||
//MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
|
||||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
|
||||||
|
|
||||||
// Normalise accelerometer measurement
|
|
||||||
recipNorm = sqrt(ax * ax + ay * ay + az * az);
|
|
||||||
ax *= recipNorm;
|
|
||||||
ay *= recipNorm;
|
|
||||||
az *= recipNorm;
|
|
||||||
|
|
||||||
// Normalise magnetometer measurement
|
|
||||||
recipNorm = sqrt(mx * mx + my * my + mz * mz);
|
|
||||||
mx *= recipNorm;
|
|
||||||
my *= recipNorm;
|
|
||||||
mz *= recipNorm;
|
|
||||||
|
|
||||||
// Auxiliary variables to avoid repeated arithmetic
|
|
||||||
q0q0 = q0 * q0;
|
|
||||||
q0q1 = q0 * q1;
|
|
||||||
q0q2 = q0 * q2;
|
|
||||||
q0q3 = q0 * q3;
|
|
||||||
q1q1 = q1 * q1;
|
|
||||||
q1q2 = q1 * q2;
|
|
||||||
q1q3 = q1 * q3;
|
|
||||||
q2q2 = q2 * q2;
|
|
||||||
q2q3 = q2 * q3;
|
|
||||||
q3q3 = q3 * q3;
|
|
||||||
|
|
||||||
// Reference direction of Earth's magnetic field
|
|
||||||
hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
|
|
||||||
hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
|
|
||||||
bx = sqrt(hx * hx + hy * hy);
|
|
||||||
bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
|
|
||||||
|
|
||||||
// Estimated direction of gravity and magnetic field
|
|
||||||
halfvx = q1q3 - q0q2;
|
|
||||||
halfvy = q0q1 + q2q3;
|
|
||||||
halfvz = q0q0 - 0.5f + q3q3;
|
|
||||||
halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
|
|
||||||
halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
|
|
||||||
halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
|
|
||||||
|
|
||||||
// Error is sum of cross product between estimated direction and measured direction of field vectors
|
|
||||||
halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
|
|
||||||
halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
|
|
||||||
halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
|
|
||||||
|
|
||||||
// Compute and apply integral feedback if enabled
|
|
||||||
if(twoKi > 0.0f) {
|
|
||||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
|
||||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
|
||||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
|
||||||
gx += integralFBx; // apply integral feedback
|
|
||||||
gy += integralFBy;
|
|
||||||
gz += integralFBz;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
integralFBx = 0.0f; // prevent integral windup
|
|
||||||
integralFBy = 0.0f;
|
|
||||||
integralFBz = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply proportional feedback
|
|
||||||
gx += twoKp * halfex;
|
|
||||||
gy += twoKp * halfey;
|
|
||||||
gz += twoKp * halfez;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integrate rate of change of quaternion
|
|
||||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
|
||||||
gy *= (0.5f * (1.0f / sampleFreq));
|
|
||||||
gz *= (0.5f * (1.0f / sampleFreq));
|
|
||||||
qa = q0;
|
|
||||||
qb = q1;
|
|
||||||
qc = q2;
|
|
||||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
|
||||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
|
||||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
|
||||||
q3 += (qa * gz + qb * gy - qc * gx);
|
|
||||||
|
|
||||||
// Normalise quaternion
|
|
||||||
recipNorm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
|
||||||
q0 *= recipNorm;
|
|
||||||
q1 *= recipNorm;
|
|
||||||
q2 *= recipNorm;
|
|
||||||
q3 *= recipNorm;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// IMU algorithm update
|
|
||||||
|
|
||||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw) {
|
|
||||||
float recipNorm;
|
|
||||||
float halfvx, halfvy, halfvz;
|
|
||||||
float halfex, halfey, halfez;
|
|
||||||
float qa, qb, qc;
|
|
||||||
|
|
||||||
|
|
||||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
|
||||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
|
||||||
|
|
||||||
// Normalise accelerometer measurement
|
|
||||||
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
|
|
||||||
ax *= recipNorm;
|
|
||||||
ay *= recipNorm;
|
|
||||||
az *= recipNorm;
|
|
||||||
|
|
||||||
// Estimated direction of gravity and vector perpendicular to magnetic flux
|
|
||||||
halfvx = q1 * q3 - q0 * q2;
|
|
||||||
halfvy = q0 * q1 + q2 * q3;
|
|
||||||
halfvz = q0 * q0 - 0.5f + q3 * q3;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Error is sum of cross product between estimated and measured direction of gravity
|
|
||||||
halfex = (ay * halfvz - az * halfvy);
|
|
||||||
halfey = (az * halfvx - ax * halfvz);
|
|
||||||
halfez = (ax * halfvy - ay * halfvx);
|
|
||||||
|
|
||||||
// Compute and apply integral feedback if enabled
|
|
||||||
if(twoKi > 0.0f) {
|
|
||||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
|
||||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
|
||||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
|
||||||
gx += integralFBx; // apply integral feedback
|
|
||||||
gy += integralFBy;
|
|
||||||
gz += integralFBz;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
integralFBx = 0.0f; // prevent integral windup
|
|
||||||
integralFBy = 0.0f;
|
|
||||||
integralFBz = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply proportional feedback
|
|
||||||
gx += twoKp * halfex;
|
|
||||||
gy += twoKp * halfey;
|
|
||||||
gz += twoKp * halfez;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integrate rate of change of quaternion
|
|
||||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
|
||||||
gy *= (0.5f * (1.0f / sampleFreq));
|
|
||||||
gz *= (0.5f * (1.0f / sampleFreq));
|
|
||||||
qa = q0;
|
|
||||||
qb = q1;
|
|
||||||
qc = q2;
|
|
||||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
|
||||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
|
||||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
|
||||||
q3 += (qa * gz + qb * gy - qc * gx);
|
|
||||||
|
|
||||||
// Normalise quaternion
|
|
||||||
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
|
||||||
q0 *= recipNorm;
|
|
||||||
q1 *= recipNorm;
|
|
||||||
q2 *= recipNorm;
|
|
||||||
q3 *= recipNorm;
|
|
||||||
|
|
||||||
|
|
||||||
*pitch = asin(-2 * q1 * q3 + 2 * q0* q2); // pitch
|
|
||||||
*roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1); // roll
|
|
||||||
*yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3); //yaw
|
|
||||||
|
|
||||||
*pitch *= RAD_TO_DEG;
|
|
||||||
*yaw *= RAD_TO_DEG;
|
|
||||||
// Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is
|
|
||||||
// 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19
|
|
||||||
// - http://www.ngdc.noaa.gov/geomag-web/#declination
|
|
||||||
*yaw -= 8.5;
|
|
||||||
*roll *= RAD_TO_DEG;
|
|
||||||
|
|
||||||
///Serial.printf("%f %f %f \r\n", pitch, roll, yaw);
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Fast inverse square-root
|
|
||||||
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
|
||||||
float invSqrt(float x) {
|
|
||||||
float halfx = 0.5f * x;
|
|
||||||
float y = x;
|
|
||||||
long i = *(long*)&y;
|
|
||||||
i = 0x5f3759df - (i>>1);
|
|
||||||
y = *(float*)&i;
|
|
||||||
y = y * (1.5f - (halfx * y * y));
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
//====================================================================================================
|
|
||||||
// END OF CODE
|
|
||||||
//====================================================================================================
|
|
@ -1,33 +0,0 @@
|
|||||||
//=====================================================================================================
|
|
||||||
// MahonyAHRS.h
|
|
||||||
//=====================================================================================================
|
|
||||||
//
|
|
||||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
|
||||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
|
||||||
//
|
|
||||||
// Date Author Notes
|
|
||||||
// 29/09/2011 SOH Madgwick Initial release
|
|
||||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
|
||||||
//
|
|
||||||
//=====================================================================================================
|
|
||||||
#ifndef MahonyAHRS_h
|
|
||||||
#define MahonyAHRS_h
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
|
||||||
// Variable declaration
|
|
||||||
|
|
||||||
extern volatile float twoKp; // 2 * proportional gain (Kp)
|
|
||||||
extern volatile float twoKi; // 2 * integral gain (Ki)
|
|
||||||
//volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------
|
|
||||||
// Function declarations
|
|
||||||
|
|
||||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
|
|
||||||
//void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az);
|
|
||||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw);
|
|
||||||
float invSqrt(float x);
|
|
||||||
#endif
|
|
||||||
//=====================================================================================================
|
|
||||||
// End of file
|
|
||||||
//=====================================================================================================
|
|
@ -782,6 +782,7 @@ const char JSON_SNS_RANGE[] PROGMEM = ",\"%s\":{\"" D_JSON_RANGE "\":%d}";
|
|||||||
const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}";
|
const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}";
|
||||||
|
|
||||||
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
|
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
|
||||||
|
const char S_LOG_I2C_FOUND_AT_PORT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x (" D_PORT " %d)";
|
||||||
|
|
||||||
const char S_RSLT_POWER[] PROGMEM = D_RSLT_POWER;
|
const char S_RSLT_POWER[] PROGMEM = D_RSLT_POWER;
|
||||||
const char S_RSLT_RESULT[] PROGMEM = D_RSLT_RESULT;
|
const char S_RSLT_RESULT[] PROGMEM = D_RSLT_RESULT;
|
||||||
|
@ -607,6 +607,7 @@
|
|||||||
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
// #define USE_EZORGB // [I2cDriver55] Enable support for EZO's RGB sensor (+0k5 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||||
// #define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
// #define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code)
|
||||||
// #define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code)
|
// #define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code)
|
||||||
|
// #define USE_MPU6886 // [I2cDriver58] Enable MPU6686 - found in M5Stack - support 2 I2C buses on ESP32 (I2C address 0x68) (+2k code)
|
||||||
|
|
||||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||||
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
|
||||||
|
@ -2053,10 +2053,19 @@ void I2cSetActive(uint32_t addr, uint32_t count = 1)
|
|||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("I2C: Active %08X,%08X,%08X,%08X"), i2c_active[0], i2c_active[1], i2c_active[2], i2c_active[3]);
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("I2C: Active %08X,%08X,%08X,%08X"), i2c_active[0], i2c_active[1], i2c_active[2], i2c_active[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2cSetActiveFound(uint32_t addr, const char *types)
|
void I2cSetActiveFound(uint32_t addr, const char *types, uint32_t bus = 0);
|
||||||
|
void I2cSetActiveFound(uint32_t addr, const char *types, uint32_t bus)
|
||||||
{
|
{
|
||||||
I2cSetActive(addr);
|
I2cSetActive(addr);
|
||||||
|
#ifdef ESP32
|
||||||
|
if (0 == bus) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr);
|
||||||
|
} else {
|
||||||
|
AddLog(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT_PORT, types, addr, bus);
|
||||||
|
}
|
||||||
|
#else
|
||||||
AddLog(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr);
|
AddLog(LOG_LEVEL_INFO, S_LOG_I2C_FOUND_AT, types, addr);
|
||||||
|
#endif // ESP32
|
||||||
}
|
}
|
||||||
|
|
||||||
bool I2cActive(uint32_t addr)
|
bool I2cActive(uint32_t addr)
|
||||||
@ -2068,14 +2077,24 @@ bool I2cActive(uint32_t addr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
bool I2cSetDevice(uint32_t addr, uint32_t bus = 0);
|
||||||
|
bool I2cSetDevice(uint32_t addr, uint32_t bus)
|
||||||
|
#else
|
||||||
bool I2cSetDevice(uint32_t addr)
|
bool I2cSetDevice(uint32_t addr)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#ifdef ESP32
|
||||||
|
TwoWire & myWire = (bus == 0) ? Wire : Wire1;
|
||||||
|
#else
|
||||||
|
TwoWire & myWire = Wire;
|
||||||
|
#endif
|
||||||
addr &= 0x7F; // Max I2C address is 127
|
addr &= 0x7F; // Max I2C address is 127
|
||||||
if (I2cActive(addr)) {
|
if (I2cActive(addr)) {
|
||||||
return false; // If already active report as not present;
|
return false; // If already active report as not present;
|
||||||
}
|
}
|
||||||
Wire.beginTransmission((uint8_t)addr);
|
myWire.beginTransmission((uint8_t)addr);
|
||||||
return (0 == Wire.endTransmission());
|
return (0 == myWire.endTransmission());
|
||||||
}
|
}
|
||||||
#endif // USE_I2C
|
#endif // USE_I2C
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ extern "C" {
|
|||||||
be_raise(vm, kTypeError, nullptr);
|
be_raise(vm, kTypeError, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Berry: `validwrite(address:int, reg:int, val:int, size:int) -> bool or nil`
|
// Berry: `write(address:int, reg:int, val:int, size:int) -> bool or nil`
|
||||||
int32_t b_wire_validwrite(struct bvm *vm);
|
int32_t b_wire_validwrite(struct bvm *vm);
|
||||||
int32_t b_wire_validwrite(struct bvm *vm) {
|
int32_t b_wire_validwrite(struct bvm *vm) {
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
@ -202,7 +202,7 @@ extern "C" {
|
|||||||
be_raise(vm, kTypeError, nullptr);
|
be_raise(vm, kTypeError, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Berry: `validread(address:int, reg:int, size:int) -> int or nil`
|
// Berry: `read(address:int, reg:int, size:int) -> int or nil`
|
||||||
int32_t b_wire_validread(struct bvm *vm);
|
int32_t b_wire_validread(struct bvm *vm);
|
||||||
int32_t b_wire_validread(struct bvm *vm) {
|
int32_t b_wire_validread(struct bvm *vm) {
|
||||||
int32_t top = be_top(vm); // Get the number of arguments
|
int32_t top = be_top(vm); // Get the number of arguments
|
||||||
|
@ -32,15 +32,14 @@ rtc better sync
|
|||||||
#include <esp_system.h>
|
#include <esp_system.h>
|
||||||
|
|
||||||
#include <AXP192.h>
|
#include <AXP192.h>
|
||||||
#include <MPU6886.h>
|
|
||||||
#include <BM8563_RTC.h>
|
#include <BM8563_RTC.h>
|
||||||
#include <soc/rtc.h>
|
#include <soc/rtc.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
#define XDRV_84 84
|
#define XDRV_84 84
|
||||||
|
|
||||||
struct CORE2_globs {
|
struct CORE2_globs {
|
||||||
AXP192 Axp;
|
AXP192 Axp;
|
||||||
MPU6886 Mpu;
|
|
||||||
BM8563_RTC Rtc;
|
BM8563_RTC Rtc;
|
||||||
bool ready;
|
bool ready;
|
||||||
bool tset;
|
bool tset;
|
||||||
@ -56,9 +55,6 @@ struct CORE2_ADC {
|
|||||||
float vbus_c;
|
float vbus_c;
|
||||||
float batt_c;
|
float batt_c;
|
||||||
float temp;
|
float temp;
|
||||||
int16_t x;
|
|
||||||
int16_t y;
|
|
||||||
int16_t z;
|
|
||||||
} core2_adc;
|
} core2_adc;
|
||||||
|
|
||||||
// cause SC card is needed by scripter
|
// cause SC card is needed by scripter
|
||||||
@ -75,9 +71,6 @@ void CORE2_Module_Init(void) {
|
|||||||
// motor voltage
|
// motor voltage
|
||||||
core2_globs.Axp.SetLDOVoltage(3,2000);
|
core2_globs.Axp.SetLDOVoltage(3,2000);
|
||||||
|
|
||||||
core2_globs.Mpu.Init();
|
|
||||||
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886");
|
|
||||||
|
|
||||||
core2_globs.Rtc.begin();
|
core2_globs.Rtc.begin();
|
||||||
I2cSetActiveFound(RTC_ADRESS, "RTC");
|
I2cSetActiveFound(RTC_ADRESS, "RTC");
|
||||||
|
|
||||||
@ -119,12 +112,6 @@ const char HTTP_CORE2[] PROGMEM =
|
|||||||
"{s}BATT Voltage" "{m}%s V" "{e}"
|
"{s}BATT Voltage" "{m}%s V" "{e}"
|
||||||
"{s}BATT Current" "{m}%s mA" "{e}"
|
"{s}BATT Current" "{m}%s mA" "{e}"
|
||||||
"{s}Chip Temperature" "{m}%s C" "{e}";
|
"{s}Chip Temperature" "{m}%s C" "{e}";
|
||||||
#ifdef USE_MPU6886
|
|
||||||
const char HTTP_CORE2_MPU[] PROGMEM =
|
|
||||||
"{s}MPU x" "{m}%d mg" "{e}"
|
|
||||||
"{s}MPU y" "{m}%d mg" "{e}"
|
|
||||||
"{s}MPU z" "{m}%d mg" "{e}";
|
|
||||||
#endif // USE_MPU6886
|
|
||||||
#endif // USE_WEBSERVER
|
#endif // USE_WEBSERVER
|
||||||
|
|
||||||
|
|
||||||
@ -146,18 +133,9 @@ void CORE2_WebShow(uint32_t json) {
|
|||||||
dtostrfd(core2_adc.temp, 2, tstring);
|
dtostrfd(core2_adc.temp, 2, tstring);
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"VBC\":%s,\"BC\":%s,\"CT\":%s"), vstring, cstring, bvstring, bcstring, tstring);
|
ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"VBC\":%s,\"BC\":%s,\"CT\":%s}"), vstring, cstring, bvstring, bcstring, tstring);
|
||||||
|
|
||||||
#ifdef USE_MPU6886
|
|
||||||
ResponseAppend_P(PSTR(",\"MPUX\":%d,\"MPUY\":%d,\"MPUZ\":%d"), core2_adc.x, core2_adc.y, core2_adc.z);
|
|
||||||
#endif
|
|
||||||
ResponseJsonEnd();
|
|
||||||
} else {
|
} else {
|
||||||
WSContentSend_PD(HTTP_CORE2, vstring, cstring, bvstring, bcstring, tstring);
|
WSContentSend_PD(HTTP_CORE2, vstring, cstring, bvstring, bcstring, tstring);
|
||||||
|
|
||||||
#ifdef USE_MPU6886
|
|
||||||
WSContentSend_PD(HTTP_CORE2_MPU, core2_adc.x, core2_adc.y, core2_adc.z);
|
|
||||||
#endif // USE_MPU6886
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,15 +320,6 @@ void CORE2_GetADC(void) {
|
|||||||
core2_adc.batt_c = core2_globs.Axp.GetBatCurrent();
|
core2_adc.batt_c = core2_globs.Axp.GetBatCurrent();
|
||||||
|
|
||||||
core2_adc.temp = core2_globs.Axp.GetTempInAXP192();
|
core2_adc.temp = core2_globs.Axp.GetTempInAXP192();
|
||||||
#ifdef USE_MPU6886
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
float z;
|
|
||||||
core2_globs.Mpu.getAccelData(&x, &y, &z);
|
|
||||||
core2_adc.x=x*1000;
|
|
||||||
core2_adc.y=y*1000;
|
|
||||||
core2_adc.z=z*1000;
|
|
||||||
#endif // USE_MPU6886
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
|
128
tasmota/xsns_85_mpu6886.ino
Normal file
128
tasmota/xsns_85_mpu6886.ino
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
xsns_84_tof10120.ino - TOF10120 sensor support for Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2021 Stephan Hadinger 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_I2C
|
||||||
|
#ifdef USE_MPU6886
|
||||||
|
|
||||||
|
#include <MPU6886.h>
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* MPU6886
|
||||||
|
* Internal chip found in M5Stack devices, using `Wire1` internal I2C bus
|
||||||
|
*
|
||||||
|
* I2C Address: 0x68
|
||||||
|
*
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XSNS_85 85
|
||||||
|
#define XI2C_58 58 // See I2CDEVICES.md
|
||||||
|
|
||||||
|
#define MPU6886_ADDRESS 0x68
|
||||||
|
|
||||||
|
struct {
|
||||||
|
MPU6886 Mpu;
|
||||||
|
bool ready = false;
|
||||||
|
int16_t ax=0, ay=0, az=0; // accelerator data
|
||||||
|
int16_t gyx=0, gyy=0, gyz=0; // accelerator data
|
||||||
|
} mpu6886_sensor;
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
const char HTTP_MPU6686[] PROGMEM =
|
||||||
|
"{s}MPU6686 acc_x" "{m}%3_f G" "{e}"
|
||||||
|
"{s}MPU6686 acc_y" "{m}%3_f G" "{e}"
|
||||||
|
"{s}MPU6686 acc_z" "{m}%3_f G" "{e}"
|
||||||
|
"{s}MPU6686 gyr_x" "{m}%i dps" "{e}"
|
||||||
|
"{s}MPU6686 gyr_y" "{m}%i dps" "{e}"
|
||||||
|
"{s}MPU6686 gyr_z" "{m}%i dps" "{e}"
|
||||||
|
;
|
||||||
|
|
||||||
|
void MPU6686_Show(uint32_t json) {
|
||||||
|
if (json) {
|
||||||
|
ResponseAppend_P(PSTR(",\"MPU6686\":{\"AX\":%i,\"AY\":%i,\"AZ\":%i,\"GX\":%i,\"GY\":%i,\"GZ\":%i}"),
|
||||||
|
mpu6886_sensor.ax, mpu6886_sensor.ay, mpu6886_sensor.az,
|
||||||
|
mpu6886_sensor.gyx, mpu6886_sensor.gyy, mpu6886_sensor.gyz);
|
||||||
|
} else {
|
||||||
|
float ax = mpu6886_sensor.ax / 1000.0f;
|
||||||
|
float ay = mpu6886_sensor.ay / 1000.0f;
|
||||||
|
float az = mpu6886_sensor.az / 1000.0f;
|
||||||
|
WSContentSend_PD(HTTP_MPU6686, &ax, &ay, &az,
|
||||||
|
mpu6886_sensor.gyx, mpu6886_sensor.gyy, mpu6886_sensor.gyz);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPU6686Detect(void) {
|
||||||
|
#ifdef ESP32
|
||||||
|
if (!I2cSetDevice(MPU6886_ADDRESS, 0)) {
|
||||||
|
if (!I2cSetDevice(MPU6886_ADDRESS, 1)) { return; } // check on bus 1
|
||||||
|
mpu6886_sensor.Mpu.setBus(1); // switch to bus 1
|
||||||
|
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886", 1);
|
||||||
|
} else {
|
||||||
|
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886", 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!I2cSetDevice(MPU6886_ADDRESS)) { return; }
|
||||||
|
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mpu6886_sensor.Mpu.Init();
|
||||||
|
mpu6886_sensor.ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MPU6886Every_Second(void) {
|
||||||
|
mpu6886_sensor.Mpu.getAccelDataInt(&mpu6886_sensor.ax, &mpu6886_sensor.ay, &mpu6886_sensor.az);
|
||||||
|
mpu6886_sensor.Mpu.getGyroDataInt(&mpu6886_sensor.gyx, &mpu6886_sensor.gyy, &mpu6886_sensor.gyz);
|
||||||
|
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, PSTR(">> Acc x=%i y=%i z=%i gx=%i gy=%i gz=%i"), mpu6886_sensor.ax, mpu6886_sensor.ay, mpu6886_sensor.az,
|
||||||
|
// mpu6886_sensor.gyx, mpu6886_sensor.gyy, mpu6886_sensor.gyz);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xsns85(uint8_t function) {
|
||||||
|
if (!I2cEnabled(XI2C_58)) { return false; }
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (FUNC_INIT == function) {
|
||||||
|
MPU6686Detect();
|
||||||
|
}
|
||||||
|
else if (mpu6886_sensor.ready) {
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_EVERY_SECOND:
|
||||||
|
MPU6886Every_Second();
|
||||||
|
break;
|
||||||
|
case FUNC_JSON_APPEND:
|
||||||
|
MPU6686_Show(1);
|
||||||
|
break;
|
||||||
|
#ifdef USE_WEBSERVER
|
||||||
|
case FUNC_WEB_SENSOR:
|
||||||
|
MPU6686_Show(0);
|
||||||
|
break;
|
||||||
|
#endif // USE_WEBSERVER
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_MPU6886
|
||||||
|
#endif // USE_I2C
|
Loading…
x
Reference in New Issue
Block a user