From 64db0b051a546fcd4cd5216ae158acd5f72c6a68 Mon Sep 17 00:00:00 2001 From: SeasonWings <79470909+SeasonWings@users.noreply.github.com> Date: Sun, 19 Dec 2021 17:13:07 +0800 Subject: [PATCH] Add files via upload --- samd21 chuni/include/README | 39 +++ samd21 chuni/lib/README | 46 ++++ samd21 chuni/platformio.ini | 17 ++ samd21 chuni/src/Adafruit_MPR121.cpp | 140 +++++++++++ samd21 chuni/src/Adafruit_MPR121.h | 93 ++++++++ samd21 chuni/src/main.cpp | 340 +++++++++++++++++++++++++++ samd21 chuni/src/mpr121-config.h | 54 +++++ samd21 chuni/src/mpr121-helper.cpp | 134 +++++++++++ samd21 chuni/src/mpr121-helper.h | 227 ++++++++++++++++++ samd21 chuni/test/README | 11 + 10 files changed, 1101 insertions(+) create mode 100644 samd21 chuni/include/README create mode 100644 samd21 chuni/lib/README create mode 100644 samd21 chuni/platformio.ini create mode 100644 samd21 chuni/src/Adafruit_MPR121.cpp create mode 100644 samd21 chuni/src/Adafruit_MPR121.h create mode 100644 samd21 chuni/src/main.cpp create mode 100644 samd21 chuni/src/mpr121-config.h create mode 100644 samd21 chuni/src/mpr121-helper.cpp create mode 100644 samd21 chuni/src/mpr121-helper.h create mode 100644 samd21 chuni/test/README diff --git a/samd21 chuni/include/README b/samd21 chuni/include/README new file mode 100644 index 0000000..45496b1 --- /dev/null +++ b/samd21 chuni/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/samd21 chuni/lib/README b/samd21 chuni/lib/README new file mode 100644 index 0000000..8c9c29c --- /dev/null +++ b/samd21 chuni/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/samd21 chuni/platformio.ini b/samd21 chuni/platformio.ini new file mode 100644 index 0000000..26e285c --- /dev/null +++ b/samd21 chuni/platformio.ini @@ -0,0 +1,17 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:sparkfun_samd21_dev_usb] +platform = atmelsam +board = sparkfun_samd21_dev_usb +framework = arduino +lib_deps = + nicohood/HID-Project@^2.8.2 + fastled/FastLED@^3.4.0 diff --git a/samd21 chuni/src/Adafruit_MPR121.cpp b/samd21 chuni/src/Adafruit_MPR121.cpp new file mode 100644 index 0000000..1db3764 --- /dev/null +++ b/samd21 chuni/src/Adafruit_MPR121.cpp @@ -0,0 +1,140 @@ +/*! + * @file Adafruit_MPR121.cpp + * + * @mainpage Adafruit MPR121 arduino driver + * + * @section intro_sec Introduction + * + * This is a library for the MPR121 I2C 12-chan Capacitive Sensor + * + * Designed specifically to work with the MPR121 sensor from Adafruit + * ----> https://www.adafruit.com/products/1982 + * + * These sensors use I2C to communicate, 2+ pins are required to + * interface + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * @section author Author + * + * Written by Limor Fried/Ladyada for Adafruit Industries. + * + * @section license License + * + * BSD license, all text here must be included in any redistribution. + */ + +#include "Adafruit_MPR121.h" +Adafruit_MPR121::Adafruit_MPR121() {} +boolean Adafruit_MPR121::begin(uint8_t i2caddr, TwoWire *theWire, + uint8_t touchThreshold, + uint8_t releaseThreshold) { + _i2caddr = i2caddr; + _wire = theWire; + _wire->begin(); + writeRegister(MPR121_SOFTRESET, 0x63); + delay(1); + writeRegister(MPR121_ECR, 0x0); + uint8_t c = readRegister8(MPR121_CONFIG2); + if (c != 0x24) + return false; + setThresholds(touchThreshold, releaseThreshold); + writeRegister(MPR121_MHDR, 0x01); + writeRegister(MPR121_NHDR, 0x01); + writeRegister(MPR121_NCLR, 0x01); + writeRegister(MPR121_FDLR, 0x00); + writeRegister(MPR121_MHDF, 0x01); + writeRegister(MPR121_NHDF, 0x01); + writeRegister(MPR121_NCLF, 0x01); + writeRegister(MPR121_FDLF, 0x00); + writeRegister(MPR121_NHDT, 0x00); + writeRegister(MPR121_NCLT, 0x00); + writeRegister(MPR121_FDLT, 0x00); + writeRegister(MPR121_DEBOUNCE, 0x01); + writeRegister(MPR121_CONFIG1, 0xF0); + writeRegister(MPR121_CONFIG2, 0x40); +#ifdef AUTOCONFIG + writeRegister(MPR121_AUTOCONFIG0, 0x0B); + writeRegister(MPR121_UPLIMIT, 200); + writeRegister(MPR121_TARGETLIMIT, 180); + writeRegister(MPR121_LOWLIMIT, 130); +#endif + byte ECR_SETTING = + B10000000 + 12; + writeRegister(MPR121_ECR, ECR_SETTING); + return true; +} +void Adafruit_MPR121::setThreshholds(uint8_t touch, uint8_t release) { + setThresholds(touch, release); +} +void Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t release) { + writeRegister(MPR121_ECR, 0x00); + for (uint8_t i = 0; i < 12; i++) { + writeRegister(MPR121_TOUCHTH_0 + 2 * i, touch); + writeRegister(MPR121_RELEASETH_0 + 2 * i, release); + } + writeRegister(MPR121_ECR, 0x8F); +} +uint16_t Adafruit_MPR121::filteredData(uint8_t t) { + if (t > 12) + return 0; + return readRegister16(MPR121_FILTDATA_0L + t * 2); +} +uint16_t Adafruit_MPR121::baselineData(uint8_t t) { + if (t > 12) + return 0; + uint16_t bl = readRegister8(MPR121_BASELINE_0 + t); + return (bl << 2); +} +uint16_t Adafruit_MPR121::touched(void) { + uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L); + return t & 0x0FFF; +} +uint8_t Adafruit_MPR121::readRegister8(uint8_t reg) { + _wire->beginTransmission(_i2caddr); + _wire->write(reg); + _wire->endTransmission(false); + _wire->requestFrom(_i2caddr, 1); + if (_wire->available() < 1) + return 0; + return (_wire->read()); +} +uint16_t Adafruit_MPR121::readRegister16(uint8_t reg) { + _wire->beginTransmission(_i2caddr); + _wire->write(reg); + _wire->endTransmission(false); + _wire->requestFrom(_i2caddr, 2); + if (_wire->available() < 2) + return 0; + uint16_t v = _wire->read(); + v |= ((uint16_t)_wire->read()) << 8; + return v; +} +void Adafruit_MPR121::writeRegister(uint8_t reg, uint8_t value) { + bool stop_required = true; + uint8_t ECR = readRegister8( + MPR121_ECR); + if (reg == MPR121_ECR || (0x73 <= reg && reg <= 0x7A)) { + stop_required = false; + } + if (stop_required) { + _wire->beginTransmission(_i2caddr); + _wire->write(MPR121_ECR); + _wire->write((byte)0x00); + _wire->endTransmission(); + } + + _wire->beginTransmission(_i2caddr); + _wire->write((uint8_t)reg); + _wire->write((uint8_t)(value)); + _wire->endTransmission(); + + if (stop_required) { + _wire->beginTransmission(_i2caddr); + _wire->write(MPR121_ECR); + _wire->write(ECR); + _wire->endTransmission(); + } +} diff --git a/samd21 chuni/src/Adafruit_MPR121.h b/samd21 chuni/src/Adafruit_MPR121.h new file mode 100644 index 0000000..088014c --- /dev/null +++ b/samd21 chuni/src/Adafruit_MPR121.h @@ -0,0 +1,93 @@ +/*! + * @file Adafruit_MPR121.cpp + * + * @mainpage Adafruit MPR121 arduino driver + * + * @section intro_sec Introduction + * + * This is a library for the MPR121 I2C 12-chan Capacitive Sensor + * + * Designed specifically to work with the MPR121 sensor from Adafruit + * ----> https://www.adafruit.com/products/1982 + * + * These sensors use I2C to communicate, 2+ pins are required to + * interface + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * @section author Author + * + * Written by Limor Fried/Ladyada for Adafruit Industries. + * + * @section license License + * + * BSD license, all text here must be included in any redistribution. + */ + +#ifndef ADAFRUIT_MPR121_H +#define ADAFRUIT_MPR121_H +#include "Arduino.h" +#include +#define MPR121_I2CADDR_DEFAULT 0x5A +#define MPR121_TOUCH_THRESHOLD_DEFAULT 0 +#define MPR121_RELEASE_THRESHOLD_DEFAULT 0 +enum { + MPR121_TOUCHSTATUS_L = 0x00, + MPR121_TOUCHSTATUS_H = 0x01, + MPR121_FILTDATA_0L = 0x04, + MPR121_FILTDATA_0H = 0x05, + MPR121_BASELINE_0 = 0x1E, + MPR121_MHDR = 0x2B, + MPR121_NHDR = 0x2C, + MPR121_NCLR = 0x2D, + MPR121_FDLR = 0x2E, + MPR121_MHDF = 0x2F, + MPR121_NHDF = 0x30, + MPR121_NCLF = 0x31, + MPR121_FDLF = 0x32, + MPR121_NHDT = 0x33, + MPR121_NCLT = 0x34, + MPR121_FDLT = 0x35, + MPR121_TOUCHTH_0 = 0x41, + MPR121_RELEASETH_0 = 0x42, + MPR121_DEBOUNCE = 0x5B, + MPR121_CONFIG1 = 0x5C, + MPR121_CONFIG2 = 0x5D, + MPR121_CHARGECURR_0 = 0x5F, + MPR121_CHARGETIME_1 = 0x6C, + MPR121_ECR = 0x5E, + MPR121_AUTOCONFIG0 = 0x7B, + MPR121_AUTOCONFIG1 = 0x7C, + MPR121_UPLIMIT = 0x7D, + MPR121_LOWLIMIT = 0x7E, + MPR121_TARGETLIMIT = 0x7F, + MPR121_GPIODIR = 0x76, + MPR121_GPIOEN = 0x77, + MPR121_GPIOSET = 0x78, + MPR121_GPIOCLR = 0x79, + MPR121_GPIOTOGGLE = 0x7A, + MPR121_SOFTRESET = 0x80, +}; +class Adafruit_MPR121 { +public: + Adafruit_MPR121(); + boolean begin(uint8_t i2caddr = MPR121_I2CADDR_DEFAULT, + TwoWire *theWire = &Wire, + uint8_t touchThreshold = MPR121_TOUCH_THRESHOLD_DEFAULT, + uint8_t releaseThreshold = MPR121_RELEASE_THRESHOLD_DEFAULT); + uint16_t filteredData(uint8_t t); + uint16_t baselineData(uint8_t t); + uint8_t readRegister8(uint8_t reg); + uint16_t readRegister16(uint8_t reg); + void writeRegister(uint8_t reg, uint8_t value); + uint16_t touched(void); + void setThreshholds(uint8_t touch, uint8_t release) + __attribute__((deprecated)); + void setThresholds(uint8_t touch, uint8_t release); +private: + int8_t _i2caddr; + TwoWire *_wire; +}; +#endif diff --git a/samd21 chuni/src/main.cpp b/samd21 chuni/src/main.cpp new file mode 100644 index 0000000..6bd888d --- /dev/null +++ b/samd21 chuni/src/main.cpp @@ -0,0 +1,340 @@ +////基础定义//// +#ifndef _BV +#define _BV(bit) (1 << (bit)) +#endif +#include "mpr121-helper.h" +#include "mpr121-config.h" +#include "HID-Project.h" +#include "FastLED.h" +#include +#define Serial SerialUSB + +////MPR定义//// +#define CA_ADDR 0x5A//mpr121A +#define CB_ADDR 0x5B//mpr121B +#define CC_ADDR 0x5C//mpr121C + +uint16_t LastA = -1, CurrA, LastB = -1, CurrB, LastC = -1, CurrC; //存储触摸的状态 +static MPR121 capA, capB, capC; //mpr121 + +////Air定义//// +int calibrationCounter; +bool calibrated; +uint16_t thresholds[6]; +uint16_t maxReadings[6]; + +#define AIR_LED_DELAY 96//轮询延迟(推荐96,128,192,256这几个数值) +#define AIR_INPUT_SENSITIVITY 0.3//红外敏感度(推荐0.1-0.3之间) +#define CALIBRATION_SAMPLES 256//(校准采样数) +#define SKIP_SAMPLES 256//(校准跳过采样数) + + +int ir_INPUT_pins[6] = {3,4,5,2,6,11};//定义轮询发射红外针脚 +int ir_sensor_pins[6] = {A0,A1,A2,A3,A4,A5};//定义轮询接收红外针脚 + + +////按键定义//// +KeyboardKeycode KeyCode[32] = {//键值列表 + KEY_3, KEY_D, KEY_W, KEY_X, KEY_2, KEY_S, KEY_Q, KEY_Z, KEY_1, KEY_A, + KEY_6, KEY_H, KEY_T, KEY_B, KEY_5, KEY_G, KEY_R, KEY_V, KEY_4, KEY_F, KEY_E, KEY_C, + KEY_I, KEY_COMMA, KEY_8, KEY_K, KEY_U, KEY_M, KEY_7, KEY_J, KEY_Y, KEY_N, + }; + +KeyboardKeycode AirKeys[6] = {KEY_SLASH, KEY_PERIOD, KEY_QUOTE, KEY_SEMICOLON, KEY_RIGHT_BRACE, KEY_LEFT_BRACE}; + +////串口定义//// +#define CLAMP(val, lo, hi) (val < lo ? lo : (val > hi ? hi : val)) +static bool auto_scan = false;//串口用标记 + + +////灯光定义//// + +#define LED_NUM 31 //灯数量 +#define LED_PIN 7 //灯针脚 +uint16_t LED_BRI= 0xFF; //灯亮度 +#define Aqua CRGB::Cyan +#define Red CRGB::Red +CRGB leds[LED_NUM]; +//Air灯光定义 +#define air_right_pin 10 +#define air_right_num 6 +CRGB AIR_RIGHT[air_right_num]; + +#define air_left_pin 8 +#define air_left_num 6 +CRGB AIR_LEFT[air_left_num]; + +////函数指针//// +void (*MainCheck)(); +void (*AirSensor)(); + +////灯效函数//// + +void LEDset() { + FastLED.addLeds(leds, LED_NUM); + FastLED.addLeds(AIR_RIGHT, air_right_num); + FastLED.addLeds(AIR_LEFT, air_left_num); + +} + +uint8_t air_rgb_loop = 0; +uint16_t air_colour = 0; +uint16_t air_colour_state = 0; +void air_rgb_Serial() { + AIR_RIGHT[air_rgb_loop] = CHSV(air_colour_state, 255, 255); + AIR_LEFT[air_rgb_loop] = CHSV(air_colour_state, 255, 255); + air_rgb_loop++; + if (air_rgb_loop >= 6) { + air_colour_state++; + air_rgb_loop = 0; + } + if (air_colour_state > 255) { + air_colour_state = 0; + } + for (uint8_t i = 0; i < 6; i++) { + if (ir_sensor_pins[i]) { + AIR_RIGHT[i] = 0xffffff; + AIR_LEFT[i] = 0xffffff; + } + } + FastLED[1].showLeds(255); + FastLED[2].showLeds(255); +} + +//////////Air////////// + +void AirSetup() { + calibrated = false; + for (int i = 0; i < 6; i++) { + maxReadings[i] = 0; + } + for (int i = 0; i < 6; i++) { + pinMode(ir_sensor_pins[i], INPUT_PULLUP); + pinMode(ir_INPUT_pins[i], OUTPUT); + } +} + +void turnOffLight() {//关闭灯光函数 + for(int i = 0;i < 6;i++){ + digitalWrite(ir_INPUT_pins[i], LOW); + } +} + +void changeLight(int light) {//切换红外发射轮询 + switch (light) { + case 0: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("一号发射"); + //Serial.print("\t"); + break; + case 1: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("二号发射"); + //Serial.print("\t"); + break; + case 2: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("三号发射"); + //Serial.print("\t"); + break; + case 3: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("四号发射"); + //Serial.print("\t"); + break; + case 4: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("五号发射"); + //Serial.print("\t"); + break; + case 5: + digitalWrite(ir_INPUT_pins[light], HIGH); + //Serial.print("六号发射"); + //Serial.print("\t"); + break; + default: + turnOffLight(); + break; + } +} + + + +uint16_t getValue(int sensor) {//获取开灯函数 + changeLight(sensor);// 开灯 + delayMicroseconds(AIR_LED_DELAY);// 加上延迟保证完全开启 + return analogRead(ir_sensor_pins[sensor]);//读数值 +} + +bool getSensorState(int sensor) { + turnOffLight();//关灯 + delayMicroseconds(AIR_LED_DELAY);//加上延迟保证完全关闭 + int enviroment = analogRead(ir_sensor_pins[sensor]);//读取环境数值 + int value = getValue(sensor);//读取开灯数值 + + Serial.print(sensor); + Serial.print("\t"); + Serial.print(value); + Serial.print("\t"); + Serial.print(enviroment); + Serial.print("\t"); + Serial.print(value - enviroment); + Serial.print("\t"); + Serial.print(value - enviroment + 200); + Serial.print("\t"); + Serial.print(maxReadings[sensor]); + Serial.print("\t"); + Serial.print(thresholds[sensor]); + Serial.println(); + + //把读数减去环境数值和校准数值比较后返回布尔值,+200为防止负数的比较(这里我不知道咋搞可以防止负数,就这样了) + return (value - enviroment + 200) < (thresholds[sensor] + 200); + +} + +void AirCalibrate() { + // 跳过开头采样 + for (int i = 0; i < SKIP_SAMPLES; i++) { + for (int sensor = 0; sensor < 6; sensor++) { + getValue(sensor); + turnOffLight(); + } + } + //开始校准 + for (int i = 0; i < CALIBRATION_SAMPLES; i++) { + for (int sensor = 0; sensor < 6; sensor++) { + turnOffLight();//关灯 + delayMicroseconds(AIR_LED_DELAY);//加上延迟保证完全关闭 + int enviroment = analogRead(ir_sensor_pins[sensor]);//读取环境数值 + int value = getValue(sensor) - enviroment;//读取开灯数值 + if (value > maxReadings[sensor])//记录最高读数 + maxReadings[sensor] = value; + } + Serial.println(); + } + for (int i = 0; i < 6; i++) {//通过敏感度生成阈值 + thresholds[i] = (AIR_INPUT_SENSITIVITY * maxReadings[i]); + } + calibrated = true;//完成校准 +} + +void AirCheck(){ + if (calibrated){ + for (int i = 0; i < 6; i++){ + if (getSensorState(i)){ + NKROKeyboard.press(AirKeys[i]); + } else if (!getSensorState(i)){ + NKROKeyboard.release(AirKeys[i]); + } + } + } +} +void NoAir(){}//关闭Air + +//////////触摸////////// +void MprCheck() {////触摸扫描(按键) + bool change = false; + CurrA = capA.touched(); + if (CurrA != LastA) { + for (uint8_t i = 0; i < 10; i++) { + if ((CurrA & _BV(i))) { + NKROKeyboard.press(KeyCode[i + 22]); + if(i%2==0){ + leds[i] = Red;} + else if(i%2==1){ + leds[i-1] = Red;} + } else if (!(CurrA & _BV(i))) { + NKROKeyboard.release(KeyCode[i + 22]); + if(i%2==0){ + leds[i] = Aqua;} + else if(i%2==1){ + leds[i] = Red;} + } + } + change = true; + LastA = CurrA; + } + CurrB = capB.touched(); + if (CurrB != LastB) { + for (uint8_t i = 0; i < 12; i++) { + if ((CurrB & _BV(i))) { + NKROKeyboard.press(KeyCode[i + 10]); + if(i%2==0){ + leds[i + 10] = Red;} + else if(i%2==1){ + leds[i + 10 - 1] = Red;} + } else if (!(CurrB & _BV(i))) { + NKROKeyboard.release(KeyCode[i + 10]); + if(i%2==0){ + leds[i + 10] = Aqua;} + else if(i%2==1){ + leds[i + 10] = Red;} + } + } + change = true; + LastB = CurrB; + } + CurrC = capC.touched(); + if (CurrC != LastC) { + for (uint8_t i = 0; i < 10; i++) { + if ((CurrC & _BV(i))) { + NKROKeyboard.press(KeyCode[i]); + if(i%2==0){ + leds[i + 22] = Red;} + else if(i%2==1){ + leds[i + 22 - 1] = Red;} + } else if (!(CurrC & _BV(i))) { + NKROKeyboard.release(KeyCode[i]); + if(i%2==0){ + leds[i + 22] = Aqua;} + else if(i%2==1){ + leds[i + 22] = Red;} + } + } + change = true; + LastC = CurrC; + } + if (change) { + NKROKeyboard.send(); + FastLED[0].show(leds, LED_NUM, LED_BRI); + } + AirCheck(); +} + +//////启动函数////// + +void TouchSetup() {//触摸初始化 + capA.begin(CA_ADDR); + capA.init(); + capA.run(); + + capB.begin(CB_ADDR); + capB.init(); + capB.run(); + + capC.begin(CC_ADDR); + capC.init(); + capC.run(); + + Wire.setClock(800000);//如果感觉有明显延迟,调成1600000 +} + + +void setup() { + //串口启动// + SerialUSB.begin(115200); + SerialUSB.setTimeout(0); + //灯带添加// + LEDset(); + TouchSetup();//触摸启动 + AirSetup();//Air启动 + AirCalibrate();//Air校准 +} + + + +void loop() { + MprCheck(); +} + + diff --git a/samd21 chuni/src/mpr121-config.h b/samd21 chuni/src/mpr121-config.h new file mode 100644 index 0000000..bab036a --- /dev/null +++ b/samd21 chuni/src/mpr121-config.h @@ -0,0 +1,54 @@ +#ifndef _MPR121_CONFIG_H +#define _MPR121_CONFIG_H + +#include "mpr121-helper.h" + +// Thresholds +#define MPR121CONF_TTH 5///< 触发阈值 +#define MPR121CONF_RTH 5///< 释放阈值 +// De-bounce +#define MPR121CONF_DR 3 ///< 松开样本采集数 +#define MPR121CONF_DT 2 ///< 按下样本采集数 +// AFE Configurations +#define MPR121CONF_FFI MPR121_FFI_6 ///< 一层过滤采样数 +#define MPR121CONF_CDC 16 ///< 充放电电流 +#define MPR121CONF_CDT MPR121_CDT_500NS ///< 充放电时间 +#define MPR121CONF_SFI MPR121_SFI_4 ///< 二层过滤 +#define MPR121CONF_ESI MPR121_ESI_1MS ///< 二层过滤采样间隔时间 +// ECR Configurations +#define MPR121CONF_CL MPR121_CL_INIT1 ///< 启用基线动态校准 +#define MPR121CONF_ELEPROX MPR121_ELEPROX_0 ///< 接近检测电极,禁用 +#define MPR121CONF_ELE 12 ///< touch detection electrodes +// 基线动态校准 +#define MPR121CONF_MHDR 1 ///< 上升最大变化值 +#define MPR121CONF_NHDR 8 ///< 上升幅度 +#define MPR121CONF_NCLR 1 ///< 上升修正样本个数 +#define MPR121CONF_FDLR 0 ///< 修正前等待样本个数 +#define MPR121CONF_MHDF 1 ///< 下降最大变化值 +#define MPR121CONF_NHDF 1 ///< 下降幅度 +#define MPR121CONF_NCLF 16 ///< 下降修正样本个数 +#define MPR121CONF_FDLF 2 ///< 修正前等待样本个数 +#define MPR121CONF_NHDT 0 ///< Touched Noise Half Delta +#define MPR121CONF_NCLT 0 ///< Touched Noise Count Limit +#define MPR121CONF_FDLT 0 ///< Touched Filter Delay Count Limit +// 自动初始化 +//#define MPR121CONF_USL 200 ///< 上限,MPR121_UPLIMIT,((Vdd - 0.7)/Vdd) * 256,200 +//#define MPR121CONF_LSL 130 ///< 下限,MPR121_LOWLIMIT,UPLIMIT * 0.65,130 +//#define MPR121CONF_TL 180 ///< 目标,MPR121_TARGETLIMIT,UPLIMIT * 0.9,180 + +#define MPR121CONF_USL 156 ///< 上限,MPR121_UPLIMIT,((Vdd - 0.7)/Vdd) * 256 +#define MPR121CONF_LSL 101 ///< 下限,MPR121_LOWLIMIT,UPLIMIT * 0.65 +#define MPR121CONF_TL 140 ///< 目标,MPR121_TARGETLIMIT,UPLIMIT * 0.9 + +#define MPR121CONF_AFES MPR121CONF_FFI ///< 必须设置为FFI +#define MPR121CONF_RETRY MPR121_RETRY_0 ///< 重试次数 +#define MPR121CONF_BVA MPR121CONF_CL ///< 必须设置为CL +#define MPR121CONF_ARE 1 ///< 开启自动重配置 +#define MPR121CONF_ACE 1 ///< 开启自动配置 +#define MPR121CONF_SCTS 1 ///< 跳过充电时间 +//中断用,全部关闭 +#define MPR121CONF_ACFIE 0 ///< Auto-configuration fail interrupt enable +#define MPR121CONF_ARFIE 0 ///< Auto-reconfiguration fail interrupt enable +#define MPR121CONF_OORIE 0 ///< Out-of-range interrupt enable + +#endif diff --git a/samd21 chuni/src/mpr121-helper.cpp b/samd21 chuni/src/mpr121-helper.cpp new file mode 100644 index 0000000..d447c13 --- /dev/null +++ b/samd21 chuni/src/mpr121-helper.cpp @@ -0,0 +1,134 @@ +/* + Support class for MPR121, giving full control over the device efficiently. + + Modifications licensed under University of Illinois/NCSA Open Source License + + Copyright (c) 2020 Fang Lu + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal with the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the documentation + and/or other materials provided with the distribution. + - Neither the names of Fang Lu, nor the names of its contributors may be + used to endorse or promote products derived from this Software without + specific prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + WITH THE SOFTWARE. + + Original license text from Adafruit + + @file Adafruit_MPR121.cpp + + This is a library for the MPR121 12-Channel Capacitive Sensor + + Designed specifically to work with the MPR121 board. + + Pick one up today in the adafruit shop! + ------> https://www.adafruit.com/product/1982 + + These sensors use I2C to communicate, 2+ pins are required to interface + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Limor Fried/Ladyada (Adafruit Industries). + + BSD license, all text above must be included in any redistribution +*/ + +#include "mpr121-helper.h" +#include "mpr121-config.h" + + + +void MPR121::begin(uint8_t addr, TwoWire *wire) { + _i2caddr = addr; + _wire = wire; + _wire->begin(); +} + +void MPR121::init() { + // soft reset + reset(); + delay(1); + stop(); + + writeRegisterRaw(MPR121_MHDR, MPR121CONF_MHDR, false); + writeRegisterRaw(MPR121_NHDR, MPR121CONF_NHDR, false); + writeRegisterRaw(MPR121_NCLR, MPR121CONF_NCLR, false); + writeRegisterRaw(MPR121_FDLR, MPR121CONF_FDLR, false); + writeRegisterRaw(MPR121_MHDF, MPR121CONF_MHDF, false); + writeRegisterRaw(MPR121_NHDF, MPR121CONF_NHDF, false); + writeRegisterRaw(MPR121_NCLF, MPR121CONF_NCLF, false); + writeRegisterRaw(MPR121_FDLF, MPR121CONF_FDLF, false); + writeRegisterRaw(MPR121_NHDT, MPR121CONF_NHDT, false); + writeRegisterRaw(MPR121_NCLT, MPR121CONF_NCLT, false); + writeRegisterRaw(MPR121_FDLT, MPR121CONF_FDLT, false); + // Skip ELEPROX baseline controls + for (int i = 0; i < 12; i++) {//设置触发阈值和充放电流时间 + writeRegisterRaw(MPR121_TOUCHTH(i), MPR121CONF_TTH, false); + writeRegisterRaw(MPR121_RELEASETH(i), MPR121CONF_RTH, false); + writeRegisterRaw(MPR121_CDC(i), 0, false); + writeRegisterRaw(MPR121_CDT(i), 0, false); + } + writeRegisterRaw(MPR121_DEBOUNCE, (MPR121CONF_DR << 4) | MPR121CONF_DT, false); //设置采样数 + writeRegisterRaw(MPR121_AFE1, (MPR121CONF_FFI << 6) | MPR121CONF_CDC, false); + writeRegisterRaw(MPR121_AFE2, (MPR121CONF_CDT << 5) | (MPR121CONF_SFI << 3) | MPR121CONF_ESI, false); + _ecr = (MPR121CONF_CL << 6) | (MPR121CONF_ELEPROX << 4) | MPR121CONF_ELE; // Write when start + // Skip GPIO configurations + writeRegisterRaw(MPR121_AUTOCONF0, + (MPR121CONF_AFES << 6) | (MPR121CONF_RETRY << 4) | (MPR121CONF_BVA << 2) | (MPR121CONF_ARE << 1) | MPR121CONF_ACE, + false); + writeRegisterRaw(MPR121_AUTOCONF1, + (MPR121CONF_SCTS << 7) | (MPR121CONF_OORIE << 2) | (MPR121CONF_ARFIE << 1) | MPR121CONF_ACFIE, + false); + writeRegisterRaw(MPR121_USL, MPR121CONF_USL, false); + writeRegisterRaw(MPR121_LSL, MPR121CONF_LSL, false); + writeRegisterRaw(MPR121_TL, MPR121CONF_TL, false); + + // Manually call run to start +} + +void MPR121::writeRegister(uint8_t reg, uint8_t value) {//相同 + // MPR121 must be put in Stop Mode to write to most registers + bool stop_required = true; + if (reg == MPR121_ECR || (0x73 <= reg && reg <= 0x7A)) { + stop_required = false; + } + if (stop_required) { + _wire->beginTransmission(_i2caddr); + _wire->write(MPR121_ECR); + _wire->write(0x00); // clear this register to set stop modus + _wire->endTransmission(false); + } + + _wire->beginTransmission(_i2caddr); + _wire->write((uint8_t)reg); + _wire->write((uint8_t)value); + _wire->endTransmission(!stop_required); + + if (stop_required) { + _wire->beginTransmission(_i2caddr); + _wire->write(MPR121_ECR); + _wire->write(_ecr); // restore ECR + _wire->endTransmission(true); + } +} + +//#endif diff --git a/samd21 chuni/src/mpr121-helper.h b/samd21 chuni/src/mpr121-helper.h new file mode 100644 index 0000000..f79c780 --- /dev/null +++ b/samd21 chuni/src/mpr121-helper.h @@ -0,0 +1,227 @@ +/* + Support class for MPR121, giving full control over the device efficiently. + + Modifications licensed under University of Illinois/NCSA Open Source License + + Copyright (c) 2020 Fang Lu + All rights reserved. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal with the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the documentation + and/or other materials provided with the distribution. + - Neither the names of Fang Lu, nor the names of its contributors may be + used to endorse or promote products derived from this Software without + specific prior written permission. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + WITH THE SOFTWARE. + + Original license text from Adafruit + + @file Adafruit_MPR121.h + + This is a library for the MPR121 12-Channel Capacitive Sensor + + Designed specifically to work with the MPR121 board. + + Pick one up today in the adafruit shop! + ------> https://www.adafruit.com/product/1982 + + These sensors use I2C to communicate, 2+ pins are required to interface + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Limor Fried/Ladyada (Adafruit Industries). + + BSD license, all text above must be included in any redistribution +*/ + +#ifndef _MPR121_HELPER_H +#define _MPR121_HELPER_H + +#include "Arduino.h" +#include + +// Configuration values + +#define MPR121_FFI_6 0 +#define MPR121_FFI_10 1 +#define MPR121_FFI_18 2 +#define MPR121_FFI_34 3 + +#define MPR121_CDT_INHERIT 0 +#define MPR121_CDT_500NS 1 +#define MPR121_CDT_1US 2 +#define MPR121_CDT_2US 3 +#define MPR121_CDT_4US 4 +#define MPR121_CDT_8US 5 +#define MPR121_CDT_16US 6 +#define MPR121_CDT_32US 7 + +#define MPR121_SFI_4 0 +#define MPR121_SFI_6 0 +#define MPR121_SFI_10 0 +#define MPR121_SFI_18 0 + +#define MPR121_ESI_1MS 0 +#define MPR121_ESI_2MS 1 +#define MPR121_ESI_4MS 2 +#define MPR121_ESI_8MS 3 +#define MPR121_ESI_16MS 4 +#define MPR121_ESI_32MS 5 +#define MPR121_ESI_64MS 6 +#define MPR121_ESI_128MS 7 + +#define MPR121_CL_NONE 0 +#define MPR121_CL_LOCK 1 +#define MPR121_CL_INIT1 2 +#define MPR121_CL_INTI2 3 + +#define MPR121_ELEPROX_0 0 +#define MPR121_ELEPROX_2 1 +#define MPR121_ELEPROX_4 2 +#define MPR121_ELEPROX_12 3 + +#define MPR121_AFES_6 0 +#define MPR121_AFES_10 1 +#define MPR121_AFES_18 2 +#define MPR121_AFES_34 3 + +#define MPR121_RETRY_0 0 +#define MPR121_RETRY_2 1 +#define MPR121_RETRY_4 2 +#define MPR121_RETRY_8 3 + +// Device register map + +#define MPR121_TOUCHSTATUS_L 0x00 +#define MPR121_TOUCHSTATUS_H 0x01 +#define MPR121_OOR_L 0x02 +#define MPR121_OOR_R 0x03 +#define MPR121_FILTDATA(ch) (0x04 + 2*(ch)) +#define MPR121_BASELINE(ch) (0x1E + (ch)) +#define MPR121_MHDR 0x2B +#define MPR121_NHDR 0x2C +#define MPR121_NCLR 0x2D +#define MPR121_FDLR 0x2E +#define MPR121_MHDF 0x2F +#define MPR121_NHDF 0x30 +#define MPR121_NCLF 0x31 +#define MPR121_FDLF 0x32 +#define MPR121_NHDT 0x33 +#define MPR121_NCLT 0x34 +#define MPR121_FDLT 0x35 +#define MPR121_MHDPROXR 0x36 +#define MPR121_HHDPROXR 0x37 +#define MPR121_NCLPROXR 0x38 +#define MPR121_FDLPROXR 0x39 +#define MPR121_MHDPROXF 0x3A +#define MPR121_NHDPROXF 0x3B +#define MPR121_NCLPROXF 0x3C +#define MPR121_FDLPROXF 0x3D +#define MPR121_NHDPROXT 0x3E +#define MPR121_NCLPROXT 0x3F +#define MPR121_FDLPROXT 0x40 +#define MPR121_TOUCHTH(ch) (0x41 + 2*(ch)) +#define MPR121_RELEASETH(ch) (0x42 + 2*(ch)) +#define MPR121_DEBOUNCE 0x5B +#define MPR121_AFE1 0x5C +#define MPR121_AFE2 0x5D +#define MPR121_ECR 0x5E +#define MPR121_CDC(ch) (0x5F + (ch)) +#define MPR121_CDT(ch) (0x6C + ((ch)>>1)) +#define MPR121_CTL0 0x73 +#define MPR121_CTL1 0x74 +#define MPR121_DAT 0x75 +#define MPR121_DIR 0x76 +#define MPR121_EN 0x77 +#define MPR121_SET 0x78 +#define MPR121_CLR 0x79 +#define MPR121_TOG 0x7A +#define MPR121_AUTOCONF0 0x7B +#define MPR121_AUTOCONF1 0x7C +#define MPR121_USL 0x7D +#define MPR121_LSL 0x7E +#define MPR121_TL 0x7F +#define MPR121_SRST 0x80 + +#define MPR121_I2CADDR_DEFAULT 0x5A + +class MPR121 { + public: + MPR121() {} + + void begin(uint8_t addr = MPR121_I2CADDR_DEFAULT, TwoWire *wire = &Wire); + void init(); + + uint8_t readRegister8(uint8_t rs) {//相同 + _wire->beginTransmission(_i2caddr); + _wire->write(rs); + _wire->endTransmission(false); + _wire->requestFrom(_i2caddr, 1); + if (_wire->available() < 1) + return 0; + return _wire->read(); + } + uint16_t readRegister16(uint8_t rs) {//相同 + _wire->beginTransmission(_i2caddr); + _wire->write(rs); + _wire->endTransmission(false); + _wire->requestFrom(_i2caddr, 2); + if (_wire->available() < 2) + return 0; + uint16_t v = _wire->read(); + v |= ((uint16_t)_wire->read()) << 8; + return v; + } + void writeRegister(uint8_t rd, uint8_t value); + void writeRegisterRaw(uint8_t rd, uint8_t value, bool stop = true) { + _wire->beginTransmission(_i2caddr); + _wire->write(rd); + _wire->write(value); + _wire->endTransmission(stop); + } + + void stop() { + writeRegisterRaw(MPR121_ECR, 0x00); + } + void run() { + writeRegisterRaw(MPR121_ECR, _ecr); + } + void reset() { + writeRegisterRaw(MPR121_SRST, 0x63); + } + + uint16_t filteredData(uint8_t ch) { + return readRegister16(MPR121_FILTDATA(ch)); + } + uint16_t baselineData(uint8_t ch) { + return ((uint16_t)readRegister8(MPR121_BASELINE(ch))) << 2; + } + uint16_t touched() { + return readRegister16(MPR121_TOUCHSTATUS_L); + } + + private: + int8_t _i2caddr; + TwoWire *_wire; + uint8_t _ecr; +}; + +#endif diff --git a/samd21 chuni/test/README b/samd21 chuni/test/README new file mode 100644 index 0000000..e7d1588 --- /dev/null +++ b/samd21 chuni/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html