mirror of https://github.com/arendst/Tasmota.git
first integration of the driver into the TASMOTA-repo
This commit is contained in:
parent
070843200f
commit
0924d7a2e6
|
@ -529,6 +529,8 @@
|
|||
#define D_SENSOR_RFRECV "RFrecv"
|
||||
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||
#define D_SENSOR_MGC3130_XFER "MGC3130 Xfer"
|
||||
#define D_SENSOR_MGC3130_RESET "MGC3130 Reset"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
|
|
@ -299,6 +299,7 @@
|
|||
// #define USE_SI1145 // Enable SI1145/46/47 sensor (I2C address 0x60) (+1k code)
|
||||
#define USE_LM75AD // Enable LM75AD sensor (I2C addresses 0x48 - 0x4F) (+0k5 code)
|
||||
// #define USE_APDS9960 // Enable APDS9960 Proximity Sensor (I2C address 0x39). Disables SHT and VEML6070 (+4k7 code)
|
||||
#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42)
|
||||
// #define USE_MCP230xx // Enable MCP23008/MCP23017 - Must define I2C Address in #define USE_MCP230xx_ADDR below - range 0x20 - 0x27 (+4k7 code)
|
||||
// #define USE_MCP230xx_ADDR 0x20 // Enable MCP23008/MCP23017 I2C Address to use (Must be within range 0x20 through 0x27 - set according to your wired setup)
|
||||
// #define USE_MCP230xx_OUTPUT // Enable MCP23008/MCP23017 OUTPUT support through sensor29 commands (+1k5 code)
|
||||
|
|
|
@ -133,6 +133,8 @@ enum UserSelectablePins {
|
|||
GPIO_RFRECV, // RF receiver
|
||||
GPIO_TUYA_TX, // Tuya Serial interface
|
||||
GPIO_TUYA_RX, // Tuya Serial interface
|
||||
GPIO_MGC3130_XFER, // MGC3130 Transfer
|
||||
GPIO_MGC3130_RESET, // MGC3130 Reset
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
|
@ -190,7 +192,8 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
||||
D_SENSOR_TX20_TX "|"
|
||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
|
||||
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX;
|
||||
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX "|"
|
||||
D_SENSOR_MGC3130_XFER "|" D_SENSOR_MGC3130_RESET;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -426,7 +429,11 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||
#endif
|
||||
#ifdef USE_TUYA_DIMMER
|
||||
GPIO_TUYA_TX, // Tuya Serial interface
|
||||
GPIO_TUYA_RX // Tuya Serial interface
|
||||
GPIO_TUYA_RX, // Tuya Serial interface
|
||||
#endif
|
||||
#ifdef USE_MGC3130
|
||||
GPIO_MGC3130_XFER,
|
||||
GPIO_MGC3130_RESET
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,651 @@
|
|||
/*
|
||||
xsns_91_MGC3130.ino - Support for I2C MGC3130 Electric Field Sensor for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Christian Baars & Theo Arends
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
//#define USE_MGC3130
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_MGC3130
|
||||
|
||||
#define XSNS_36 36
|
||||
|
||||
/*********************************************************************************************\
|
||||
* MGC3130 - Electric Field Sensor
|
||||
*
|
||||
* Adaption for TASMOTA: Christian Baars
|
||||
* based on various implementations from Pimoroni, jspark311, hoverlabs and scjurgen
|
||||
*
|
||||
* I2C Address: 0x42
|
||||
*
|
||||
* Wiring: SDA/SCL as usual plus RESET and TRANSFER -> 4 Wires
|
||||
\*********************************************************************************************/
|
||||
|
||||
#warning **** MGC3130: It is recommended to disable all unneeded I2C-drivers ****
|
||||
|
||||
#define MGC3130_I2C_ADDR 0x42
|
||||
|
||||
#define MGC3130_xfer pin[GPIO_MGC3130_XFER]
|
||||
#define MGC3130_reset pin[GPIO_MGC3130_RESET]
|
||||
|
||||
|
||||
bool MGC3130_type = false;
|
||||
char MGC3130stype[8];
|
||||
|
||||
|
||||
#define MGC3130_SYSTEM_STATUS 0x15
|
||||
#define MGC3130_REQUEST_MSG 0x06
|
||||
#define MGC3130_FW_VERSION 0x83
|
||||
#define MGC3130_SET_RUNTIME 0xA2
|
||||
#define MGC3130_SENSOR_DATA 0x91
|
||||
|
||||
|
||||
#define MGC3130_GESTURE_GARBAGE 1
|
||||
#define MGC3130_FLICK_WEST_EAST 2
|
||||
#define MGC3130_FLICK_EAST_WEST 3
|
||||
#define MGC3130_FLICK_SOUTH_NORTH 4
|
||||
#define MGC3130_FLICK_NORTH_SOUTH 5
|
||||
#define MGC3130_CIRCLE_CLOCKWISE 6 //not active in airwheel mode
|
||||
#define MGC3130_CIRCLE_CCLOCKWISE 7 //not active in airwheel mode
|
||||
|
||||
#define MGC3130_MIN_ROTVALUE 0
|
||||
#define MGC3130_MAX_ROTVALUE 1023
|
||||
#define MGC3130_MIN_ZVALUE 32768 // if we fly under the radar, we do not report anything
|
||||
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_MGC_3130_SNS[] PROGMEM = "%s"
|
||||
"{s}" "%s" "{m}%s{e}"
|
||||
"{s}" "HwRev" "{m}%u.%u{e}"
|
||||
"{s}" "loaderVer" "{m}%u.%u{e}"
|
||||
"{s}" "platVer" "{m}%u{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* MGC3130
|
||||
*
|
||||
* Programmer : MGC3130 Datasheet
|
||||
\*********************************************************************************************/
|
||||
#pragma pack(1)
|
||||
union MGC3130_Union{
|
||||
uint8_t buffer[132];
|
||||
struct
|
||||
{
|
||||
// header
|
||||
uint8_t msgSize; // in Bytes
|
||||
uint8_t flag; //not used
|
||||
uint8_t counter; // cyclic counter of transmitted messages
|
||||
uint8_t id; // 0x91 for data output
|
||||
// payload
|
||||
struct {
|
||||
uint8_t DSPStatus:1;
|
||||
uint8_t gestureInfo:1;
|
||||
uint8_t touchInfo:1;
|
||||
uint8_t airWheelInfo:1;
|
||||
uint8_t xyzPosition:1;
|
||||
uint8_t noisePower:1;
|
||||
uint8_t reserved:2;
|
||||
uint8_t electrodeConfiguration:3;
|
||||
uint8_t CICData:1;
|
||||
uint8_t SDData:1;
|
||||
uint16_t reserved2:3;
|
||||
} outputConfigMask;
|
||||
uint8_t timestamp;
|
||||
struct {
|
||||
uint8_t positionValid:1;
|
||||
uint8_t airWheelValid:1;
|
||||
uint8_t rawDataValid:1;
|
||||
uint8_t noisePowerValid:1;
|
||||
uint8_t environmentalNoise:1;
|
||||
uint8_t clipping:1;
|
||||
uint8_t reserved:1;
|
||||
uint8_t DSPRunning:1;
|
||||
} systemInfo;
|
||||
uint16_t dspInfo;
|
||||
struct {
|
||||
uint8_t gestureCode:8; // 0 -> No Gesture
|
||||
uint8_t reserved:4;
|
||||
uint8_t gestureType:4; //garbage, flick or circular
|
||||
uint8_t edgeFlick:1;
|
||||
uint16_t reserved2:14;
|
||||
uint8_t gestureInProgress:1; // If "1" Gesture recognition in progress
|
||||
} gestureInfo;
|
||||
struct {
|
||||
uint8_t touchSouth:1;
|
||||
uint8_t touchWest:1; //:Bit 01
|
||||
uint8_t touchNorth:1; //:Bit 02
|
||||
uint8_t touchEast:1; //:Bit 03
|
||||
uint8_t touchCentre:1; //:Bit 04
|
||||
uint8_t tapSouth:1; //:Bit 05
|
||||
uint8_t tapWest:1; //:Bit 06
|
||||
uint8_t tapNorth:1; //:Bit 07
|
||||
uint8_t tapEast :1; //:Bit 08
|
||||
uint8_t tapCentre:1; //:Bit 09
|
||||
uint8_t doubleTapSouth:1; //:Bit 10
|
||||
uint8_t doubleTapWest:1; //:Bit 11
|
||||
uint8_t doubleTapNorth:1; //:Bit 12
|
||||
uint8_t doubleTapEast:1; //:Bit 13
|
||||
uint8_t doubleTapCentre:1; //:Bit 14
|
||||
uint8_t reserved:1; //:Bit 15
|
||||
uint8_t touchCounter; //period between the time when the hand starts moving to touch until it is detected
|
||||
uint8_t reserved2;
|
||||
} touchInfo;
|
||||
int8_t airWheel;
|
||||
uint8_t reserved;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t z;
|
||||
float noisePower;
|
||||
float CICData[4]; // uncalibrated sensor data
|
||||
float SDData[4]; // signal deviation
|
||||
} out;
|
||||
struct {
|
||||
uint8_t header[3];
|
||||
// payload
|
||||
uint8_t valid;
|
||||
uint8_t hwRev[2];
|
||||
uint8_t parameterStartAddr;
|
||||
uint8_t loaderVersion[2];
|
||||
uint8_t loaderPlatform;
|
||||
uint8_t fwStartAddr;
|
||||
char fwVersion[120];
|
||||
} fw;
|
||||
struct{
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
uint16_t error;
|
||||
uint32_t reserved;
|
||||
uint32_t reserved1;
|
||||
} status;
|
||||
} MGC_data;
|
||||
#pragma pack()
|
||||
|
||||
char MGC3130_currentGesture[12];
|
||||
|
||||
int8_t MGC3130_delta, MGC3130_lastrotation = 0;
|
||||
int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0;
|
||||
|
||||
uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0;
|
||||
|
||||
uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0;
|
||||
char MGC3130_firmwareInfo[20];
|
||||
|
||||
uint8_t MGC3130_touchTimeout = 0;
|
||||
uint16_t MGC3130_touchCounter = 1; // measure how long you touch the surface in loop cycles
|
||||
uint32_t MGC3130_touchTimeStamp = millis();
|
||||
bool MGC3130_triggeredByTouch = false;
|
||||
|
||||
uint8_t MGC3130_mode = 1; // 1-gesture; 2-airwheel; 3-position
|
||||
|
||||
|
||||
// predefined messages
|
||||
uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
|
||||
uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
|
||||
|
||||
void MGC3130_triggerTele(){
|
||||
mqtt_data[0] = '\0';
|
||||
if (MqttShowSensor()) {
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
#ifdef USE_RULES
|
||||
RulesTeleperiod(); // Allow rule based HA messages
|
||||
#endif // USE_RULES
|
||||
}
|
||||
}
|
||||
|
||||
void MGC3130_handleSensorData(){
|
||||
if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){
|
||||
if (MGC3130_handleTouch()){
|
||||
MGC3130_triggeredByTouch = true;
|
||||
MGC3130_triggerTele();
|
||||
}
|
||||
}
|
||||
|
||||
if(MGC3130_mode == 1){
|
||||
if( MGC_data.out.outputConfigMask.gestureInfo && MGC_data.out.gestureInfo.gestureCode > 0){
|
||||
MGC3130_handleGesture();
|
||||
MGC3130_triggerTele();
|
||||
}
|
||||
}
|
||||
if(MGC3130_mode == 2){
|
||||
if(MGC_data.out.outputConfigMask.airWheelInfo && MGC_data.out.systemInfo.airWheelValid){
|
||||
MGC3130_handleAirWheel();
|
||||
MGC3130_triggerTele();
|
||||
}
|
||||
}
|
||||
if(MGC3130_mode == 3){
|
||||
if(MGC_data.out.systemInfo.positionValid && (MGC_data.out.z > MGC3130_MIN_ZVALUE)){
|
||||
MGC3130_triggerTele();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MGC3130_sendMessage(uint8_t data[], uint8_t length){
|
||||
Wire.beginTransmission(MGC3130_I2C_ADDR);
|
||||
Wire.write(data,length);
|
||||
Wire.endTransmission();
|
||||
delay(2);
|
||||
MGC3130_receiveMessage();
|
||||
}
|
||||
|
||||
|
||||
void MGC3130_handleGesture(){
|
||||
//char log[LOGSZ];
|
||||
char edge[5];
|
||||
if (MGC_data.out.gestureInfo.edgeFlick){
|
||||
snprintf_P(edge, sizeof(edge), PSTR("ED_"));
|
||||
}
|
||||
else{
|
||||
snprintf_P(edge, sizeof(edge), PSTR(""));
|
||||
}
|
||||
switch(MGC_data.out.gestureInfo.gestureCode){
|
||||
case MGC3130_GESTURE_GARBAGE:
|
||||
//snprintf_P(log, sizeof(log), PSTR("NONE"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("NONE"));
|
||||
break;
|
||||
case MGC3130_FLICK_WEST_EAST:
|
||||
//snprintf_P(log, sizeof(log), PSTR("%sFL_WE"), edge);
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_WE"), edge);
|
||||
break;
|
||||
case MGC3130_FLICK_EAST_WEST:
|
||||
//snprintf_P(log, sizeof(log), PSTR("%sFL_EW"), edge);
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_EW"), edge);
|
||||
break;
|
||||
case MGC3130_FLICK_SOUTH_NORTH:
|
||||
//snprintf_P(log, sizeof(log), PSTR("%sFL_SN"), edge);
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_SN"), edge);
|
||||
break;
|
||||
case MGC3130_FLICK_NORTH_SOUTH:
|
||||
//snprintf_P(log, sizeof(log), PSTR("%sFL_NS"), edge);
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("%sFL_NS"), edge);
|
||||
break;
|
||||
case MGC3130_CIRCLE_CLOCKWISE:
|
||||
//snprintf_P(log, sizeof(log), PSTR("CW"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CW"));
|
||||
break;
|
||||
case MGC3130_CIRCLE_CCLOCKWISE:
|
||||
//snprintf_P(log, sizeof(log), PSTR("CCW"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("CCW"));
|
||||
break;
|
||||
}
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
|
||||
bool MGC3130_handleTouch(){
|
||||
//char log[LOGSZ];
|
||||
bool success = false; // if we find a touch of higher order, we are done
|
||||
if (MGC_data.out.touchInfo.doubleTapCentre && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("DTAP_CENTRE"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_C"));
|
||||
MGC3130_touchTimeout = 5;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.doubleTapEast && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("DTAP_EAST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_E"));
|
||||
MGC3130_touchTimeout = 5;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.doubleTapNorth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("DTAP_NORTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_N"));
|
||||
MGC3130_touchTimeout = 5;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.doubleTapWest && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("DTAP_WEST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_W"));
|
||||
MGC3130_touchTimeout = 5;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.doubleTapSouth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("DTAP_SOUTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("DT_S"));
|
||||
MGC3130_touchTimeout = 5;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
if (MGC_data.out.touchInfo.tapCentre && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TAP_CENTRE"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_C"));
|
||||
MGC3130_touchTimeout = 2;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.tapEast && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TAP_EAST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_E"));
|
||||
MGC3130_touchTimeout = 2;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.tapNorth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TAP_NORTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_N"));
|
||||
MGC3130_touchTimeout = 2;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.tapWest && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TAP_WEST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_W"));
|
||||
MGC3130_touchTimeout = 2;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.tapSouth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TAP_SOUTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TP_S"));
|
||||
MGC3130_touchTimeout = 2;
|
||||
success = true;
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.touchCentre && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TOUCH_CENTRE"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_C"));
|
||||
success = true;
|
||||
MGC3130_touchCounter++; // This will reset to 0 after touching for approx. 1h and 50 minutes ;)
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.touchEast && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TOUCH_EAST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_E"));
|
||||
success = true;
|
||||
MGC3130_touchCounter++;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.touchNorth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TOUCH_NORTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_N"));
|
||||
success = true;
|
||||
MGC3130_touchCounter++;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.touchWest && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TOUCH_WEST"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_W"));
|
||||
success = true;
|
||||
MGC3130_touchCounter++;
|
||||
}
|
||||
else if (MGC_data.out.touchInfo.touchSouth && !success){
|
||||
//snprintf_P(log, sizeof(log), PSTR("TOUCH_SOUTH"));
|
||||
snprintf_P(MGC3130_currentGesture, sizeof(MGC3130_currentGesture), PSTR("TH_S"));
|
||||
success = true;
|
||||
MGC3130_touchCounter++;
|
||||
}
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, log);
|
||||
return success;
|
||||
}
|
||||
|
||||
void MGC3130_handleAirWheel(){
|
||||
MGC3130_delta = MGC_data.out.airWheel - MGC3130_lastrotation;
|
||||
MGC3130_lastrotation = MGC_data.out.airWheel;
|
||||
|
||||
MGC3130_rotValue = MGC3130_rotValue + MGC3130_delta;
|
||||
if(MGC3130_rotValue < MGC3130_MIN_ROTVALUE){
|
||||
MGC3130_rotValue = MGC3130_MIN_ROTVALUE;
|
||||
}
|
||||
if(MGC3130_rotValue > MGC3130_MAX_ROTVALUE){
|
||||
MGC3130_rotValue = MGC3130_MAX_ROTVALUE;
|
||||
}
|
||||
}
|
||||
|
||||
void MGC3130_handleSystemStatus(){
|
||||
//Serial.println("Got System status");
|
||||
}
|
||||
|
||||
bool MGC3130_receiveMessage(){
|
||||
if(MGC3130_readData()){
|
||||
switch(MGC_data.out.id){
|
||||
case MGC3130_SENSOR_DATA:
|
||||
MGC3130_handleSensorData();
|
||||
break;
|
||||
case MGC3130_SYSTEM_STATUS:
|
||||
MGC3130_handleSystemStatus();
|
||||
break;
|
||||
case MGC3130_FW_VERSION:
|
||||
hwRev[0] = MGC_data.fw.hwRev[1];
|
||||
hwRev[1] = MGC_data.fw.hwRev[0];
|
||||
loaderVersion[0] = MGC_data.fw.loaderVersion[0];
|
||||
loaderVersion[1] = MGC_data.fw.loaderVersion[1];
|
||||
loaderPlatform = MGC_data.fw.loaderPlatform;
|
||||
snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion);
|
||||
MGC3130_firmwareInfo[20] = '\0';
|
||||
// Serial.print(MGC3130_firmwareInfo);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MGC3130_readData()
|
||||
{
|
||||
bool success = false;
|
||||
if (!digitalRead(MGC3130_xfer)){
|
||||
pinMode(MGC3130_xfer, OUTPUT);
|
||||
digitalWrite(MGC3130_xfer, LOW);
|
||||
Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); // request usual data output
|
||||
|
||||
MGC_data.buffer[0] = 4; // read at least header, but update after first read anyway
|
||||
unsigned char i = 0;
|
||||
while(Wire.available() && (i < MGC_data.buffer[0])){
|
||||
MGC_data.buffer[i] = Wire.read();
|
||||
i++;
|
||||
}
|
||||
digitalWrite(MGC3130_xfer, HIGH);
|
||||
pinMode(MGC3130_xfer, INPUT);
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void MGC3130_nextMode(){
|
||||
if (MGC3130_mode < 3){
|
||||
MGC3130_mode++;
|
||||
}
|
||||
else{
|
||||
MGC3130_mode = 1;
|
||||
}
|
||||
switch(MGC3130_mode){ // there is more to be done in the future
|
||||
case 1:
|
||||
MGC3130_sendMessage(MGC3130disableAirwheel,16);
|
||||
break;
|
||||
case 2:
|
||||
MGC3130_sendMessage(MGC3130enableAirwheel,16);
|
||||
break;
|
||||
case 3:
|
||||
MGC3130_sendMessage(MGC3130disableAirwheel,16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MGC3130_loop()
|
||||
{
|
||||
if(MGC3130_touchTimeout > 0){
|
||||
MGC3130_touchTimeout--;
|
||||
}
|
||||
MGC3130_receiveMessage();
|
||||
}
|
||||
|
||||
|
||||
bool MGC3130_detect(void)
|
||||
{
|
||||
if (MGC3130_type){
|
||||
return true;
|
||||
}
|
||||
|
||||
pinMode(MGC3130_xfer, INPUT_PULLUP);
|
||||
pinMode(MGC3130_reset, OUTPUT);
|
||||
digitalWrite(MGC3130_reset, LOW);
|
||||
delay(10);
|
||||
digitalWrite(MGC3130_reset, HIGH);
|
||||
delay(50);
|
||||
|
||||
boolean success = false;
|
||||
success = MGC3130_receiveMessage(); // This should read the firmware info
|
||||
if (success) {
|
||||
strcpy_P(MGC3130stype, PSTR("MGC3130"));
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, MGC3130stype, MGC3130_I2C_ADDR);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
MGC3130_currentGesture[0] = '\0';
|
||||
MGC3130_type = true;
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("MGC3130 did not respond at address 0x%x"), MGC3130_I2C_ADDR);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MGC3130_show(boolean json)
|
||||
{
|
||||
if (!MGC3130_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
char status_chr[2];
|
||||
if(MGC_data.out.systemInfo.DSPRunning){
|
||||
sprintf (status_chr, "1");
|
||||
}
|
||||
else{
|
||||
sprintf (status_chr, "0");
|
||||
}
|
||||
|
||||
|
||||
if (json) {
|
||||
if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch)
|
||||
{
|
||||
if(MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"),
|
||||
mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64);
|
||||
MGC3130_lastSentX = MGC_data.out.x;
|
||||
MGC3130_lastSentY = MGC_data.out.y;
|
||||
MGC3130_lastSentZ = MGC_data.out.z;
|
||||
}
|
||||
}
|
||||
MGC3130_triggeredByTouch = false;
|
||||
|
||||
if (MGC3130_mode == 2){
|
||||
if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue);
|
||||
MGC3130_lastSentRotValue = MGC3130_rotValue;
|
||||
}
|
||||
}
|
||||
|
||||
if (MGC3130_currentGesture[0] != '\0'){
|
||||
if (millis() - MGC3130_touchTimeStamp > 220 ){
|
||||
MGC3130_touchCounter = 1;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter);
|
||||
MGC3130_currentGesture[0] = '\0';
|
||||
MGC3130_touchTimeStamp = millis();
|
||||
}
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
else {
|
||||
if (true){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_MGC_3130_SNS, mqtt_data, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform );
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* Command Sensor91
|
||||
*
|
||||
* Command | Payload | Description
|
||||
* ---------|---------|--------------------------
|
||||
* Sensor91 | | ...
|
||||
* Sensor91 | 0 | Next Mode - cycle through the modes
|
||||
* Sensor91 | 1 | Gesture Mode
|
||||
* Sensor91 | 2 | Airwheel Mode
|
||||
* Sensor91 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool MGC3130CommandSensor()
|
||||
{
|
||||
boolean serviced = true;
|
||||
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 0: // cycle through the modes
|
||||
MGC3130_nextMode();
|
||||
break;
|
||||
case 1: // gesture & touch
|
||||
MGC3130_mode = 1;
|
||||
MGC3130_sendMessage(MGC3130disableAirwheel,16);
|
||||
break;
|
||||
case 2: // airwheel & touch
|
||||
MGC3130_mode = 2;
|
||||
MGC3130_sendMessage(MGC3130enableAirwheel,16);
|
||||
break;
|
||||
case 3: // position & touch
|
||||
MGC3130_mode = 3;
|
||||
MGC3130_sendMessage(MGC3130disableAirwheel,16);
|
||||
break;
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean Xsns36(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
if ((FUNC_INIT == function) && (pin[GPIO_MGC3130_XFER] < 99) && (pin[GPIO_MGC3130_RESET] < 99)) {
|
||||
MGC3130_detect();
|
||||
} else if (MGC3130_type) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
MGC3130_loop();
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_36 == XdrvMailbox.index) {
|
||||
result = MGC3130CommandSensor();
|
||||
}
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
MGC3130_show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_APPEND:
|
||||
MGC3130_show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // USE_MGC3130
|
||||
#endif // USE_I2C
|
Loading…
Reference in New Issue