├── .gitignore ├── LICENSE ├── README.md ├── include └── README ├── lib ├── Button │ ├── Button.cpp │ ├── Button.h │ ├── LICENSE │ ├── README.md │ └── library.properties ├── README ├── mpu6886 │ ├── MPU6886.cpp │ ├── MPU6886.h │ ├── MahonyAHRS.cpp │ └── MahonyAHRS.h └── rtc │ ├── cplus_RTC.cpp │ └── cplus_RTC.h ├── platformio.ini ├── src ├── main.cpp └── test │ ├── Icon.c │ ├── test.cpp │ ├── test.h │ ├── test_ble.cpp │ ├── test_imu.cpp │ ├── test_io.cpp │ ├── test_ir.cpp │ ├── test_key.cpp │ ├── test_lcd.cpp │ ├── test_mic.cpp │ ├── test_rtc.cpp │ └── test_wifi.cpp └── test └── README /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 M5Stack 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # M5StickCPlus2-UserDemo 2 | M5StickCPlus2 user demo for hardware evaluation. 3 | 4 | ## Tool Chains 5 | 6 | [PlatformIO](https://platformio.org/) 7 | 8 | ## Build 9 | 10 | - Upload firmware 11 | - Upload filesystem image 12 | -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /lib/Button/Button.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Button - a small library for Arduino to handle button debouncing 3 | 4 | MIT licensed. 5 | */ 6 | 7 | #include "Button.h" 8 | #include 9 | 10 | Button::Button(uint8_t pin, uint16_t debounce_ms) 11 | : _pin(pin) 12 | , _delay(debounce_ms) 13 | , _state(HIGH) 14 | , _ignore_until(0) 15 | , _has_changed(false) 16 | { 17 | } 18 | 19 | void Button::begin() 20 | { 21 | pinMode(_pin, INPUT_PULLUP); 22 | } 23 | 24 | // 25 | // public methods 26 | // 27 | 28 | bool Button::read() 29 | { 30 | // ignore pin changes until after this delay time 31 | if (_ignore_until > millis()) 32 | { 33 | // ignore any changes during this period 34 | } 35 | 36 | // pin has changed 37 | else if (digitalRead(_pin) != _state) 38 | { 39 | _ignore_until = millis() + _delay; 40 | _state = !_state; 41 | _has_changed = true; 42 | } 43 | 44 | return _state; 45 | } 46 | 47 | // has the button been toggled from on -> off, or vice versa 48 | bool Button::toggled() 49 | { 50 | read(); 51 | return has_changed(); 52 | } 53 | 54 | // mostly internal, tells you if a button has changed after calling the read() function 55 | bool Button::has_changed() 56 | { 57 | if (_has_changed) 58 | { 59 | _has_changed = false; 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | // has the button gone from off -> on 66 | bool Button::pressed() 67 | { 68 | return (read() == PRESSED && has_changed()); 69 | } 70 | 71 | // has the button gone from on -> off 72 | bool Button::released() 73 | { 74 | return (read() == RELEASED && has_changed()); 75 | } 76 | -------------------------------------------------------------------------------- /lib/Button/Button.h: -------------------------------------------------------------------------------- 1 | /* 2 | Button - a small library for Arduino to handle button debouncing 3 | 4 | MIT licensed. 5 | */ 6 | 7 | #ifndef Button_h 8 | #define Button_h 9 | #include "Arduino.h" 10 | 11 | class Button 12 | { 13 | public: 14 | Button(uint8_t pin, uint16_t debounce_ms = 100); 15 | void begin(); 16 | bool read(); 17 | bool toggled(); 18 | bool pressed(); 19 | bool released(); 20 | bool has_changed(); 21 | 22 | const static bool PRESSED = LOW; 23 | const static bool RELEASED = HIGH; 24 | 25 | private: 26 | uint8_t _pin; 27 | uint16_t _delay; 28 | bool _state; 29 | uint32_t _ignore_until; 30 | bool _has_changed; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /lib/Button/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Michael D K Adams 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/Button/README.md: -------------------------------------------------------------------------------- 1 | Button 2 | ====== 3 | 4 | * Author: Michael Adams () 5 | * Copyright (C) 2016 Michael D K Adams. 6 | * Released under the MIT license. 7 | 8 | Button is a tiny library to make reading buttons very simple. It handles debouncing automatically, and monitoring of state. 9 | 10 | Motivation 11 | ---------- 12 | Ahh buttons. Ahh debouncing! Sometimes you really wish you could ignore all the mechanics of debouncing, reading inputs, monitoring state, and just say... `if (button.pressed())` and know that it'll only run once each time you press a button. 13 | 14 | Or how about `if (button.released())`, or `button.toggled()`. It is such a simple concept, but in practice you need to set up timers, monitor input puts, set pullups, etc etc. On anything more than the most simple example, that can become quite a headache. 15 | 16 | So fed up with all that I figured there had to be a better way. This library is the result. 17 | 18 | Features 19 | -------- 20 | * Super simple API. 21 | * Handles debouncing. 22 | * Sets the pin mode automatically. 23 | * Lets you write code that triggers: 24 | ** based on the pin state (high or low) 25 | ** when a button is pressed 26 | ** when a button is released 27 | ** or when a button changes (i.e. pressing or releasing) 28 | 29 | Requirements 30 | ------------ 31 | * An Arduino — http://arduino.cc/ 32 | * A button 33 | 34 | Installation 35 | ------------ 36 | Download the ZIP archive (https://github.com/madleech/Button/zipball/master), then open the Arduino IDE and choose Sketch > Include Library > Add .ZIP Library... and select your downloaded file. 37 | 38 | You should now see in File > Examples > Button entires for the basic\_usage example. 39 | 40 | Code Examples 41 | ------------- 42 | Here is the 'basic\_usage' example program, included in the download: 43 | 44 | ```C++ 45 | #include 46 | 47 | Button button1(2); // Connect your button between pin 2 and GND 48 | Button button2(3); // Connect your button between pin 3 and GND 49 | Button button3(4); // Connect your button between pin 4 and GND 50 | 51 | void setup() { 52 | button1.begin(); 53 | button2.begin(); 54 | button3.begin(); 55 | 56 | while (!Serial) { }; // for Leos 57 | Serial.begin(9600); 58 | } 59 | 60 | void loop() { 61 | if (button1.pressed()) 62 | Serial.println("Button 1 pressed"); 63 | 64 | if (button2.released()) 65 | Serial.println("Button 2 released"); 66 | 67 | if (button3.toggled()) { 68 | if (button3.read() == Button::PRESSED) 69 | Serial.println("Button 3 has been pressed"); 70 | else 71 | Serial.println("Button 3 has been released"); 72 | } 73 | } 74 | ``` 75 | 76 | Documentation 77 | ------------- 78 | **Button(int pin)** 79 | Creates a new Button. 80 | 81 | **void begin()** 82 | Call this in your `setup` method to setup the button. All it does is set the correct pin mode. 83 | 84 | **bool pressed()** 85 | Returns true when _and only when_ the button is pressed. Until the button is released (in the debounced-sense of the word) this function won't return true again. So in effect, it returns true only while you are pressing the button, or to put it another way, it fires on a rising edge. 86 | 87 | **bool released()** 88 | Like `pressed()`, but round the other way. So if you hold down a button, and then release it... that is when it fires. 89 | 90 | **bool toggled()** 91 | Returns true whenever the button is pressed or released, i.e., its position is toggled. To find out what the position actually is, you can use the `read()` function. 92 | 93 | **bool read()** 94 | Returns the current debounced state of the button, i.e. Button::PRESSED or Button::RELEASED. 95 | 96 | **bool has_changed()** 97 | Returns whether the position/state of the button has changed after calling the previous read() function. Unlikely to be used except by Super Gurus. 98 | 99 | Quirks and Things to Keep in Mind 100 | --------------------------------- 101 | **Highs and lows, lows and highs** 102 | The easiest way to connect a switch on an Arduino is to connect it between an input pin and ground, and use the internal pullup resistor to make sure it doesn't float. This is fine and dandy, but it can get a bit confusing, as a "pressed" button is logic level: low, while a "released" button is logic level: high. 103 | 104 | So to make it a bit more obvious what you're talking about, you can use a couple of handy shortcuts: `Button::PRESSED` and `Button::RELEASED` which map to the expected values. 105 | 106 | License 107 | ------- 108 | Copyright (c) 2016 Michael D K Adams. http://www.michael.net.nz/ 109 | 110 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 111 | 112 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 113 | 114 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 115 | 116 | -------------------------------------------------------------------------------- /lib/Button/library.properties: -------------------------------------------------------------------------------- 1 | name=Button 2 | version=1.0.0 3 | author=Michael Adams 4 | maintainer=Michael Adams 5 | sentence=Button is a tiny library to make reading buttons very simple. 6 | paragraph=It handles debouncing automatically, and monitoring of state. 7 | category=Signal Input/Output 8 | url=http://utrainia.com/ 9 | architectures=* -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /lib/mpu6886/MPU6886.cpp: -------------------------------------------------------------------------------- 1 | #include "MPU6886.h" 2 | #include 3 | #include 4 | 5 | MPU6886::MPU6886() { 6 | } 7 | 8 | void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, 9 | uint8_t number_Bytes, uint8_t* read_Buffer) { 10 | Wire1.beginTransmission(driver_Addr); 11 | Wire1.write(start_Addr); 12 | Wire1.endTransmission(false); 13 | uint8_t i = 0; 14 | Wire1.requestFrom(driver_Addr, number_Bytes); 15 | 16 | //! Put read results in the Rx buffer 17 | while (Wire1.available()) { 18 | read_Buffer[i++] = Wire1.read(); 19 | } 20 | } 21 | 22 | void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, 23 | uint8_t number_Bytes, uint8_t* write_Buffer) { 24 | Wire1.beginTransmission(driver_Addr); 25 | Wire1.write(start_Addr); 26 | Wire1.write(*write_Buffer); 27 | Wire1.endTransmission(); 28 | } 29 | 30 | int MPU6886::Init(void) { 31 | unsigned char tempdata[1]; 32 | unsigned char regdata; 33 | 34 | // Wire1.begin(21, 22); 35 | 36 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata); 37 | if (tempdata[0] != 0x19) return -1; 38 | delay(1); 39 | 40 | regdata = 0x00; 41 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data); 42 | delay(10); 43 | 44 | regdata = (0x01 << 7); 45 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data); 46 | delay(10); 47 | 48 | regdata = (0x01 << 0); 49 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data); 50 | delay(10); 51 | 52 | regdata = 0x10; 53 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data); 54 | delay(1); 55 | 56 | regdata = 0x18; 57 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data); 58 | delay(1); 59 | 60 | regdata = 0x01; 61 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, ®data); 62 | delay(1); 63 | 64 | regdata = 0x05; 65 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1, ®data); 66 | delay(1); 67 | 68 | regdata = 0x00; 69 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 70 | delay(1); 71 | 72 | regdata = 0x00; 73 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG2, 1, ®data); 74 | delay(1); 75 | 76 | regdata = 0x00; 77 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data); 78 | delay(1); 79 | 80 | regdata = 0x00; 81 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, ®data); 82 | delay(1); 83 | 84 | regdata = 0x22; 85 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_PIN_CFG, 1, ®data); 86 | delay(1); 87 | 88 | regdata = 0x01; 89 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 90 | 91 | delay(100); 92 | getGres(); 93 | getAres(); 94 | return 0; 95 | } 96 | 97 | void MPU6886::getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az) { 98 | uint8_t buf[6]; 99 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_XOUT_H, 6, buf); 100 | 101 | *ax = ((int16_t)buf[0] << 8) | buf[1]; 102 | *ay = ((int16_t)buf[2] << 8) | buf[3]; 103 | *az = ((int16_t)buf[4] << 8) | buf[5]; 104 | } 105 | void MPU6886::getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz) { 106 | uint8_t buf[6]; 107 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_XOUT_H, 6, buf); 108 | 109 | *gx = ((uint16_t)buf[0] << 8) | buf[1]; 110 | *gy = ((uint16_t)buf[2] << 8) | buf[3]; 111 | *gz = ((uint16_t)buf[4] << 8) | buf[5]; 112 | } 113 | 114 | void MPU6886::getTempAdc(int16_t* t) { 115 | uint8_t buf[2]; 116 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_TEMP_OUT_H, 2, buf); 117 | 118 | *t = ((uint16_t)buf[0] << 8) | buf[1]; 119 | } 120 | 121 | //!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。 122 | void MPU6886::getAhrsData(float* pitch, float* roll, float* yaw) { 123 | float accX = 0; 124 | float accY = 0; 125 | float accZ = 0; 126 | 127 | float gyroX = 0; 128 | float gyroY = 0; 129 | float gyroZ = 0; 130 | 131 | getGyroData(&gyroX, &gyroY, &gyroZ); 132 | getAccelData(&accX, &accY, &accZ); 133 | 134 | MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, 135 | gyroZ * DEG_TO_RAD, accX, accY, accZ, pitch, roll, yaw); 136 | } 137 | 138 | void MPU6886::getGres() { 139 | switch (Gyscale) { 140 | // Possible gyro scales (and their register bit settings) are: 141 | case GFS_250DPS: 142 | gRes = 250.0 / 32768.0; 143 | break; 144 | case GFS_500DPS: 145 | gRes = 500.0 / 32768.0; 146 | break; 147 | case GFS_1000DPS: 148 | gRes = 1000.0 / 32768.0; 149 | break; 150 | case GFS_2000DPS: 151 | gRes = 2000.0 / 32768.0; 152 | break; 153 | } 154 | } 155 | 156 | void MPU6886::getAres() { 157 | switch (Acscale) { 158 | // Possible accelerometer scales (and their register bit settings) 159 | // are: 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11). Here's a 160 | // bit of an algorith to calculate DPS/(ADC tick) based on that 161 | // 2-bit value: 162 | case AFS_2G: 163 | aRes = 2.0 / 32768.0; 164 | break; 165 | case AFS_4G: 166 | aRes = 4.0 / 32768.0; 167 | break; 168 | case AFS_8G: 169 | aRes = 8.0 / 32768.0; 170 | break; 171 | case AFS_16G: 172 | aRes = 16.0 / 32768.0; 173 | break; 174 | } 175 | } 176 | 177 | void MPU6886::SetGyroFsr(Gscale scale) { 178 | // return IIC_Write_Byte(MPU_GYRO_CFG_REG,scale<<3);//设置陀螺仪满量程范围 179 | unsigned char regdata; 180 | regdata = (scale << 3); 181 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data); 182 | delay(10); 183 | 184 | Gyscale = scale; 185 | getGres(); 186 | } 187 | 188 | void MPU6886::SetAccelFsr(Ascale scale) { 189 | unsigned char regdata; 190 | regdata = (scale << 3); 191 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data); 192 | delay(10); 193 | 194 | Acscale = scale; 195 | getAres(); 196 | } 197 | 198 | void MPU6886::getAccelData(float* ax, float* ay, float* az) { 199 | int16_t accX = 0; 200 | int16_t accY = 0; 201 | int16_t accZ = 0; 202 | getAccelAdc(&accX, &accY, &accZ); 203 | 204 | *ax = (float)accX * aRes; 205 | *ay = (float)accY * aRes; 206 | *az = (float)accZ * aRes; 207 | } 208 | 209 | void MPU6886::getGyroData(float* gx, float* gy, float* gz) { 210 | int16_t gyroX = 0; 211 | int16_t gyroY = 0; 212 | int16_t gyroZ = 0; 213 | getGyroAdc(&gyroX, &gyroY, &gyroZ); 214 | 215 | *gx = (float)gyroX * gRes; 216 | *gy = (float)gyroY * gRes; 217 | *gz = (float)gyroZ * gRes; 218 | } 219 | 220 | void MPU6886::getTempData(float* t) { 221 | int16_t temp = 0; 222 | getTempAdc(&temp); 223 | 224 | *t = (float)temp / 326.8 + 25.0; 225 | } 226 | 227 | void MPU6886::enableFIFO(Fodr rate) { 228 | unsigned char regdata; 229 | 230 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data); 231 | regdata &= 0x1C; // Clear bits 7:5 and 0:1 of FCHOICE_B to enable sample 232 | // rate divider and DLPF setting 233 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data); 234 | delay(10); 235 | 236 | regdata = rate & 0xFF; // Set sample rate clock divider based on passed 237 | // value for sample rate desired 238 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1, ®data); 239 | delay(10); 240 | 241 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, ®data); 242 | regdata |= 0x01; // Set DLPF_CFG to 176Hz DLPF filtering (highest value 243 | // where sample rate clock divider still works) 244 | regdata &= 0xBF; // Clear bit 6 to allow overflow writes to the FIFO - Use 245 | // it, or lose it! 246 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, ®data); 247 | delay(10); 248 | 249 | regdata = 0x18; // Set GYRO_FIFO_EN and ACCEL_FIFO_EN bits to one in FIFO 250 | // Enable register to enable FIFO on ALL sensor data 251 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, ®data); 252 | delay(10); 253 | 254 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 255 | regdata |= 0x10; // Set bit 4 to turn on interrupts on FIFO overflow events 256 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 257 | delay(10); 258 | 259 | regdata = 0x44; // Set FIFO_EN and FIFO_RST bits to one in User Control 260 | // register to enable FIFO mode 261 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data); 262 | delay(10); 263 | } 264 | 265 | void MPU6886::resetFIFO(void) { 266 | unsigned char regdata; 267 | 268 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data); 269 | regdata |= 0x04; // Set bit 2 to reset FIFO module 270 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data); 271 | delay(10); 272 | } 273 | 274 | void MPU6886::disableFIFO(void) { 275 | unsigned char regdata; 276 | 277 | regdata = 0x00; // Clear GYRO_FIFO_EN and ACCEL_FIFO_EN bits to zero in 278 | // FIFO Enable register 279 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, ®data); 280 | delay(10); 281 | 282 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 283 | regdata &= 284 | 0xEF; // Clear bit 4 to turn off interrupts on FIFO overflow events 285 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data); 286 | delay(10); 287 | 288 | regdata = 0x00; // Set FIFO_EN bit to zero in User Control register to 289 | // dsiable FIFO mode 290 | I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data); 291 | delay(10); 292 | } 293 | 294 | int MPU6886::getFIFOData(int16_t databuf[]) { 295 | uint8_t buf[14]; 296 | uint8_t i; 297 | 298 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_R_W, 14, 299 | buf); // Burst read 14 byte sensor data sample array 300 | 301 | if ((((uint16_t)buf[0] << 8) | buf[1]) == 302 | 0x7F7F) { // Datasheet suggests 0xFFFF, but not what appears to work 303 | return -1; 304 | } 305 | databuf[0] = ((int16_t)buf[0] << 8) | buf[1]; // accelX 306 | databuf[1] = ((int16_t)buf[2] << 8) | buf[3]; // accelY 307 | databuf[2] = ((int16_t)buf[4] << 8) | buf[5]; // accelZ 308 | databuf[6] = ((int16_t)buf[6] << 8) | buf[7]; // temp 309 | databuf[3] = ((int16_t)buf[8] << 8) | buf[9]; // gyroX 310 | databuf[4] = ((int16_t)buf[10] << 8) | buf[11]; // gyroY 311 | databuf[5] = ((int16_t)buf[12] << 8) | buf[13]; // gyroZ 312 | return 0; 313 | } 314 | 315 | int MPU6886::getFIFOData(int16_t* ax, int16_t* ay, int16_t* az, int16_t* gx, 316 | int16_t* gy, int16_t* gz, int16_t* t) { 317 | uint8_t buf[14]; 318 | uint8_t i; 319 | 320 | I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_R_W, 14, 321 | buf); // Burst read 14 byte sensor data sample array 322 | 323 | if ((((uint16_t)buf[0] << 8) | buf[1]) == 324 | 0x7F7F) { // Datasheet suggests 0xFFFF, but not what appears to work 325 | return -1; 326 | } 327 | *ax = ((int16_t)buf[0] << 8) | buf[1]; 328 | *ay = ((int16_t)buf[2] << 8) | buf[3]; 329 | *az = ((int16_t)buf[4] << 8) | buf[5]; 330 | *t = ((int16_t)buf[6] << 8) | buf[7]; 331 | *gx = ((int16_t)buf[8] << 8) | buf[9]; 332 | *gy = ((int16_t)buf[10] << 8) | buf[11]; 333 | *gz = ((int16_t)buf[12] << 8) | buf[13]; 334 | return 0; 335 | } 336 | -------------------------------------------------------------------------------- /lib/mpu6886/MPU6886.h: -------------------------------------------------------------------------------- 1 | /* 2 | Note: The MPU6886 is an I2C sensor and uses the Arduino Wire library. 3 | Because the sensor is not 5V tolerant, we are using a 3.3 V 8 MHz Pro Mini or 4 | a 3.3 V Teensy 3.1. We have disabled the internal pull-ups used by the Wire 5 | library in the Wire.h/twi.c utility file. We are also using the 400 kHz fast 6 | I2C mode by setting the TWI_FREQ to 400000L /twi.h utility file. 7 | */ 8 | #ifndef _MPU6886_H_ 9 | #define _MPU6886_H_ 10 | 11 | #include 12 | #include 13 | #include "MahonyAHRS.h" 14 | 15 | #define MPU6886_ADDRESS 0x68 16 | #define MPU6886_WHOAMI 0x75 17 | #define MPU6886_ACCEL_INTEL_CTRL 0x69 18 | #define MPU6886_SMPLRT_DIV 0x19 19 | #define MPU6886_INT_PIN_CFG 0x37 20 | #define MPU6886_INT_ENABLE 0x38 21 | #define MPU6886_ACCEL_XOUT_H 0x3B 22 | #define MPU6886_ACCEL_XOUT_L 0x3C 23 | #define MPU6886_ACCEL_YOUT_H 0x3D 24 | #define MPU6886_ACCEL_YOUT_L 0x3E 25 | #define MPU6886_ACCEL_ZOUT_H 0x3F 26 | #define MPU6886_ACCEL_ZOUT_L 0x40 27 | 28 | #define MPU6886_TEMP_OUT_H 0x41 29 | #define MPU6886_TEMP_OUT_L 0x42 30 | 31 | #define MPU6886_GYRO_XOUT_H 0x43 32 | #define MPU6886_GYRO_XOUT_L 0x44 33 | #define MPU6886_GYRO_YOUT_H 0x45 34 | #define MPU6886_GYRO_YOUT_L 0x46 35 | #define MPU6886_GYRO_ZOUT_H 0x47 36 | #define MPU6886_GYRO_ZOUT_L 0x48 37 | 38 | #define MPU6886_USER_CTRL 0x6A 39 | #define MPU6886_PWR_MGMT_1 0x6B 40 | #define MPU6886_PWR_MGMT_2 0x6C 41 | #define MPU6886_CONFIG 0x1A 42 | #define MPU6886_GYRO_CONFIG 0x1B 43 | #define MPU6886_ACCEL_CONFIG 0x1C 44 | #define MPU6886_ACCEL_CONFIG2 0x1D 45 | #define MPU6886_FIFO_EN 0x23 46 | // add register for R/W FIFO buffer 47 | #define MPU6886_FIFO_R_W 0x74 48 | 49 | //#define G (9.8) 50 | #define RtA 57.324841 51 | #define AtR 0.0174533 52 | #define Gyro_Gr 0.0010653 53 | 54 | class MPU6886 { 55 | public: 56 | enum Ascale { AFS_2G = 0, AFS_4G, AFS_8G, AFS_16G }; 57 | 58 | enum Gscale { GFS_250DPS = 0, GFS_500DPS, GFS_1000DPS, GFS_2000DPS }; 59 | 60 | // Enumeration type for selecting FIFO output data rate (sample rate) 61 | enum Fodr { 62 | ODR_1kHz = 0, 63 | ODR_500Hz = 1, 64 | ODR_250Hz = 3, 65 | ODR_200Hz = 4, 66 | ODR_125Hz = 7, 67 | ODR_100Hz = 9, 68 | ODR_50Hz = 19, 69 | ODR_10Hz = 99 70 | }; 71 | 72 | Gscale Gyscale = GFS_2000DPS; 73 | Ascale Acscale = AFS_8G; 74 | 75 | public: 76 | MPU6886(); 77 | int Init(void); 78 | void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az); 79 | void getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz); 80 | void getTempAdc(int16_t* t); 81 | 82 | void getAccelData(float* ax, float* ay, float* az); 83 | void getGyroData(float* gx, float* gy, float* gz); 84 | void getTempData(float* t); 85 | 86 | void SetGyroFsr(Gscale scale); 87 | void SetAccelFsr(Ascale scale); 88 | void getAhrsData(float* pitch, float* roll, float* yaw); 89 | 90 | // New public functions of MPU6886 to support FIFO buffered sensor data 91 | // output 92 | void enableFIFO(Fodr rate); 93 | void resetFIFO(void); 94 | void disableFIFO(void); 95 | int getFIFOData(int16_t databuf[]); 96 | int getFIFOData(int16_t* ax, int16_t* ay, int16_t* az, int16_t* t, 97 | int16_t* gx, int16_t* gy, int16_t* gz); 98 | 99 | public: 100 | float aRes, gRes; 101 | 102 | private: 103 | private: 104 | void I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, 105 | uint8_t number_Bytes, uint8_t* read_Buffer); 106 | void I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, 107 | uint8_t number_Bytes, uint8_t* write_Buffer); 108 | void getGres(); 109 | void getAres(); 110 | }; 111 | #endif 112 | -------------------------------------------------------------------------------- /lib/mpu6886/MahonyAHRS.cpp: -------------------------------------------------------------------------------- 1 | //===================================================================================================== 2 | // MahonyAHRS.c 3 | //===================================================================================================== 4 | // 5 | // Madgwick's implementation of Mayhony's AHRS algorithm. 6 | // See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms 7 | // 8 | // Date Author Notes 9 | // 29/09/2011 SOH Madgwick Initial release 10 | // 02/10/2011 SOH Madgwick Optimised for reduced CPU load 11 | // 12 | //===================================================================================================== 13 | 14 | //--------------------------------------------------------------------------------------------------- 15 | // Header files 16 | 17 | #include "MahonyAHRS.h" 18 | #include 19 | // #include 20 | #include 21 | 22 | //--------------------------------------------------------------------------------------------------- 23 | // Definitions 24 | 25 | #define sampleFreq 25.0f // sample frequency in Hz 26 | #define twoKpDef (2.0f * 1.0f) // 2 * proportional gain 27 | #define twoKiDef (2.0f * 0.0f) // 2 * integral gain 28 | 29 | //#define twoKiDef (0.0f * 0.0f) 30 | 31 | //--------------------------------------------------------------------------------------------------- 32 | // Variable definitions 33 | 34 | volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp) 35 | volatile float twoKi = twoKiDef; // 2 * integral gain (Ki) 36 | volatile float 37 | q0 = 1.0, 38 | q1 = 0.0, q2 = 0.0, 39 | q3 = 0.0; // quaternion of sensor frame relative to auxiliary frame 40 | volatile float integralFBx = 0.0f, integralFBy = 0.0f, 41 | integralFBz = 0.0f; // integral error terms scaled by Ki 42 | 43 | //--------------------------------------------------------------------------------------------------- 44 | // Function declarations 45 | 46 | // float invSqrt(float x); 47 | 48 | //==================================================================================================== 49 | // Functions 50 | 51 | //--------------------------------------------------------------------------------------------------- 52 | // AHRS algorithm update 53 | 54 | void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, 55 | float az, float mx, float my, float mz) { 56 | float recipNorm; 57 | float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3; 58 | float hx, hy, bx, bz; 59 | float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz; 60 | float halfex, halfey, halfez; 61 | float qa, qb, qc; 62 | 63 | // Use IMU algorithm if magnetometer measurement invalid (avoids NaN in 64 | // magnetometer normalisation) 65 | if ((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) { 66 | // MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az); 67 | return; 68 | } 69 | 70 | // Compute feedback only if accelerometer measurement valid (avoids NaN in 71 | // accelerometer normalisation) 72 | if (!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { 73 | // Normalise accelerometer measurement 74 | recipNorm = sqrt(ax * ax + ay * ay + az * az); 75 | ax *= recipNorm; 76 | ay *= recipNorm; 77 | az *= recipNorm; 78 | 79 | // Normalise magnetometer measurement 80 | recipNorm = sqrt(mx * mx + my * my + mz * mz); 81 | mx *= recipNorm; 82 | my *= recipNorm; 83 | mz *= recipNorm; 84 | 85 | // Auxiliary variables to avoid repeated arithmetic 86 | q0q0 = q0 * q0; 87 | q0q1 = q0 * q1; 88 | q0q2 = q0 * q2; 89 | q0q3 = q0 * q3; 90 | q1q1 = q1 * q1; 91 | q1q2 = q1 * q2; 92 | q1q3 = q1 * q3; 93 | q2q2 = q2 * q2; 94 | q2q3 = q2 * q3; 95 | q3q3 = q3 * q3; 96 | 97 | // Reference direction of Earth's magnetic field 98 | hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + 99 | mz * (q1q3 + q0q2)); 100 | hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + 101 | mz * (q2q3 - q0q1)); 102 | bx = sqrt(hx * hx + hy * hy); 103 | bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + 104 | mz * (0.5f - q1q1 - q2q2)); 105 | 106 | // Estimated direction of gravity and magnetic field 107 | halfvx = q1q3 - q0q2; 108 | halfvy = q0q1 + q2q3; 109 | halfvz = q0q0 - 0.5f + q3q3; 110 | halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2); 111 | halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3); 112 | halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2); 113 | 114 | // Error is sum of cross product between estimated direction and 115 | // measured direction of field vectors 116 | halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy); 117 | halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz); 118 | halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx); 119 | 120 | // Compute and apply integral feedback if enabled 121 | if (twoKi > 0.0f) { 122 | integralFBx += twoKi * halfex * 123 | (1.0f / sampleFreq); // integral error scaled by Ki 124 | integralFBy += twoKi * halfey * (1.0f / sampleFreq); 125 | integralFBz += twoKi * halfez * (1.0f / sampleFreq); 126 | gx += integralFBx; // apply integral feedback 127 | gy += integralFBy; 128 | gz += integralFBz; 129 | } else { 130 | integralFBx = 0.0f; // prevent integral windup 131 | integralFBy = 0.0f; 132 | integralFBz = 0.0f; 133 | } 134 | 135 | // Apply proportional feedback 136 | gx += twoKp * halfex; 137 | gy += twoKp * halfey; 138 | gz += twoKp * halfez; 139 | } 140 | 141 | // Integrate rate of change of quaternion 142 | gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors 143 | gy *= (0.5f * (1.0f / sampleFreq)); 144 | gz *= (0.5f * (1.0f / sampleFreq)); 145 | qa = q0; 146 | qb = q1; 147 | qc = q2; 148 | q0 += (-qb * gx - qc * gy - q3 * gz); 149 | q1 += (qa * gx + qc * gz - q3 * gy); 150 | q2 += (qa * gy - qb * gz + q3 * gx); 151 | q3 += (qa * gz + qb * gy - qc * gx); 152 | 153 | // Normalise quaternion 154 | recipNorm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); 155 | q0 *= recipNorm; 156 | q1 *= recipNorm; 157 | q2 *= recipNorm; 158 | q3 *= recipNorm; 159 | } 160 | 161 | //--------------------------------------------------------------------------------------------------- 162 | // IMU algorithm update 163 | 164 | void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, 165 | float az, float *pitch, float *roll, float *yaw) { 166 | float recipNorm; 167 | float halfvx, halfvy, halfvz; 168 | float halfex, halfey, halfez; 169 | float qa, qb, qc; 170 | 171 | // Compute feedback only if accelerometer measurement valid (avoids NaN in 172 | // accelerometer normalisation) 173 | if (!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) { 174 | // Normalise accelerometer measurement 175 | recipNorm = invSqrt(ax * ax + ay * ay + az * az); 176 | ax *= recipNorm; 177 | ay *= recipNorm; 178 | az *= recipNorm; 179 | 180 | // Estimated direction of gravity and vector perpendicular to magnetic 181 | // flux 182 | halfvx = q1 * q3 - q0 * q2; 183 | halfvy = q0 * q1 + q2 * q3; 184 | halfvz = q0 * q0 - 0.5f + q3 * q3; 185 | 186 | // Error is sum of cross product between estimated and measured 187 | // direction of gravity 188 | halfex = (ay * halfvz - az * halfvy); 189 | halfey = (az * halfvx - ax * halfvz); 190 | halfez = (ax * halfvy - ay * halfvx); 191 | 192 | // Compute and apply integral feedback if enabled 193 | if (twoKi > 0.0f) { 194 | integralFBx += twoKi * halfex * 195 | (1.0f / sampleFreq); // integral error scaled by Ki 196 | integralFBy += twoKi * halfey * (1.0f / sampleFreq); 197 | integralFBz += twoKi * halfez * (1.0f / sampleFreq); 198 | gx += integralFBx; // apply integral feedback 199 | gy += integralFBy; 200 | gz += integralFBz; 201 | } else { 202 | integralFBx = 0.0f; // prevent integral windup 203 | integralFBy = 0.0f; 204 | integralFBz = 0.0f; 205 | } 206 | 207 | // Apply proportional feedback 208 | gx += twoKp * halfex; 209 | gy += twoKp * halfey; 210 | gz += twoKp * halfez; 211 | } 212 | 213 | // Integrate rate of change of quaternion 214 | gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors 215 | gy *= (0.5f * (1.0f / sampleFreq)); 216 | gz *= (0.5f * (1.0f / sampleFreq)); 217 | qa = q0; 218 | qb = q1; 219 | qc = q2; 220 | q0 += (-qb * gx - qc * gy - q3 * gz); 221 | q1 += (qa * gx + qc * gz - q3 * gy); 222 | q2 += (qa * gy - qb * gz + q3 * gx); 223 | q3 += (qa * gz + qb * gy - qc * gx); 224 | 225 | // Normalise quaternion 226 | recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3); 227 | q0 *= recipNorm; 228 | q1 *= recipNorm; 229 | q2 *= recipNorm; 230 | q3 *= recipNorm; 231 | 232 | *pitch = asin(-2 * q1 * q3 + 2 * q0 * q2); // pitch 233 | *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, 234 | -2 * q1 * q1 - 2 * q2 * q2 + 1); // roll 235 | *yaw = atan2(2 * (q1 * q2 + q0 * q3), 236 | q0 * q0 + q1 * q1 - q2 * q2 - q3 * q3); // yaw 237 | 238 | *pitch *= RAD_TO_DEG; 239 | *yaw *= RAD_TO_DEG; 240 | // Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is 241 | // 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19 242 | // - http://www.ngdc.noaa.gov/geomag-web/#declination 243 | *yaw -= 8.5; 244 | *roll *= RAD_TO_DEG; 245 | 246 | /// Serial.printf("%f %f %f \r\n", pitch, roll, yaw); 247 | } 248 | 249 | //--------------------------------------------------------------------------------------------------- 250 | // Fast inverse square-root 251 | // See: http://en.wikipedia.org/wiki/Fast_inverse_square_root 252 | 253 | float invSqrt(float x) { 254 | float halfx = 0.5f * x; 255 | float y = x; 256 | #pragma GCC diagnostic ignored "-Wstrict-aliasing" 257 | long i = *(long *)&y; 258 | i = 0x5f3759df - (i >> 1); 259 | y = *(float *)&i; 260 | #pragma GCC diagnostic warning "-Wstrict-aliasing" 261 | y = y * (1.5f - (halfx * y * y)); 262 | return y; 263 | } 264 | 265 | //==================================================================================================== 266 | // END OF CODE 267 | //==================================================================================================== 268 | -------------------------------------------------------------------------------- /lib/mpu6886/MahonyAHRS.h: -------------------------------------------------------------------------------- 1 | //===================================================================================================== 2 | // MahonyAHRS.h 3 | //===================================================================================================== 4 | // 5 | // Madgwick's implementation of Mayhony's AHRS algorithm. 6 | // See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms 7 | // 8 | // Date Author Notes 9 | // 29/09/2011 SOH Madgwick Initial release 10 | // 02/10/2011 SOH Madgwick Optimised for reduced CPU load 11 | // 12 | //===================================================================================================== 13 | #ifndef MahonyAHRS_h 14 | #define MahonyAHRS_h 15 | 16 | //---------------------------------------------------------------------------------------------------- 17 | // Variable declaration 18 | 19 | extern volatile float twoKp; // 2 * proportional gain (Kp) 20 | extern volatile float twoKi; // 2 * integral gain (Ki) 21 | // volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to 22 | // auxiliary frame 23 | 24 | //--------------------------------------------------------------------------------------------------- 25 | // Function declarations 26 | 27 | void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, 28 | float az, float mx, float my, float mz); 29 | // void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, 30 | // float az); 31 | void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, 32 | float az, float *pitch, float *roll, float *yaw); 33 | float invSqrt(float x); 34 | #endif 35 | //===================================================================================================== 36 | // End of file 37 | //===================================================================================================== 38 | -------------------------------------------------------------------------------- /lib/rtc/cplus_RTC.cpp: -------------------------------------------------------------------------------- 1 | #include "cplus_RTC.h" 2 | 3 | // RTC::RTC() { 4 | // } 5 | 6 | void cplus_RTC::begin(void) { 7 | Wire1.begin(21, 22); 8 | } 9 | 10 | void cplus_RTC::GetBm8563Time(void) { 11 | Wire1.beginTransmission(0x51); 12 | Wire1.write(0x02); 13 | Wire1.endTransmission(); 14 | Wire1.requestFrom(0x51, 7); 15 | while (Wire1.available()) { 16 | trdata[0] = Wire1.read(); 17 | trdata[1] = Wire1.read(); 18 | trdata[2] = Wire1.read(); 19 | trdata[3] = Wire1.read(); 20 | trdata[4] = Wire1.read(); 21 | trdata[5] = Wire1.read(); 22 | trdata[6] = Wire1.read(); 23 | } 24 | 25 | DataMask(); 26 | Bcd2asc(); 27 | Str2Time(); 28 | } 29 | 30 | void cplus_RTC::Str2Time(void) { 31 | Second = (asc[0] - 0x30) * 10 + asc[1] - 0x30; 32 | Minute = (asc[2] - 0x30) * 10 + asc[3] - 0x30; 33 | Hour = (asc[4] - 0x30) * 10 + asc[5] - 0x30; 34 | /* 35 | uint8_t Hour; 36 | uint8_t Week; 37 | uint8_t Day; 38 | uint8_t Month; 39 | uint8_t Year; 40 | */ 41 | } 42 | 43 | void cplus_RTC::DataMask() { 44 | trdata[0] = trdata[0] & 0x7f; //秒 45 | trdata[1] = trdata[1] & 0x7f; //分 46 | trdata[2] = trdata[2] & 0x3f; //时 47 | 48 | trdata[3] = trdata[3] & 0x3f; //日 49 | trdata[4] = trdata[4] & 0x07; //星期 50 | trdata[5] = trdata[5] & 0x1f; //月 51 | 52 | trdata[6] = trdata[6] & 0xff; //年 53 | } 54 | /******************************************************************** 55 | 函 数 名: void Bcd2asc(void) 56 | 功 能: bcd 码转换成 asc 码,供Lcd显示用 57 | 说 明: 58 | 调 用: 59 | 入口参数: 60 | 返 回 值:无 61 | ***********************************************************************/ 62 | void cplus_RTC::Bcd2asc(void) { 63 | uint8_t i, j; 64 | for (j = 0, i = 0; i < 7; i++) { 65 | asc[j++] = 66 | (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */ 67 | asc[j++] = (trdata[i] & 0x0f) | 0x30; 68 | } 69 | } 70 | 71 | uint8_t cplus_RTC::Bcd2ToByte(uint8_t Value) { 72 | uint8_t tmp = 0; 73 | tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; 74 | return (tmp + (Value & (uint8_t)0x0F)); 75 | } 76 | 77 | uint8_t cplus_RTC::ByteToBcd2(uint8_t Value) { 78 | uint8_t bcdhigh = 0; 79 | 80 | while (Value >= 10) { 81 | bcdhigh++; 82 | Value -= 10; 83 | } 84 | 85 | return ((uint8_t)(bcdhigh << 4) | Value); 86 | } 87 | 88 | void cplus_RTC::GetTime(RTC_TimeTypeDef* RTC_TimeStruct) { 89 | // if() 90 | uint8_t buf[3] = {0}; 91 | 92 | Wire1.beginTransmission(0x51); 93 | Wire1.write(0x02); 94 | Wire1.endTransmission(); 95 | Wire1.requestFrom(0x51, 3); 96 | 97 | while (Wire1.available()) { 98 | buf[0] = Wire1.read(); 99 | buf[1] = Wire1.read(); 100 | buf[2] = Wire1.read(); 101 | } 102 | 103 | RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒 104 | RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分 105 | RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时 106 | } 107 | 108 | void cplus_RTC::SetTime(RTC_TimeTypeDef* RTC_TimeStruct) { 109 | if (RTC_TimeStruct == NULL) return; 110 | 111 | Wire1.beginTransmission(0x51); 112 | Wire1.write(0x02); 113 | Wire1.write(ByteToBcd2(RTC_TimeStruct->Seconds)); 114 | Wire1.write(ByteToBcd2(RTC_TimeStruct->Minutes)); 115 | Wire1.write(ByteToBcd2(RTC_TimeStruct->Hours)); 116 | Wire1.endTransmission(); 117 | } 118 | 119 | void cplus_RTC::GetDate(RTC_DateTypeDef* RTC_DateStruct) { 120 | uint8_t buf[4] = {0}; 121 | 122 | Wire1.beginTransmission(0x51); 123 | Wire1.write(0x05); 124 | Wire1.endTransmission(); 125 | Wire1.requestFrom(0x51, 4); 126 | 127 | while (Wire1.available()) { 128 | buf[0] = Wire1.read(); 129 | buf[1] = Wire1.read(); 130 | buf[2] = Wire1.read(); 131 | buf[3] = Wire1.read(); 132 | } 133 | 134 | RTC_DateStruct->Date = Bcd2ToByte(buf[0] & 0x3f); 135 | RTC_DateStruct->WeekDay = Bcd2ToByte(buf[1] & 0x07); 136 | RTC_DateStruct->Month = Bcd2ToByte(buf[2] & 0x1f); 137 | 138 | if (buf[2] & 0x80) { 139 | RTC_DateStruct->Year = 1900 + Bcd2ToByte(buf[3] & 0xff); 140 | } else { 141 | RTC_DateStruct->Year = 2000 + Bcd2ToByte(buf[3] & 0xff); 142 | } 143 | } 144 | 145 | void cplus_RTC::SetDate(RTC_DateTypeDef* RTC_DateStruct) { 146 | if (RTC_DateStruct == NULL) return; 147 | Wire1.beginTransmission(0x51); 148 | Wire1.write(0x05); 149 | Wire1.write(ByteToBcd2(RTC_DateStruct->Date)); 150 | Wire1.write(ByteToBcd2(RTC_DateStruct->WeekDay)); 151 | 152 | if (RTC_DateStruct->Year < 2000) { 153 | Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x80); 154 | Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100))); 155 | 156 | } else { 157 | /* code */ 158 | Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x00); 159 | Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100))); 160 | } 161 | 162 | Wire1.endTransmission(); 163 | } 164 | 165 | 166 | 167 | 168 | 169 | void cplus_RTC::WriteReg(uint8_t reg, uint8_t data) { 170 | Wire1.beginTransmission(0x51); 171 | Wire1.write(reg); 172 | Wire1.write(data); 173 | Wire1.endTransmission(); 174 | } 175 | 176 | uint8_t cplus_RTC::ReadReg(uint8_t reg) { 177 | Wire1.beginTransmission(0x51); 178 | Wire1.write(reg); 179 | Wire1.endTransmission(false); 180 | Wire1.requestFrom(0x51, 1); 181 | return Wire1.read(); 182 | } 183 | 184 | 185 | int cplus_RTC::SetAlarmIRQ(int afterSeconds) { 186 | uint8_t reg_value = 0; 187 | reg_value = ReadReg(0x01); 188 | printf("read 0x%X\n", reg_value); 189 | 190 | if (afterSeconds < 0) { 191 | reg_value &= ~(1 << 0); 192 | WriteReg(0x01, reg_value); 193 | reg_value = 0x03; 194 | WriteReg(0x0E, reg_value); 195 | return -1; 196 | } 197 | 198 | uint8_t type_value = 2; 199 | uint8_t div = 1; 200 | if (afterSeconds > 255) { 201 | div = 60; 202 | type_value = 0x83; 203 | } else { 204 | type_value = 0x82; 205 | } 206 | 207 | afterSeconds = (afterSeconds / div) & 0xFF; 208 | WriteReg(0x0F, afterSeconds); 209 | WriteReg(0x0E, type_value); 210 | 211 | reg_value |= (1 << 0); 212 | reg_value &= ~(1 << 7); 213 | WriteReg(0x01, reg_value); 214 | return afterSeconds * div; 215 | } 216 | 217 | 218 | void cplus_RTC::clearIRQ() { 219 | uint8_t data = ReadReg(0x01); 220 | WriteReg(0x01, data & 0xf3); 221 | } 222 | void cplus_RTC::disableIRQ() { 223 | clearIRQ(); 224 | uint8_t data = ReadReg(0x01); 225 | WriteReg(0x01, data & 0xfC); 226 | } 227 | 228 | -------------------------------------------------------------------------------- /lib/rtc/cplus_RTC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | typedef struct { 6 | uint8_t Hours; 7 | uint8_t Minutes; 8 | uint8_t Seconds; 9 | } RTC_TimeTypeDef; 10 | 11 | typedef struct { 12 | uint8_t WeekDay; 13 | uint8_t Month; 14 | uint8_t Date; 15 | uint16_t Year; 16 | } RTC_DateTypeDef; 17 | 18 | class cplus_RTC { 19 | public: 20 | // cplus_RTC(); 21 | 22 | void begin(void); 23 | void GetBm8563Time(void); 24 | 25 | void SetTime(RTC_TimeTypeDef* RTC_TimeStruct); 26 | void SetDate(RTC_DateTypeDef* RTC_DateStruct); 27 | 28 | void GetTime(RTC_TimeTypeDef* RTC_TimeStruct); 29 | void GetDate(RTC_DateTypeDef* RTC_DateStruct); 30 | 31 | 32 | void WriteReg(uint8_t reg, uint8_t data); 33 | uint8_t ReadReg(uint8_t reg); 34 | 35 | int SetAlarmIRQ(int afterSeconds); 36 | 37 | void clearIRQ(); 38 | void disableIRQ(); 39 | 40 | public: 41 | uint8_t Second; 42 | uint8_t Minute; 43 | uint8_t Hour; 44 | uint8_t Week; 45 | uint8_t Day; 46 | uint8_t Month; 47 | uint8_t Year; 48 | uint8_t DateString[9]; 49 | uint8_t TimeString[9]; 50 | 51 | uint8_t asc[14]; 52 | 53 | private: 54 | void Bcd2asc(void); 55 | void DataMask(); 56 | void Str2Time(void); 57 | 58 | uint8_t Bcd2ToByte(uint8_t Value); 59 | uint8_t ByteToBcd2(uint8_t Value); 60 | 61 | private: 62 | /*定义数组用来存储读取的时间数据 */ 63 | uint8_t trdata[7]; 64 | /*定义数组用来存储转换的 asc 码时间数据*/ 65 | // uint8_t asc[14]; 66 | }; 67 | 68 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:m5stick-c] 12 | platform = espressif32@6.1.0 13 | board = m5stick-c 14 | framework = arduino 15 | 16 | board_build.partitions = huge_app.csv 17 | build_flags = 18 | -DCORE_DEBUG_LEVEL=0 19 | 20 | lib_deps = 21 | kosme/arduinoFFT @ 1.6.1 22 | z3t0/IRremote @ 4.2.0 23 | m5stack/M5GFX @ 0.1.11 24 | 25 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file main.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include 12 | #include "test/test.h" 13 | 14 | TEST::TEST test; 15 | 16 | void setup() 17 | { 18 | test.setup(); 19 | } 20 | 21 | void loop() 22 | { 23 | test.loop(); 24 | } 25 | -------------------------------------------------------------------------------- /src/test/test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | namespace TEST 14 | { 15 | 16 | void TEST::hardware_init() 17 | { 18 | /* Hold pwr pin */ 19 | gpio_reset_pin((gpio_num_t)POWER_HOLD_PIN); 20 | pinMode(POWER_HOLD_PIN, OUTPUT); 21 | digitalWrite(POWER_HOLD_PIN, HIGH); 22 | 23 | Wire1.begin(I2C_SDA_PIN, I2C_SCL_PIN); 24 | } 25 | 26 | void TEST::power_off() 27 | { 28 | rtc_init(); 29 | display->fillScreen(TFT_BLACK); 30 | displayUpdate(); 31 | 32 | while ((!btnPWR.read())) 33 | { 34 | delay(100); 35 | } 36 | 37 | delay(200); 38 | 39 | printf("power off\n"); 40 | digitalWrite(POWER_HOLD_PIN, 0); 41 | delay(10000); 42 | 43 | while (1) 44 | { 45 | delay(1000); 46 | } 47 | } 48 | 49 | void TEST::setup() 50 | { 51 | hardware_init(); 52 | key_init(); 53 | lcd_init(); 54 | 55 | // lcd.fillScreen(TFT_BLUE); 56 | // delay(1000); 57 | 58 | // lcd.fillScreen(TFT_RED); 59 | // while (1) 60 | // { 61 | // delay(1000); 62 | // } 63 | 64 | // gpio_test(); 65 | 66 | // gpio_reset_pin(GPIO_NUM_19); 67 | // pinMode(19, OUTPUT); 68 | // while (1) { 69 | // digitalWrite(19, 0); 70 | // printf("19 %d\n", digitalRead(19)); 71 | // delay(1000); 72 | // digitalWrite(19, 1); 73 | // printf("19 %d\n", digitalRead(19)); 74 | // delay(1000); 75 | // } 76 | 77 | /* Check test mode */ 78 | is_test_mode = false; 79 | if (!btnB.read()) 80 | { 81 | delay(20); 82 | if (!btnB.read()) 83 | { 84 | printf("test mode\n"); 85 | is_test_mode = true; 86 | 87 | display->fillScreen(TFT_BLACK); 88 | display->setFont(&fonts::efontCN_24); 89 | display->printf("松开按键进入测试模式"); 90 | display->setCursor(0, 10); 91 | displayUpdate(); 92 | 93 | /* Start wifi test */ 94 | // wifi_init(); 95 | 96 | while (!btnB.read()) 97 | { 98 | delay(10); 99 | } 100 | } 101 | } 102 | else 103 | { 104 | printf("normal mode\n"); 105 | } 106 | 107 | // lcd_init(); 108 | rtc_init(); 109 | imu_init(); 110 | mic_init(); 111 | ble_init(); 112 | 113 | if (!is_test_mode) 114 | { 115 | ColorBar(); 116 | } 117 | } 118 | 119 | void TEST::loop() 120 | { 121 | // rtc_wakeup_test(); 122 | 123 | if (is_test_mode) 124 | { 125 | lcd_test(); 126 | } 127 | 128 | imu_test(); 129 | rtc_test(); 130 | 131 | // mic_test(); 132 | // new_mic_test(); 133 | new_mic_test_fft(); 134 | 135 | ir_test(); 136 | 137 | if (is_test_mode) 138 | { 139 | gpio_test(); 140 | key_test(); 141 | // rtc_wakeup_test(); 142 | } 143 | 144 | wifi_test(); 145 | 146 | display->setFont(&fonts::Font0); 147 | display->setTextSize(1); 148 | displayUpdate(); 149 | ble_test(); 150 | 151 | if (is_test_mode) 152 | { 153 | // gpio_test(); 154 | // key_test(); 155 | rtc_wakeup_test(); 156 | } 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/test/test.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test.h 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #pragma once 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | #include "arduinoFFT.h" 31 | 32 | #define display Disbuff 33 | #define displayUpdate Displaybuff 34 | 35 | #define LCD_MOSI_PIN 15 36 | #define LCD_MISO_PIN -1 37 | #define LCD_SCLK_PIN 13 38 | #define LCD_DC_PIN 14 39 | #define LCD_CS_PIN 5 40 | #define LCD_RST_PIN 12 41 | #define LCD_BUSY_PIN -1 42 | #define LCD_BL_PIN 27 43 | 44 | #define POWER_HOLD_PIN 4 45 | #define I2C_SDA_PIN 21 46 | #define I2C_SCL_PIN 22 47 | 48 | #define I2S_DATA_PIN 34 49 | #define I2S_SCLK_PIN 0 50 | 51 | #define BUZZ_PIN 2 52 | 53 | class CLite_GFX : public lgfx::LGFX_Device 54 | { 55 | lgfx::Panel_ST7789 _panel_instance; 56 | lgfx::Bus_SPI _bus_instance; 57 | lgfx::Light_PWM _light_instance; 58 | 59 | public: 60 | CLite_GFX(void) 61 | { 62 | { 63 | auto cfg = _bus_instance.config(); 64 | 65 | cfg.pin_mosi = LCD_MOSI_PIN; 66 | cfg.pin_miso = LCD_MISO_PIN; 67 | cfg.pin_sclk = LCD_SCLK_PIN; 68 | cfg.pin_dc = LCD_DC_PIN; 69 | cfg.freq_write = 40000000; 70 | 71 | _bus_instance.config(cfg); 72 | _panel_instance.setBus(&_bus_instance); 73 | } 74 | { 75 | auto cfg = _panel_instance.config(); 76 | 77 | cfg.invert = true; 78 | cfg.pin_cs = LCD_CS_PIN; 79 | cfg.pin_rst = LCD_RST_PIN; 80 | cfg.pin_busy = LCD_BUSY_PIN; 81 | cfg.panel_width = 135; 82 | cfg.panel_height = 240; 83 | cfg.offset_x = 52; 84 | cfg.offset_y = 40; 85 | // cfg.offset_x = 0; 86 | // cfg.offset_y = 0; 87 | 88 | _panel_instance.config(cfg); 89 | } 90 | { // バックライト制御の設定を行います。(必要なければ削除) 91 | auto cfg = _light_instance.config(); // バックライト設定用の構造体を取得します。 92 | 93 | cfg.pin_bl = 27; // バックライトが接続されているピン番号 94 | cfg.invert = false; // バックライトの輝度を反転させる場合 true 95 | // cfg.freq = 44100; // バックライトのPWM周波数 96 | cfg.freq = 200; // バックライトのPWM周波数 97 | cfg.pwm_channel = 7; // 使用するPWMのチャンネル番号 98 | 99 | _light_instance.config(cfg); 100 | _panel_instance.setLight(&_light_instance); // バックライトをパネルにセットします。 101 | } 102 | 103 | setPanel(&_panel_instance); 104 | } 105 | }; 106 | 107 | extern const unsigned char ImageData[768]; 108 | extern const unsigned char error_48[4608]; 109 | extern const unsigned char icon_ir[4608]; 110 | extern const unsigned char icon_ble[4608]; 111 | extern const unsigned char icon_wifi[4608]; 112 | extern const unsigned char icon_ble_disconnect[4608]; 113 | 114 | namespace TEST 115 | { 116 | 117 | class TEST 118 | { 119 | private: 120 | bool is_test_mode; 121 | 122 | void hardware_init(); 123 | void power_off(); 124 | 125 | inline void _tone(unsigned int frequency, unsigned long duration = 0UL) { tone(BUZZ_PIN, frequency, duration); } 126 | inline void _noTone() { noTone(BUZZ_PIN); } 127 | 128 | /* Display */ 129 | CLite_GFX lcd; 130 | LGFX_Sprite *Disbuff; 131 | 132 | void Displaybuff(); 133 | void ColorBar(); 134 | 135 | void frame_test(); 136 | void color_test(); 137 | void lcd_init(); 138 | void lcd_test(); 139 | 140 | /* Keys */ 141 | void key_init(); 142 | void key_test(); 143 | Button btnA = Button(37, 20); 144 | Button btnB = Button(39, 20); 145 | Button btnPWR = Button(35, 20); 146 | void checkReboot(); 147 | bool checkNext(); 148 | void waitNext(); 149 | 150 | /* IMU */ 151 | MPU6886 imu; 152 | void imu_init(); 153 | void imu_test(); 154 | 155 | /* Mic */ 156 | void mic_init(); 157 | void mic_test(); 158 | void mic_test_one_task(); 159 | 160 | void DisplayMicro(); 161 | 162 | void new_mic_test(); 163 | void new_mic_test_fft(); 164 | 165 | /* IR */ 166 | void ir_init(); 167 | void ir_test(); 168 | 169 | /* BLE */ 170 | void ble_init(); 171 | void ble_test(); 172 | 173 | void DisPlayBLESend(); 174 | 175 | /* RTC */ 176 | void rtc_init(); 177 | void rtc_test(); 178 | void rtc_wakeup_test(); 179 | 180 | void DisplayRTC(); 181 | 182 | /* GPIO */ 183 | void gpio_test(); 184 | 185 | /* Wifi */ 186 | void wifi_init(); 187 | void wifi_test(); 188 | void wifi_display_test_mode(); 189 | void wifi_display_normal_mode(); 190 | 191 | public: 192 | TEST() : is_test_mode(false) {} 193 | ~TEST() {} 194 | 195 | inline void setTestMode(bool testMode) { is_test_mode = testMode; } 196 | 197 | void setup(); 198 | void loop(); 199 | }; 200 | 201 | } 202 | -------------------------------------------------------------------------------- /src/test/test_ble.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_ble.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | #define SERVICE_UUID "1bc68b2a-f3e3-11e9-81b4-2a2ae2dbcce4" 14 | #define CHARACTERISTIC_RX_UUID "1bc68da0-f3e3-11e9-81b4-2a2ae2dbcce4" 15 | #define CHARACTERISTIC_TX_UUID "1bc68efe-f3e3-11e9-81b4-2a2ae2dbcce4" 16 | 17 | BLEServer *pServer = NULL; 18 | BLEService *pService = NULL; 19 | BLECharacteristic *pTxCharacteristic; 20 | bool deviceConnected = false; 21 | bool oldDeviceConnected = false; 22 | 23 | class MyServerCallbacks : public BLEServerCallbacks 24 | { 25 | void onConnect(BLEServer *pServer) 26 | { 27 | deviceConnected = true; 28 | }; 29 | 30 | void onDisconnect(BLEServer *pServer) 31 | { 32 | deviceConnected = false; 33 | } 34 | }; 35 | 36 | uint8_t *data = new uint8_t[128]; 37 | 38 | class MyCallbacks : public BLECharacteristicCallbacks 39 | { 40 | void onWrite(BLECharacteristic *pCharacteristic) 41 | { 42 | data = pCharacteristic->getData(); 43 | } 44 | }; 45 | 46 | namespace TEST 47 | { 48 | 49 | bool InitBLEServer() 50 | { 51 | uint64_t chipid = ESP.getEfuseMac(); 52 | String blename = "M5-" + String((uint32_t)(chipid >> 32), HEX); 53 | 54 | BLEDevice::init(blename.c_str()); 55 | // BLEDevice::setPower(ESP_PWR_LVL_N12); 56 | pServer = BLEDevice::createServer(); 57 | 58 | pServer->setCallbacks(new MyServerCallbacks()); 59 | pService = pServer->createService(SERVICE_UUID); 60 | pTxCharacteristic = pService->createCharacteristic( 61 | CHARACTERISTIC_RX_UUID, BLECharacteristic::PROPERTY_NOTIFY); 62 | 63 | pTxCharacteristic->addDescriptor(new BLE2902()); 64 | BLECharacteristic *pRxCharacteristic = pService->createCharacteristic( 65 | CHARACTERISTIC_TX_UUID, BLECharacteristic::PROPERTY_WRITE); 66 | pRxCharacteristic->setCallbacks(new MyCallbacks()); 67 | 68 | return true; 69 | } 70 | 71 | bool deinit_ble_server() 72 | { 73 | BLEDevice::deinit(true); 74 | } 75 | 76 | void TEST::DisPlayBLESend() 77 | { 78 | uint8_t senddata[2] = {0}; 79 | 80 | pService->start(); 81 | pServer->getAdvertising()->start(); 82 | 83 | uint64_t chipid = ESP.getEfuseMac(); 84 | String blename = "M5-" + String((uint32_t)(chipid >> 32), HEX); 85 | 86 | display->setFont(&fonts::Font0); 87 | display->setTextSize(1); 88 | 89 | while (1) 90 | { 91 | Disbuff->fillRect(0, 0, 240, 135, TFT_BLACK); 92 | if (deviceConnected) 93 | { 94 | Disbuff->pushImage(180, 16, 48, 48, (uint16_t *)icon_ble); 95 | Disbuff->setTextColor(Disbuff->color565(180, 180, 180)); 96 | Disbuff->setTextSize(3); 97 | Disbuff->setCursor(12, 20); 98 | // Disbuff.printf("BLE connect!\n"); 99 | Disbuff->printf("BLE Send\n"); 100 | Disbuff->setTextSize(5); 101 | Disbuff->setCursor(12, 75); 102 | if (senddata[0] % 4 == 0) 103 | { 104 | Disbuff->printf("0x%02X> ", senddata[0]); 105 | } 106 | else if (senddata[0] % 4 == 1) 107 | { 108 | Disbuff->printf("0x%02X>>", senddata[0]); 109 | } 110 | else if (senddata[0] % 4 == 2) 111 | { 112 | Disbuff->printf("0x%02X >>", senddata[0]); 113 | } 114 | else if (senddata[0] % 4 == 3) 115 | { 116 | Disbuff->printf("0x%02X >", senddata[0]); 117 | } 118 | 119 | senddata[1]++; 120 | if (senddata[1] > 3) 121 | { 122 | senddata[1] = 0; 123 | senddata[0]++; 124 | pTxCharacteristic->setValue(senddata, 1); 125 | pTxCharacteristic->notify(); 126 | } 127 | } 128 | else 129 | { 130 | Disbuff->setTextSize(2); 131 | Disbuff->setCursor(12, 20); 132 | Disbuff->setTextColor(TFT_RED); 133 | Disbuff->printf("BLE disconnect\n"); 134 | Disbuff->setCursor(12, 45); 135 | Disbuff->setTextColor(Disbuff->color565(18, 150, 219)); 136 | 137 | Disbuff->printf(String("Name:" + blename + "\n").c_str()); 138 | Disbuff->setCursor(12, 70); 139 | Disbuff->printf("UUID:1bc68b2a\n"); 140 | Disbuff->pushImage(180, 16, 48, 48, (uint16_t *)icon_ble_disconnect); 141 | } 142 | Displaybuff(); 143 | 144 | delay(100); 145 | checkReboot(); 146 | if (checkNext()) 147 | { 148 | break; 149 | } 150 | 151 | // M5.update(); 152 | // delay(100); 153 | // checkAXPPress(); 154 | } 155 | // while ((M5.BtnA.isPressed()) || (M5.BtnB.isPressed())) { 156 | // M5.update(); 157 | // checkAXPPress(); 158 | // M5.Beep.tone(4000); 159 | // delay(10); 160 | // } 161 | // delay(50); 162 | // M5.Beep.mute(); 163 | 164 | Disbuff->setTextColor(TFT_WHITE); 165 | pService->stop(); 166 | pServer->getAdvertising()->stop(); 167 | } 168 | 169 | static bool is_ble_inited = false; 170 | 171 | void TEST::ble_init() 172 | { 173 | // InitBLEServer(); 174 | is_ble_inited = false; 175 | } 176 | 177 | void TEST::ble_test() 178 | { 179 | printf("ble test\n"); 180 | 181 | if (!is_ble_inited) 182 | { 183 | printf("init ble server\n"); 184 | InitBLEServer(); 185 | delay(100); 186 | is_ble_inited = true; 187 | } 188 | 189 | DisPlayBLESend(); 190 | 191 | printf("quit ble test\n"); 192 | } 193 | 194 | } 195 | -------------------------------------------------------------------------------- /src/test/test_imu.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_imu.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | typedef struct 14 | { 15 | double x; 16 | double y; 17 | double z; 18 | } point_3d_t; 19 | 20 | typedef struct 21 | { 22 | point_3d_t start_point; 23 | point_3d_t end_point; 24 | } line_3d_t; 25 | 26 | typedef struct 27 | { 28 | double x; 29 | double y; 30 | } point_2d_t; 31 | 32 | double r_rand = PI / 180; 33 | 34 | double r_alpha = 19.47 * PI / 180; 35 | double r_gamma = 20.7 * PI / 180; 36 | 37 | double sin_alpha = sin(19.47 * PI / 180); 38 | double cos_alpha = cos(19.47 * PI / 180); 39 | double sin_gamma = sin(20.7 * PI / 180); 40 | double cos_gamma = cos(20.7 * PI / 180); 41 | 42 | line_3d_t rect[12] = { 43 | {.start_point = {-1, -1, 1}, .end_point = {1, -1, 1}}, 44 | {.start_point = {1, -1, 1}, .end_point = {1, 1, 1}}, 45 | {.start_point = {1, 1, 1}, .end_point = {-1, 1, 1}}, 46 | {.start_point = {-1, 1, 1}, .end_point = {-1, -1, 1}}, 47 | { 48 | .start_point = {-1, -1, 1}, 49 | .end_point = {-1, -1, -1}, 50 | }, 51 | { 52 | .start_point = {1, -1, 1}, 53 | .end_point = {1, -1, -1}, 54 | }, 55 | { 56 | .start_point = {1, 1, 1}, 57 | .end_point = {1, 1, -1}, 58 | }, 59 | { 60 | .start_point = {-1, 1, 1}, 61 | .end_point = {-1, 1, -1}, 62 | }, 63 | {.start_point = {-1, -1, -1}, .end_point = {1, -1, -1}}, 64 | {.start_point = {1, -1, -1}, .end_point = {1, 1, -1}}, 65 | {.start_point = {1, 1, -1}, .end_point = {-1, 1, -1}}, 66 | {.start_point = {-1, 1, -1}, .end_point = {-1, -1, -1}}, 67 | }; 68 | 69 | bool point3Dto2D(point_3d_t *source, point_2d_t *point) 70 | { 71 | point->x = (source->x * cos_gamma) - (source->y * sin_gamma); 72 | point->y = -(source->x * sin_gamma * sin_alpha) - 73 | (source->y * cos_gamma * sin_alpha) + (source->z * cos_alpha); 74 | return true; 75 | } 76 | 77 | bool point2DToDisPoint(point_2d_t *point, uint8_t *x, uint8_t *y) 78 | { 79 | *x = point->x + 120; 80 | *y = 67 - point->y; 81 | return true; 82 | } 83 | 84 | bool printLine3D(LGFX_Sprite *display, line_3d_t *line, uint32_t color) 85 | { 86 | uint8_t start_x, start_y, end_x, end_y; 87 | point_2d_t point; 88 | point3Dto2D(&line->start_point, &point); 89 | point2DToDisPoint(&point, &start_x, &start_y); 90 | point3Dto2D(&line->end_point, &point); 91 | point2DToDisPoint(&point, &end_x, &end_y); 92 | 93 | display->drawLine(start_x, start_y, end_x, end_y, (int)color); 94 | 95 | return true; 96 | } 97 | 98 | void RotatePoint(point_3d_t *point, double x, double y, double z) 99 | { 100 | if (x != 0) 101 | { 102 | point->y = point->y * cos(x * r_rand) - point->z * sin(x * r_rand); 103 | point->z = point->y * sin(x * r_rand) + point->z * cos(x * r_rand); 104 | } 105 | 106 | if (y != 0) 107 | { 108 | point->x = point->z * sin(y * r_rand) + point->x * cos(y * r_rand); 109 | point->z = point->z * cos(y * r_rand) - point->x * sin(y * r_rand); 110 | } 111 | 112 | if (z != 0) 113 | { 114 | point->x = point->x * cos(z * r_rand) - point->y * sin(z * r_rand); 115 | point->y = point->x * sin(z * r_rand) + point->y * cos(z * r_rand); 116 | } 117 | } 118 | 119 | void RotatePoint(point_3d_t *point, point_3d_t *point_new, double x, double y, 120 | double z) 121 | { 122 | if (x != 0) 123 | { 124 | point_new->y = point->y * cos(x * r_rand) - point->z * sin(x * r_rand); 125 | point_new->z = point->y * sin(x * r_rand) + point->z * cos(x * r_rand); 126 | } 127 | 128 | if (y != 0) 129 | { 130 | point_new->x = point->z * sin(y * r_rand) + point->x * cos(y * r_rand); 131 | point_new->z = point->z * cos(y * r_rand) - point->x * sin(y * r_rand); 132 | } 133 | 134 | if (z != 0) 135 | { 136 | point_new->x = point->x * cos(z * r_rand) - point->y * sin(z * r_rand); 137 | point_new->y = point->x * sin(z * r_rand) + point->y * cos(z * r_rand); 138 | } 139 | } 140 | 141 | namespace TEST 142 | { 143 | 144 | void TEST::imu_init() 145 | { 146 | imu.Init(); 147 | } 148 | 149 | void TEST::imu_test() 150 | { 151 | printf("imu test\n"); 152 | 153 | float accX = 0; 154 | float accY = 0; 155 | float accZ = 0; 156 | 157 | double theta = 0, last_theta = 0; 158 | double phi = 0, last_phi = 0; 159 | double alpha = 0.2; 160 | 161 | line_3d_t x = {.start_point = {0, 0, 0}, .end_point = {0, 0, 0}}; 162 | line_3d_t y = {.start_point = {0, 0, 0}, .end_point = {0, 0, 0}}; 163 | line_3d_t z = {.start_point = {0, 0, 0}, .end_point = {0, 0, 30}}; 164 | 165 | line_3d_t rect_source[12]; 166 | line_3d_t rect_dis; 167 | for (int n = 0; n < 12; n++) 168 | { 169 | rect_source[n].start_point.x = rect[n].start_point.x * 30; 170 | rect_source[n].start_point.y = rect[n].start_point.y * 30; 171 | rect_source[n].start_point.z = rect[n].start_point.z * 30; 172 | rect_source[n].end_point.x = rect[n].end_point.x * 30; 173 | rect_source[n].end_point.y = rect[n].end_point.y * 30; 174 | rect_source[n].end_point.z = rect[n].end_point.z * 30; 175 | } 176 | 177 | while (1) 178 | { 179 | imu.getAccelData(&accX, &accY, &accZ); 180 | // printf("%f \t %f \t %f\n", accX, accY, accZ); 181 | 182 | // M5.MPU6886.getAccelData(&accX, &accY, &accZ); 183 | if ((accX < 1) && (accX > -1)) 184 | { 185 | theta = asin(-accX) * 57.295; 186 | } 187 | if (accZ != 0) 188 | { 189 | phi = atan(accY / accZ) * 57.295; 190 | } 191 | 192 | theta = alpha * theta + (1 - alpha) * last_theta; 193 | phi = alpha * phi + (1 - alpha) * last_phi; 194 | 195 | // Disbuff->fillRect(0, 0, 240, 135, TFT_BLACK); 196 | // Disbuff->setTextSize(1); 197 | // Disbuff->setCursor(10, 115); 198 | // Disbuff->printf("theta: %.2f", theta); 199 | // Disbuff->setCursor(10, 125); 200 | // Disbuff->printf("phi: %.2f", phi); 201 | 202 | display->fillScreen(TFT_BLACK); 203 | display->setTextColor(TFT_WHITE, TFT_BLACK); 204 | 205 | if (is_test_mode) 206 | { 207 | display->setFont(&fonts::efontCN_24); 208 | display->setTextSize(1); 209 | display->setCursor(0, 10); 210 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 211 | display->printf(" % 0.1f\n", accX); 212 | display->printf(" % 0.1f\n", accY); 213 | display->printf(" % 0.1f\n ^\n 确保数值稳定\n", accZ); 214 | } 215 | else 216 | { 217 | display->setFont(&fonts::Font0); 218 | Disbuff->fillRect(0, 0, 240, 135, TFT_BLACK); 219 | Disbuff->setTextSize(1); 220 | Disbuff->setCursor(10, 115); 221 | Disbuff->printf("%.2f", theta); 222 | Disbuff->setCursor(10, 125); 223 | Disbuff->printf("%.2f", phi); 224 | } 225 | 226 | z.end_point.x = 0; 227 | z.end_point.y = 0; 228 | z.end_point.z = 60; 229 | RotatePoint(&z.end_point, theta, phi, 0); 230 | RotatePoint(&z.end_point, &x.end_point, -90, 0, 0); 231 | RotatePoint(&z.end_point, &y.end_point, 0, 90, 0); 232 | 233 | for (int n = 0; n < 12; n++) 234 | { 235 | RotatePoint(&rect_source[n].start_point, &rect_dis.start_point, 236 | theta, phi, (double)0); 237 | RotatePoint(&rect_source[n].end_point, &rect_dis.end_point, theta, 238 | phi, (double)0); 239 | printLine3D(Disbuff, &rect_dis, TFT_WHITE); 240 | } 241 | // Disbuff.fillRect(0,0,160,80,BLACK); 242 | printLine3D(Disbuff, &x, TFT_RED); 243 | printLine3D(Disbuff, &y, TFT_GREEN); 244 | printLine3D(Disbuff, &z, TFT_BLUE); 245 | /* 246 | Disbuff.setTextColor(TFT_WHITE); 247 | Disbuff.setTextSize(1); 248 | Disbuff.fillRect(0,0,52,18,Disbuff.color565(20,20,20)); 249 | Disbuff.drawString("MPU6886",5,5,1); 250 | */ 251 | Displaybuff(); 252 | last_theta = theta; 253 | last_phi = phi; 254 | 255 | delay(20); 256 | 257 | checkReboot(); 258 | if (checkNext()) 259 | { 260 | printf("quit imu test\n"); 261 | break; 262 | } 263 | } 264 | } 265 | 266 | } 267 | -------------------------------------------------------------------------------- /src/test/test_io.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_io.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-31 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | namespace TEST 14 | { 15 | 16 | void TEST::gpio_test() 17 | { 18 | printf("hat test\n"); 19 | 20 | display->fillScreen(TFT_BLACK); 21 | display->setCursor(0, 0); 22 | display->setFont(&fonts::efontCN_24); 23 | display->setTextColor(TFT_YELLOW); 24 | display->setTextSize(1); 25 | display->printf(" [IO]测试\n"); 26 | displayUpdate(); 27 | 28 | // gpio_reset_pin(GPIO_NUM_19); 29 | // pinMode(19, OUTPUT); 30 | // while (1) { 31 | // digitalWrite(19, 0); 32 | // printf("19 %d\n", digitalRead(19)); 33 | // delay(1000); 34 | // digitalWrite(19, 1); 35 | // printf("19 %d\n", digitalRead(19)); 36 | // delay(1000); 37 | // } 38 | 39 | std::vector gpio_list = {GPIO_NUM_25, GPIO_NUM_19}; 40 | 41 | /* Reset */ 42 | for (auto i : gpio_list) 43 | { 44 | gpio_reset_pin(i); 45 | pinMode(i, OUTPUT); 46 | } 47 | 48 | uint32_t time_count = 0; 49 | auto iter = gpio_list.begin(); 50 | while (1) 51 | { 52 | 53 | if ((millis() - time_count) > 600) 54 | { 55 | 56 | display->fillScreen(TFT_BLACK); 57 | display->setCursor(0, 0); 58 | display->setFont(&fonts::efontCN_24); 59 | display->setTextColor(TFT_YELLOW); 60 | display->setTextSize(1); 61 | display->printf(" [IO]测试\n"); 62 | // displayUpdate(); 63 | 64 | printf("set %d %d\n", *iter, !digitalRead(*iter)); 65 | digitalWrite(*iter, !digitalRead(*iter)); 66 | 67 | iter++; 68 | if (iter == gpio_list.end()) 69 | { 70 | iter = gpio_list.begin(); 71 | } 72 | 73 | display->setCursor(0, 20); 74 | 75 | display->setTextColor(TFT_GREEN, TFT_BLACK); 76 | float v_bat = (float)analogReadMilliVolts(38) * 2 / 1000; 77 | if (v_bat < 3) 78 | { 79 | display->setTextColor(TFT_RED, TFT_BLACK); 80 | } 81 | display->printf(" 电池: %.2fV\n", v_bat); 82 | 83 | display->setTextColor(TFT_GREEN, TFT_BLACK); 84 | float v_g36 = (float)analogReadMilliVolts(36) / 1000; 85 | if (digitalRead(25)) 86 | { 87 | if (v_g36 < 2.5) 88 | { 89 | display->setTextColor(TFT_RED, TFT_BLACK); 90 | } 91 | } 92 | else 93 | { 94 | if (v_g36 > 2) 95 | { 96 | display->setTextColor(TFT_RED, TFT_BLACK); 97 | } 98 | } 99 | display->printf(" G36: %.2fV\n", v_g36); 100 | 101 | Wire.end(); 102 | Wire.begin(32, 33, 100000); 103 | 104 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 105 | display->printf(" [Grove]:"); 106 | 107 | byte error, address; 108 | uint8_t addr = 0x00; 109 | for (address = 0x01; address < 0x7f; address++) 110 | { 111 | Wire.beginTransmission(address); 112 | error = Wire.endTransmission(); 113 | if (error == 0) 114 | { 115 | // Serial.printf("I2C device found at address 0x%02X\n", address); 116 | 117 | addr = address; 118 | printf("fonud 0x%02X\n", addr); 119 | break; 120 | } 121 | } 122 | 123 | if (addr) 124 | { 125 | display->setTextColor(TFT_GREEN, TFT_BLACK); 126 | display->printf(" 0x%02X", addr); 127 | } 128 | else 129 | { 130 | display->setTextColor(TFT_RED, TFT_BLACK); 131 | display->printf(" 无"); 132 | } 133 | 134 | Wire.end(); 135 | Wire.begin(0, 26, 100000); 136 | 137 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 138 | display->printf("\n [Hat]:"); 139 | 140 | // byte error, address; 141 | addr = 0x00; 142 | for (address = 0x01; address < 0x7f; address++) 143 | { 144 | Wire.beginTransmission(address); 145 | error = Wire.endTransmission(); 146 | if (error == 0) 147 | { 148 | // Serial.printf("I2C device found at address 0x%02X\n", address); 149 | 150 | addr = address; 151 | printf("fonud 0x%02X", addr); 152 | break; 153 | } 154 | } 155 | 156 | if (addr) 157 | { 158 | display->setTextColor(TFT_GREEN, TFT_BLACK); 159 | display->printf(" 0x%02X", addr); 160 | } 161 | else 162 | { 163 | display->setTextColor(TFT_RED, TFT_BLACK); 164 | display->printf(" 无"); 165 | } 166 | 167 | displayUpdate(); 168 | 169 | time_count = millis(); 170 | } 171 | 172 | checkReboot(); 173 | if (checkNext()) 174 | { 175 | break; 176 | } 177 | } 178 | 179 | /* Reset */ 180 | for (auto i : gpio_list) 181 | { 182 | gpio_reset_pin(i); 183 | } 184 | 185 | display->setFont(&fonts::Font0); 186 | display->setTextSize(1); 187 | 188 | printf("quit hat test\n"); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /src/test/test_ir.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_ir.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | #define DECODE_NEC 13 | // #define DECODE_DENON 14 | #include 15 | #include 16 | // #include "../../lib/IRremote/src/IRremote.hpp" 17 | // #include "../../lib/IRremote/src/TinyIRSender.hpp" 18 | 19 | // extern const unsigned char icon_ir[4608]; 20 | 21 | namespace TEST 22 | { 23 | 24 | static void ir_test_task(void *param) 25 | { 26 | printf("ir task\n"); 27 | 28 | uint8_t IR_SEND_PIN = 19; 29 | uint8_t cmd = 0x00; 30 | while (1) 31 | { 32 | sendNEC(IR_SEND_PIN, 0x10, cmd, 0); 33 | printf("ir sended: addr: %0x02X cmd:0x%02X\n", 0x10, cmd); 34 | cmd++; 35 | delay(1000); 36 | } 37 | 38 | vTaskDelete(NULL); 39 | } 40 | 41 | void TEST::ir_init() 42 | { 43 | xTaskCreate(ir_test_task, "ir", 2048, NULL, 5, NULL); 44 | } 45 | 46 | void TEST::ir_test() 47 | { 48 | printf("ir test\n"); 49 | 50 | uint8_t IR_SEND_PIN = 19; 51 | // while (1) { 52 | 53 | // sendNEC(IR_SEND_PIN, 0x10, 0xFF, 0); 54 | // printf("sended\n"); 55 | // delay(1000); 56 | 57 | // } 58 | 59 | display->setFont(&fonts::Font0); 60 | 61 | uint8_t cmd = 0x00; 62 | unsigned long count = millis(); 63 | unsigned long anim_count = millis(); 64 | uint8_t anim_pos = 0; 65 | 66 | sendNEC(IR_SEND_PIN, 0x10, cmd, 0); 67 | printf("ir sended: addr: 0x%02X cmd:0x%02X\n", 0x10, cmd); 68 | 69 | while (1) 70 | { 71 | 72 | if ((millis() - count) > 800) 73 | { 74 | cmd++; 75 | sendNEC(IR_SEND_PIN, 0x10, cmd, 0); 76 | printf("ir sended: addr: 0x%02X cmd:0x%02X\n", 0x10, cmd); 77 | count = millis(); 78 | } 79 | 80 | if ((millis() - anim_count) > 400) 81 | { 82 | 83 | anim_pos++; 84 | if (anim_pos > 3) 85 | { 86 | anim_pos = 0; 87 | } 88 | 89 | Disbuff->fillRect(0, 0, 240, 135, TFT_BLACK); 90 | // Disbuff->setSwapBytes(true); 91 | Disbuff->pushImage(180, 16, 48, 48, (uint16_t *)icon_ir); 92 | Disbuff->setTextColor(Disbuff->color565(180, 180, 180)); 93 | Disbuff->setTextSize(3); 94 | Disbuff->setCursor(12, 20); 95 | Disbuff->printf("IR Send "); 96 | Disbuff->setTextSize(5); 97 | Disbuff->setCursor(12, 75); 98 | 99 | switch (anim_pos) 100 | { 101 | case 0: 102 | Disbuff->printf("0x%02X> ", cmd); 103 | break; 104 | case 1: 105 | Disbuff->printf("0x%02X>> ", cmd); 106 | break; 107 | case 2: 108 | Disbuff->printf("0x%02X >>", cmd); 109 | break; 110 | case 3: 111 | Disbuff->printf("0x%02X >", cmd); 112 | break; 113 | default: 114 | break; 115 | } 116 | 117 | if (is_test_mode) 118 | { 119 | display->setFont(&fonts::efontCN_24); 120 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 121 | display->setTextSize(1); 122 | display->setCursor(0, 0); 123 | display->printf("距离[2米]测试"); 124 | display->setFont(&fonts::Font0); 125 | } 126 | 127 | displayUpdate(); 128 | 129 | anim_count = millis(); 130 | } 131 | 132 | checkReboot(); 133 | if (checkNext()) 134 | { 135 | break; 136 | } 137 | } 138 | 139 | printf("quit ir test\n"); 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/test/test_key.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_key.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | namespace TEST 14 | { 15 | 16 | void TEST::key_init() 17 | { 18 | btnA.begin(); 19 | btnB.begin(); 20 | btnPWR.begin(); 21 | } 22 | 23 | void TEST::key_test() 24 | { 25 | // while (1) { 26 | // printf("%d %d %d\n", btnA.pressed(), btnB.pressed(), btnPWR.pressed()); 27 | // delay(10); 28 | // } 29 | 30 | display->fillScreen(TFT_BLACK); 31 | display->setFont(&fonts::efontCN_24); 32 | display->setTextSize(1); 33 | 34 | display->setCursor(0, 0); 35 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 36 | display->printf(" [按键测试]\n 请按下各个按键3次\n"); 37 | 38 | uint8_t key_pressed_times[3] = {0, 0, 0}; 39 | bool pass = false; 40 | 41 | while (1) 42 | { 43 | if (btnA.pressed()) 44 | { 45 | _tone(5000, 50); 46 | key_pressed_times[1]++; 47 | } 48 | if (btnB.pressed()) 49 | { 50 | _tone(5500, 50); 51 | key_pressed_times[2]++; 52 | } 53 | if (btnPWR.pressed()) 54 | { 55 | _tone(3500, 50); 56 | key_pressed_times[0]++; 57 | } 58 | 59 | display->setCursor(0, 60); 60 | for (int i = 0; i < 3; i++) 61 | { 62 | display->setTextColor((key_pressed_times[i] > 2) ? TFT_GREEN : TFT_BLUE, TFT_BLACK); 63 | // display->printf(" 按键%d: %d\n", i, key_pressed_times[i]); 64 | if (i == 0) 65 | { 66 | display->printf(" 电源键: %d\n", key_pressed_times[i]); 67 | } 68 | else if (i == 1) 69 | { 70 | display->printf(" 按键A: %d\n", key_pressed_times[i]); 71 | } 72 | else if (i == 2) 73 | { 74 | display->printf(" 按键B: %d\n", key_pressed_times[i]); 75 | } 76 | } 77 | display->printf("\n"); 78 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 79 | displayUpdate(); 80 | 81 | for (int i = 0; i < 3; i++) 82 | { 83 | if (key_pressed_times[i] > 2) 84 | { 85 | pass = true; 86 | } 87 | else 88 | { 89 | pass = false; 90 | break; 91 | } 92 | } 93 | if (pass) 94 | { 95 | printf("key test passed\n"); 96 | delay(200); 97 | break; 98 | } 99 | } 100 | } 101 | 102 | void TEST::checkReboot() 103 | { 104 | // if (btnPWR.pressed()) { 105 | // printf("rebooting...\n"); 106 | // esp_restart(); 107 | // } 108 | 109 | // printf("%d\n", btnPWR.read()); 110 | 111 | // uint8_t count = 0; 112 | // if (!btnPWR.read()) { 113 | // delay(10); 114 | // if (!btnPWR.read()) { 115 | 116 | // _tone(3500, 50); 117 | 118 | // while (!btnPWR.read()) { 119 | // delay(100); 120 | // count++; 121 | // } 122 | // if (count > 30) { 123 | // power_off(); 124 | // } 125 | // else { 126 | // printf("rebooting...\n"); 127 | // esp_restart(); 128 | // } 129 | // } 130 | // } 131 | 132 | // if (btnPWR.pressed()) { 133 | // _tone(3500, 50); 134 | 135 | // for (int i = 0; i < 4; i++) { 136 | // delay(50); 137 | // if (btnPWR.pressed()) { 138 | // _tone(3500, 50); 139 | // printf("double\n"); 140 | // power_off(); 141 | // } 142 | // } 143 | // printf("not double\n"); 144 | // printf("rebooting...\n"); 145 | // esp_restart(); 146 | // } 147 | 148 | /* Long press power off */ 149 | if (!btnPWR.read()) 150 | { 151 | _tone(3500, 50); 152 | 153 | uint32_t time_count = millis(); 154 | 155 | while (!btnPWR.read()) 156 | { 157 | 158 | display->setCursor(0, 10); 159 | display->setFont(&fonts::Font0); 160 | display->setTextSize(2); 161 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 162 | display->printf(" PWR OFF IN %d/3\n", (millis() - time_count) / 1000 + 1); 163 | displayUpdate(); 164 | 165 | delay(10); 166 | } 167 | 168 | printf("rebooting...\n"); 169 | 170 | display->fillScreen(TFT_BLACK); 171 | display->setCursor(0, 10); 172 | display->setFont(&fonts::Font0); 173 | display->setTextSize(2); 174 | display->setTextColor(TFT_RED, TFT_BLACK); 175 | display->drawCenterString("REBOOTING...\n", display->width() / 2, display->height() / 2 - 12); 176 | displayUpdate(); 177 | 178 | delay(500); 179 | 180 | esp_restart(); 181 | } 182 | } 183 | 184 | bool TEST::checkNext() 185 | { 186 | // if (btnA.pressed() || btnB.pressed()) { 187 | // return true; 188 | // } 189 | if (btnA.pressed()) 190 | { 191 | _tone(5000, 50); 192 | return true; 193 | } 194 | if (btnB.pressed()) 195 | { 196 | _tone(5500, 50); 197 | return true; 198 | } 199 | 200 | // uint8_t count = 0; 201 | // if (!btnB.read()) { 202 | // delay(10); 203 | // if (!btnB.read()) { 204 | 205 | // _tone(5500, 50); 206 | 207 | // while (!btnB.read()) { 208 | // delay(50); 209 | // count++; 210 | // if (count > 60) { 211 | // power_off(); 212 | // } 213 | // } 214 | // return true; 215 | // } 216 | // } 217 | 218 | return false; 219 | } 220 | 221 | void TEST::waitNext() 222 | { 223 | while (!checkNext()) 224 | { 225 | checkReboot(); 226 | delay(10); 227 | } 228 | printf("go next\n"); 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/test/test_lcd.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_lcd.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-25 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | namespace TEST 14 | { 15 | 16 | void TEST::Displaybuff() 17 | { 18 | Disbuff->pushSprite(0, 0); 19 | } 20 | 21 | void TEST::ColorBar() 22 | { 23 | float color_r, color_g, color_b; 24 | 25 | color_r = 0; 26 | color_g = 0; 27 | color_b = 255; 28 | 29 | for (int i = 0; i < 384; i = i + 4) 30 | { 31 | if (i < 128) 32 | { 33 | color_r = i * 2; 34 | color_g = 0; 35 | color_b = 255 - (i * 2); 36 | } 37 | else if ((i >= 128) && (i < 256)) 38 | { 39 | color_r = 255 - ((i - 128) * 2); 40 | color_g = (i - 128) * 2; 41 | color_b = 0; 42 | } 43 | else if ((i >= 256) && (i < 384)) 44 | { 45 | color_r = 0; 46 | color_g = 255 - ((i - 256) * 2); 47 | ; 48 | color_b = (i - 256) * 2; 49 | ; 50 | } 51 | Disbuff->fillRect(0, 0, 240, 135, 52 | Disbuff->color565(color_r, color_g, color_b)); 53 | Displaybuff(); 54 | } 55 | 56 | for (int i = 0; i < 4; i++) 57 | { 58 | switch (i) 59 | { 60 | case 0: 61 | color_r = 0; 62 | color_g = 0; 63 | color_b = 0; 64 | break; 65 | case 1: 66 | color_r = 255; 67 | color_g = 0; 68 | color_b = 0; 69 | break; 70 | case 2: 71 | color_r = 0; 72 | color_g = 255; 73 | color_b = 0; 74 | break; 75 | case 3: 76 | color_r = 0; 77 | color_g = 0; 78 | color_b = 255; 79 | break; 80 | } 81 | for (int n = 0; n < 240; n++) 82 | { 83 | color_r = (color_r < 255) ? color_r + 1.0625 : 255U; 84 | color_g = (color_g < 255) ? color_g + 1.0625 : 255U; 85 | color_b = (color_b < 255) ? color_b + 1.0625 : 255U; 86 | Disbuff->drawLine(n, i * 33.75, n, (i + 1) * 33.75, 87 | Disbuff->color565(color_r, color_g, color_b)); 88 | } 89 | } 90 | Displaybuff(); 91 | delay(500); 92 | 93 | for (int i = 0; i < 4; i++) 94 | { 95 | switch (i) 96 | { 97 | case 0: 98 | color_r = 255; 99 | color_g = 255; 100 | color_b = 255; 101 | break; 102 | case 1: 103 | color_r = 255; 104 | color_g = 0; 105 | color_b = 0; 106 | break; 107 | case 2: 108 | color_r = 0; 109 | color_g = 255; 110 | color_b = 0; 111 | break; 112 | case 3: 113 | color_r = 0; 114 | color_g = 0; 115 | color_b = 255; 116 | break; 117 | } 118 | for (int n = 0; n < 240; n++) 119 | { 120 | color_r = (color_r > 2) ? color_r - 1.0625 : 0U; 121 | color_g = (color_g > 2) ? color_g - 1.0625 : 0U; 122 | color_b = (color_b > 2) ? color_b - 1.0625 : 0U; 123 | Disbuff->drawLine(239 - n, i * 33.75, 239 - n, (i + 1) * 33.75, 124 | Disbuff->color565(color_r, color_g, color_b)); 125 | } 126 | } 127 | Displaybuff(); 128 | delay(500); 129 | } 130 | 131 | void TEST::frame_test() 132 | { 133 | display->fillScreen(TFT_BLACK); 134 | display->drawRect(0, 0, display->width(), display->height(), TFT_GREEN); 135 | display->drawRect(1, 1, display->width() - 2, display->height() - 2, TFT_GREEN); 136 | display->drawLine(0, 0, display->width(), display->height(), TFT_GREEN); 137 | display->drawLine(0, display->height(), display->width(), 0, TFT_GREEN); 138 | displayUpdate(); 139 | 140 | waitNext(); 141 | } 142 | 143 | void TEST::color_test() 144 | { 145 | std::vector color_list = {TFT_RED, TFT_GREEN, TFT_BLUE, TFT_BLACK, TFT_WHITE}; 146 | for (auto i : color_list) 147 | { 148 | display->fillScreen(i); 149 | displayUpdate(); 150 | waitNext(); 151 | } 152 | } 153 | 154 | void TEST::lcd_init() 155 | { 156 | lcd.begin(); 157 | lcd.setRotation(3); 158 | // lcd.setBrightness(255); 159 | 160 | // lcd.setBrightness(200); 161 | 162 | // lcd.fillScreen(TFT_RED); 163 | // while (1); 164 | // lcd.setTextColor(TFT_WHITE, TFT_RED); 165 | // lcd.setTextSize(3); 166 | // uint8_t bbb = 0; 167 | // while (1) { 168 | // printf("%d\n", bbb); 169 | // lcd.setBrightness(bbb); 170 | // lcd.setCursor(10, 10); 171 | // lcd.printf("%d ", bbb); 172 | // bbb++; 173 | // delay(20); 174 | // } 175 | 176 | /* Full scren sprite */ 177 | Disbuff = new LGFX_Sprite(&lcd); 178 | Disbuff->createSprite(lcd.width(), lcd.height()); 179 | } 180 | 181 | void TEST::lcd_test() 182 | { 183 | // ColorBar(); 184 | 185 | frame_test(); 186 | color_test(); 187 | 188 | // ColorBar(); 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /src/test/test_mic.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_mic.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | // #include "fft/fft.h" 13 | 14 | // extern const unsigned char ImageData[768]; 15 | 16 | static LGFX_Sprite *__display_ptr; 17 | // #define Disbuff __display_ptr 18 | 19 | namespace TEST 20 | { 21 | 22 | static SemaphoreHandle_t xSemaphore = NULL; 23 | static SemaphoreHandle_t start_dis = NULL; 24 | static SemaphoreHandle_t start_fft = NULL; 25 | // static int8_t i2s_readraw_buff[2048]; 26 | // static uint8_t fft_dis_buff[241][128] = {0}; 27 | static uint16_t posData = 160; 28 | 29 | static int8_t *_new_i2s_readraw_buff = nullptr; 30 | static uint8_t **_new_fft_dis_buff = nullptr; 31 | 32 | static void MicRecordfft(void *arg) 33 | { 34 | // int16_t *buffptr; 35 | // size_t bytesread; 36 | // uint16_t count_n = 0; 37 | // float adc_data; 38 | // double data = 0; 39 | // uint16_t ydata; 40 | 41 | // while (1) { 42 | // xSemaphoreTake(start_fft, portMAX_DELAY); 43 | // xSemaphoreGive(start_fft); 44 | // fft_config_t *real_fft_plan = 45 | // fft_init(1024, FFT_REAL, FFT_FORWARD, NULL, NULL); 46 | // i2s_read(I2S_NUM_0, (char *)_new_i2s_readraw_buff, 2048, &bytesread, 47 | // (100 / portTICK_RATE_MS)); 48 | // buffptr = (int16_t *)_new_i2s_readraw_buff; 49 | 50 | // for (count_n = 0; count_n < real_fft_plan->size; count_n++) { 51 | // adc_data = 52 | // (float)map(buffptr[count_n], INT16_MIN, INT16_MAX, -2000, 2000); 53 | // real_fft_plan->input[count_n] = adc_data; 54 | // } 55 | // fft_execute(real_fft_plan); 56 | 57 | // xSemaphoreTake(xSemaphore, 100 / portTICK_RATE_MS); 58 | // for (count_n = 1; count_n < real_fft_plan->size / 4; count_n++) { 59 | // data = sqrt(real_fft_plan->output[2 * count_n] * 60 | // real_fft_plan->output[2 * count_n] + 61 | // real_fft_plan->output[2 * count_n + 1] * 62 | // real_fft_plan->output[2 * count_n + 1]); 63 | // if ((count_n - 1) < 128) { 64 | // data = (data > 2000) ? 2000 : data; 65 | // ydata = map(data, 0, 2000, 0, 255); 66 | // _new_fft_dis_buff[posData][128 - count_n] = ydata; 67 | // } 68 | // } 69 | 70 | // posData++; 71 | // if (posData >= 241) { 72 | // posData = 0; 73 | // } 74 | // xSemaphoreGive(xSemaphore); 75 | // fft_destroy(real_fft_plan); 76 | // } 77 | } 78 | 79 | static void Drawdisplay(void *arg) 80 | { 81 | uint16_t count_x = 0, count_y = 0; 82 | uint16_t colorPos; 83 | while (1) 84 | { 85 | xSemaphoreTake(start_dis, portMAX_DELAY); 86 | xSemaphoreGive(start_dis); 87 | xSemaphoreTake(xSemaphore, 500 / portTICK_RATE_MS); 88 | for (count_y = 0; count_y < 128; count_y++) 89 | { 90 | for (count_x = 0; count_x < 240; count_x++) 91 | { 92 | if ((count_x + (posData % 240)) > 240) 93 | { 94 | colorPos = 95 | _new_fft_dis_buff[count_x + (posData % 240) - 240][count_y]; 96 | } 97 | else 98 | { 99 | colorPos = _new_fft_dis_buff[count_x + (posData % 240)][count_y]; 100 | } 101 | 102 | __display_ptr->drawPixel( 103 | count_x, count_y + 4, 104 | __display_ptr->color565(ImageData[colorPos * 3 + 0], 105 | ImageData[colorPos * 3 + 1], 106 | ImageData[colorPos * 3 + 2])); 107 | /* 108 | disbuff[ count_y * 160 + count_x ].r = ImageData[ colorPos * 3 109 | + 0 ]; disbuff[ count_y * 160 + count_x ].g = ImageData[ 110 | colorPos * 3 + 1 ]; disbuff[ count_y * 160 + count_x ].b = 111 | ImageData[ colorPos * 3 + 2 ]; 112 | */ 113 | } 114 | } 115 | xSemaphoreGive(xSemaphore); 116 | delay(5); 117 | /* 118 | Disbuff.setTextColor(WHITE); 119 | Disbuff.setTextSize(1); 120 | Disbuff.fillRect(0,0,70,18,Disbuff.color565(20,20,20)); 121 | Disbuff.drawString("MicroPhone",5,5,1); 122 | */ 123 | __display_ptr->pushSprite(0, 0); 124 | } 125 | } 126 | 127 | static TaskHandle_t xhandle_display = NULL; 128 | static TaskHandle_t xhandle_fft = NULL; 129 | 130 | void TEST::DisplayMicro() 131 | { 132 | __display_ptr->fillRect(0, 0, 160, 80, __display_ptr->color565(0, 0, 0)); 133 | __display_ptr->pushSprite(0, 0); 134 | 135 | // printf("nihao\n"); 136 | 137 | // xSemaphoreGive(start_dis); 138 | // xSemaphoreGive(start_fft); 139 | // while ((!M5.BtnA.isPressed()) && (!M5.BtnB.isPressed())) { 140 | // xSemaphoreGive(start_dis); 141 | // xSemaphoreGive(start_fft); 142 | // M5.update(); 143 | // // delay(100); 144 | // xSemaphoreTake(start_dis, portMAX_DELAY); 145 | // xSemaphoreTake(start_fft, portMAX_DELAY); 146 | // } 147 | 148 | /* Enable mic display */ 149 | xSemaphoreGive(start_dis); 150 | xSemaphoreGive(start_fft); 151 | waitNext(); 152 | printf("wait dis mutex\n"); 153 | xSemaphoreTake(start_dis, portMAX_DELAY); 154 | printf("wait fft mutex\n"); 155 | xSemaphoreTake(start_fft, portMAX_DELAY); 156 | printf("mutex take ok\n"); 157 | /* Wait update mic display task */ 158 | delay(200); 159 | 160 | // xSemaphoreTake( start_dis , portMAX_DELAY ); 161 | // xSemaphoreTake( start_fft , portMAX_DELAY ); 162 | 163 | // while ((M5.BtnA.isPressed()) || (M5.BtnB.isPressed())) { 164 | // M5.update(); 165 | // checkAXPPress(); 166 | // M5.Beep.tone(4000); 167 | // delay(10); 168 | // } 169 | // delay(50); 170 | // M5.Beep.mute(); 171 | } 172 | 173 | void TEST::mic_test_one_task() 174 | { 175 | display->fillScreen(TFT_BLACK); 176 | 177 | /* Mic data */ 178 | int16_t *buffptr; 179 | size_t bytesread; 180 | uint16_t count_n = 0; 181 | float adc_data; 182 | double data = 0; 183 | uint16_t ydata; 184 | uint32_t update_count = 0; 185 | 186 | /* Display data */ 187 | uint16_t count_x = 0, count_y = 0; 188 | uint16_t colorPos; 189 | 190 | while (1) 191 | { 192 | 193 | // /* Mic get data */ 194 | // // if ((millis() - update_count) > 5) { 195 | 196 | // fft_config_t *real_fft_plan = 197 | // // fft_init(1024, FFT_REAL, FFT_FORWARD, NULL, NULL); 198 | // i2s_read(I2S_NUM_0, (char *)_new_i2s_readraw_buff, 2048, &bytesread, 199 | // (100 / portTICK_RATE_MS)); 200 | // buffptr = (int16_t *)_new_i2s_readraw_buff; 201 | 202 | // for (count_n = 0; count_n < real_fft_plan->size; count_n++) { 203 | // adc_data = 204 | // (float)map(buffptr[count_n], INT16_MIN, INT16_MAX, -2000, 2000); 205 | // real_fft_plan->input[count_n] = adc_data; 206 | // } 207 | // fft_execute(real_fft_plan); 208 | 209 | // for (count_n = 1; count_n < real_fft_plan->size / 4; count_n++) { 210 | // data = sqrt(real_fft_plan->output[2 * count_n] * 211 | // real_fft_plan->output[2 * count_n] + 212 | // real_fft_plan->output[2 * count_n + 1] * 213 | // real_fft_plan->output[2 * count_n + 1]); 214 | // if ((count_n - 1) < 128) { 215 | // data = (data > 2000) ? 2000 : data; 216 | // ydata = map(data, 0, 2000, 0, 255); 217 | // _new_fft_dis_buff[posData][128 - count_n] = ydata; 218 | // } 219 | // } 220 | 221 | // posData++; 222 | // if (posData >= 241) { 223 | // posData = 0; 224 | // } 225 | // fft_destroy(real_fft_plan); 226 | 227 | // // update_count = millis(); 228 | // // } 229 | 230 | /* Display */ 231 | for (count_y = 0; count_y < 128; count_y++) 232 | { 233 | for (count_x = 0; count_x < 240; count_x++) 234 | { 235 | if ((count_x + (posData % 240)) > 240) 236 | { 237 | colorPos = 238 | _new_fft_dis_buff[count_x + (posData % 240) - 240][count_y]; 239 | } 240 | else 241 | { 242 | colorPos = _new_fft_dis_buff[count_x + (posData % 240)][count_y]; 243 | } 244 | 245 | display->drawPixel( 246 | count_x, count_y + 4, 247 | display->color565(ImageData[colorPos * 3 + 0], 248 | ImageData[colorPos * 3 + 1], 249 | ImageData[colorPos * 3 + 2])); 250 | /* 251 | disbuff[ count_y * 160 + count_x ].r = ImageData[ colorPos * 3 252 | + 0 ]; disbuff[ count_y * 160 + count_x ].g = ImageData[ 253 | colorPos * 3 + 1 ]; disbuff[ count_y * 160 + count_x ].b = 254 | ImageData[ colorPos * 3 + 2 ]; 255 | */ 256 | } 257 | } 258 | // delay(5); 259 | /* 260 | Disbuff.setTextColor(WHITE); 261 | Disbuff.setTextSize(1); 262 | Disbuff.fillRect(0,0,70,18,Disbuff.color565(20,20,20)); 263 | Disbuff.drawString("MicroPhone",5,5,1); 264 | */ 265 | display->pushSprite(0, 0); 266 | 267 | checkReboot(); 268 | if (checkNext()) 269 | { 270 | break; 271 | } 272 | } 273 | } 274 | 275 | // #define I2S_DATA_PIN 34 276 | // #define I2S_SCLK_PIN 0 277 | 278 | #define PIN_CLK 0 279 | #define PIN_DATA 34 280 | 281 | bool InitI2SMicroPhone() 282 | { 283 | esp_err_t err = ESP_OK; 284 | i2s_config_t i2s_config = { 285 | .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), 286 | // .sample_rate = 44100, 287 | .sample_rate = 48000, 288 | .bits_per_sample = 289 | I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB 290 | .channel_format = I2S_CHANNEL_FMT_ALL_RIGHT, 291 | #if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 1, 0) 292 | .communication_format = 293 | I2S_COMM_FORMAT_STAND_I2S, // Set the format of the communication. 294 | #else // 设置通讯格式 295 | .communication_format = I2S_COMM_FORMAT_I2S, 296 | #endif 297 | .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, 298 | .dma_buf_count = 2, 299 | .dma_buf_len = 128, 300 | }; 301 | 302 | i2s_pin_config_t pin_config; 303 | #if (ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 3, 0)) 304 | pin_config.mck_io_num = I2S_PIN_NO_CHANGE; 305 | #endif 306 | pin_config.bck_io_num = I2S_PIN_NO_CHANGE; 307 | pin_config.ws_io_num = PIN_CLK; 308 | pin_config.data_out_num = I2S_PIN_NO_CHANGE; 309 | pin_config.data_in_num = PIN_DATA; 310 | 311 | err += i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL); 312 | err += i2s_set_pin(I2S_NUM_0, &pin_config); 313 | // err += i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, 314 | // I2S_CHANNEL_MONO); 315 | err += i2s_set_clk(I2S_NUM_0, 48000, I2S_BITS_PER_SAMPLE_16BIT, 316 | I2S_CHANNEL_MONO); 317 | // i2s_set_clk(0) 318 | 319 | if (err != ESP_OK) 320 | { 321 | return false; 322 | } 323 | else 324 | { 325 | return true; 326 | } 327 | } 328 | 329 | void TEST::mic_init() 330 | { 331 | // InitI2SMicroPhone(); 332 | printf("mic init %s\n", InitI2SMicroPhone() ? "ok" : "failed"); 333 | 334 | // __display_ptr = Disbuff; 335 | 336 | // xSemaphore = xSemaphoreCreateMutex(); 337 | // start_dis = xSemaphoreCreateMutex(); 338 | // start_fft = xSemaphoreCreateMutex(); 339 | 340 | // xSemaphoreTake(start_dis, portMAX_DELAY); 341 | // xSemaphoreTake(start_fft, portMAX_DELAY); 342 | 343 | // xTaskCreate(Drawdisplay, "Drawdisplay", 1024 * 2, (void *)0, 4, 344 | // &xhandle_display); 345 | // xTaskCreate(MicRecordfft, "MicRecordfft", 1024 * 2, (void *)0, 5, 346 | // &xhandle_fft); 347 | } 348 | 349 | bool is_first_time = true; 350 | 351 | void TEST::mic_test() 352 | { 353 | printf("mic test\n"); 354 | 355 | // /* Alloc buffer */ 356 | // _new_i2s_readraw_buff = nullptr; 357 | // _new_i2s_readraw_buff = new int8_t[2048]; 358 | 359 | // printf("%p\n", _new_i2s_readraw_buff); 360 | 361 | // if (_new_i2s_readraw_buff == nullptr) { 362 | // printf("buffer readraw alloc failed\n"); 363 | // return; 364 | // } 365 | 366 | // // [241][128] 367 | // int a = 241; 368 | // int b = 128; 369 | // _new_fft_dis_buff = nullptr; 370 | // _new_fft_dis_buff = new uint8_t*[a]; 371 | 372 | // if (_new_fft_dis_buff == nullptr) { 373 | // printf("buffer fftdis alloc failed\n"); 374 | // return; 375 | // } 376 | 377 | // for (int i = 0; i < a; i++) { 378 | // _new_fft_dis_buff[i] = new uint8_t[b]; 379 | // } 380 | 381 | // /* memset */ 382 | // if (is_first_time) { 383 | // for (int i = 0; i < a; i++) { 384 | // for (int j = 0; j < b; j++) { 385 | // _new_fft_dis_buff[i][j] = 0; 386 | // } 387 | // } 388 | // // is_first_time = false; 389 | // } 390 | 391 | /* malloc way */ 392 | 393 | _new_i2s_readraw_buff = NULL; 394 | _new_i2s_readraw_buff = (int8_t *)malloc(2048 * sizeof(int8_t)); 395 | if (_new_i2s_readraw_buff == NULL) 396 | { 397 | printf("buffer readraw alloc failed\n"); 398 | return; 399 | } 400 | 401 | // [241][128] 402 | int a = 241; 403 | int b = 128; 404 | _new_fft_dis_buff = NULL; 405 | // _new_fft_dis_buff = new uint8_t*[a]; 406 | _new_fft_dis_buff = (uint8_t **)malloc(a * sizeof(uint8_t *)); 407 | 408 | if (_new_fft_dis_buff == NULL) 409 | { 410 | printf("buffer fftdis alloc failed\n"); 411 | return; 412 | } 413 | 414 | for (int i = 0; i < a; i++) 415 | { 416 | _new_fft_dis_buff[i] = NULL; 417 | // _new_fft_dis_buff[i] = new uint8_t[b]; 418 | _new_fft_dis_buff[i] = (uint8_t *)malloc(b * sizeof(uint8_t)); 419 | if (_new_fft_dis_buff[i] == NULL) 420 | { 421 | printf("buffer fftdis:%d alloc failed\n", i); 422 | return; 423 | } 424 | } 425 | 426 | /* memset */ 427 | if (is_first_time) 428 | { 429 | for (int i = 0; i < a; i++) 430 | { 431 | for (int j = 0; j < b; j++) 432 | { 433 | _new_fft_dis_buff[i][j] = 0; 434 | } 435 | } 436 | // is_first_time = false; 437 | } 438 | 439 | // printf("create mutex\n"); 440 | // __display_ptr = Disbuff; 441 | // xSemaphore = xSemaphoreCreateMutex(); 442 | // start_dis = xSemaphoreCreateMutex(); 443 | // start_fft = xSemaphoreCreateMutex(); 444 | // xSemaphoreTake(start_dis, portMAX_DELAY); 445 | // xSemaphoreTake(start_fft, portMAX_DELAY); 446 | 447 | // printf("create tasks\n"); 448 | // xhandle_display = NULL; 449 | // xTaskCreate(Drawdisplay, "Drawdisplay", 1024 * 2, NULL, 10, 450 | // &xhandle_display); 451 | 452 | // if (xhandle_display == NULL) { 453 | // printf("task Drawdisplay create failed\n"); 454 | // return; 455 | // } 456 | 457 | // xhandle_fft = NULL; 458 | // xTaskCreate(MicRecordfft, "MicRecordfft", 1024 * 2, NULL, 11, 459 | // &xhandle_fft); 460 | // if (xhandle_display == NULL) { 461 | // printf("task MicRecordfft create failed\n"); 462 | // return; 463 | // } 464 | 465 | // display->fillScreen(TFT_BLACK); 466 | // DisplayMicro(); 467 | 468 | // printf("delect tasks\n"); 469 | // vTaskDelete(xhandle_display); 470 | // vTaskDelete(xhandle_fft); 471 | 472 | mic_test_one_task(); 473 | 474 | // /* Release buffer */ 475 | // delete [] _new_i2s_readraw_buff; 476 | 477 | // for (int i = 0; i < a; i++) { 478 | // delete [] _new_fft_dis_buff[i]; 479 | // } 480 | // delete [] _new_fft_dis_buff; 481 | 482 | /* free way */ 483 | printf("free %p\n", _new_i2s_readraw_buff); 484 | free(_new_i2s_readraw_buff); 485 | 486 | for (int i = 0; i < a; i++) 487 | { 488 | // delete [] _new_fft_dis_buff[i]; 489 | // printf("free %p\n", _new_fft_dis_buff[i]); 490 | free(_new_fft_dis_buff[i]); 491 | } 492 | // delete [] _new_fft_dis_buff; 493 | printf("free %p\n", _new_fft_dis_buff); 494 | free(_new_fft_dis_buff); 495 | 496 | printf("quit mic test\n"); 497 | } 498 | 499 | void TEST::new_mic_test() 500 | { 501 | printf("mic test\n"); 502 | 503 | display->fillScreen(TFT_BLACK); 504 | display->setFont(&fonts::Font0); 505 | display->setTextSize(2); 506 | display->setTextColor(TFT_WHITE); 507 | // display->setCursor(0, 6); 508 | 509 | // display->fillRect(0, 0, 240, 25, Disbuff->color565(20, 20, 20)); 510 | // display->printf(" Mic test\n"); 511 | 512 | /* Alloc buffer */ 513 | printf("new mic_buffer[%d]\n", display->width()); 514 | int16_t *mic_buffer = nullptr; 515 | mic_buffer = new int16_t[display->width()]; 516 | if (mic_buffer == nullptr) 517 | { 518 | printf("failed\n"); 519 | return; 520 | } 521 | 522 | int _color_list[] = { 523 | TFT_YELLOW, 524 | TFT_ORANGE, 525 | TFT_GREENYELLOW, 526 | TFT_PINK, 527 | TFT_BROWN, 528 | TFT_GOLD, 529 | TFT_SILVER, 530 | }; 531 | int color_num = 0; 532 | 533 | size_t bytes_read = 0; 534 | while (1) 535 | { 536 | 537 | /* Read mic */ 538 | i2s_read(I2S_NUM_0, (void *)mic_buffer, (sizeof(int16_t) * display->width()), &bytes_read, (100 / portTICK_RATE_MS)); 539 | 540 | // printf("read %d\n", bytes_read); 541 | // delay(100); 542 | 543 | display->fillScreen(TFT_BLACK); 544 | 545 | for (int i = 0; i < 240; i++) 546 | { 547 | 548 | mic_buffer[i] = mic_buffer[i] / 20; 549 | 550 | // printf("m:%d\n", mic_buffer[i]); 551 | 552 | // display->fillCircle(i, mic_buffer[i], 1, TFT_YELLOW); 553 | 554 | display->drawPixel(i, mic_buffer[i], _color_list[color_num]); 555 | color_num++; 556 | if (color_num >= 7) 557 | color_num = 0; 558 | } 559 | 560 | display->setCursor(0, 6); 561 | display->fillRect(0, 0, 240, 25, Disbuff->color565(20, 20, 20)); 562 | display->printf(" Mic test\n"); 563 | displayUpdate(); 564 | 565 | checkReboot(); 566 | if (checkNext()) 567 | { 568 | break; 569 | } 570 | } 571 | 572 | /* Free buffer */ 573 | printf("free mic buffer\n"); 574 | delete[] mic_buffer; 575 | 576 | printf("quit mic test\n"); 577 | } 578 | 579 | void TEST::new_mic_test_fft() 580 | { 581 | printf("mic test\n"); 582 | 583 | display->fillScreen(TFT_BLACK); 584 | display->setFont(&fonts::Font0); 585 | display->setTextSize(2); 586 | display->setTextColor(TFT_WHITE); 587 | 588 | // /* Alloc buffer */ 589 | // printf("new mic_buffer[%d]\n", display->width()); 590 | // int16_t* mic_buffer = nullptr; 591 | // mic_buffer = new int16_t[display->width()]; 592 | // if (mic_buffer == nullptr) { 593 | // printf("failed\n"); 594 | // return; 595 | // } 596 | 597 | arduinoFFT _FFT; 598 | 599 | /* 600 | These values can be changed in order to evaluate the functions 601 | */ 602 | const uint16_t _samples = 256; // This value MUST ALWAYS be a power of 2 603 | const double _samplingFrequency = 48000; 604 | 605 | /* 606 | These are the input and output vectors 607 | Input vectors receive computed results from FFT 608 | */ 609 | // static double vReal[samples]; 610 | // static double vImag[samples]; 611 | double *_vReal; 612 | double *_vReal_old; 613 | double *_vImag; 614 | int16_t *_rawData; 615 | 616 | /* Init */ 617 | display->setRotation(2); 618 | /* Alloc buffer */ 619 | _vReal = new double[_samples]; 620 | _vReal_old = new double[_samples](); 621 | _vImag = new double[_samples]; 622 | _rawData = new int16_t[_samples]; 623 | 624 | int _color_list[] = { 625 | TFT_YELLOW, 626 | TFT_ORANGE, 627 | TFT_GREENYELLOW, 628 | TFT_PINK, 629 | TFT_BROWN, 630 | TFT_GOLD, 631 | TFT_SILVER, 632 | }; 633 | int color_num = 0; 634 | 635 | size_t bytes_read = 0; 636 | while (1) 637 | { 638 | 639 | /* Read mic */ 640 | // i2s_read(I2S_NUM_0, (void*)mic_buffer, (sizeof(int16_t) * display->width()), &bytes_read, (100 / portTICK_RATE_MS)); 641 | // printf("read %d\n", bytes_read); 642 | // delay(100); 643 | 644 | i2s_read(I2S_NUM_0, (void *)_rawData, (sizeof(int16_t) * _samples), &bytes_read, (100 / portTICK_RATE_MS)); 645 | // printf("read %d\n", bytes_read); 646 | 647 | display->fillScreen(TFT_BLACK); 648 | 649 | /* Copy data */ 650 | for (int i = 0; i < _samples; i++) 651 | { 652 | _vReal[i] = (double)_rawData[i]; 653 | _vImag[i] = 0.0; 654 | } 655 | 656 | /* FFT */ 657 | _FFT = arduinoFFT(_vReal, _vImag, _samples, _samplingFrequency); 658 | _FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD); 659 | _FFT.Compute(FFT_FORWARD); 660 | _FFT.ComplexToMagnitude(); 661 | // printf("fft done\n"); 662 | 663 | /* Draw raw wave */ 664 | color_num = 0; 665 | for (int i = 0; i < _samples; i++) 666 | { 667 | display->drawPixel(i, (_rawData[i] / 20), _color_list[color_num]); 668 | color_num++; 669 | if (color_num >= 7) 670 | color_num = 0; 671 | } 672 | 673 | double value = 0.0; 674 | for (int i = 4; i < (_samples / 4); i += 2) 675 | { 676 | /* Draw falling bricks */ 677 | value = (_vReal_old[i] + _vReal_old[i + 1]) / 2; 678 | display->fillRoundRect(8 * i - 28, 2 + value - 8, 8, 8, 2, _color_list[color_num]); 679 | 680 | /* Draw FFT */ 681 | value = (_vReal[i] + _vReal[i + 1]) / 2; 682 | value = value / 10; 683 | if (value > 135) 684 | value = 135; 685 | display->fillRoundRect(8 * i - 28, 2, 8, value, 2, _color_list[color_num]); 686 | 687 | color_num++; 688 | if (color_num >= 7) 689 | color_num = 0; 690 | } 691 | 692 | // double value = 0.0; 693 | // for (int i = 8; i < (_samples / 2); i += 2) { 694 | // /* Draw falling bricks */ 695 | // value = (_vReal_old[i] + _vReal_old[i+1]) / 2; 696 | // display->fillRoundRect(2 * i - 15, value - 2, 2, 2, 1, _color_list[color_num]); 697 | 698 | // /* Draw FFT */ 699 | // value = (_vReal[i] + _vReal[i+1]) / 2; 700 | // value = value / 10; 701 | // if (value > 135) 702 | // value = 135; 703 | // display->fillRoundRect(2 * i - 15, 0, 2, value, 1, _color_list[color_num]); 704 | 705 | // color_num++; 706 | // if (color_num >= 7) 707 | // color_num = 0; 708 | // } 709 | 710 | /* Update old buffer (falling bricks) */ 711 | for (int i = 0; i < _samples; i++) 712 | { 713 | /* Fall */ 714 | _vReal_old[i] -= 4; 715 | 716 | /* If higher hit */ 717 | value = _vReal[i] / 10; 718 | if (value > 135) 719 | value = 135; 720 | if (value > _vReal_old[i]) 721 | _vReal_old[i] = value; 722 | } 723 | 724 | // display->setCursor(0, 6); 725 | // display->fillRect(0, 0, 240, 25, Disbuff->color565(20, 20, 20)); 726 | // display->printf(" Mic test\n"); 727 | 728 | displayUpdate(); 729 | 730 | checkReboot(); 731 | if (checkNext()) 732 | { 733 | break; 734 | } 735 | } 736 | 737 | /* Free buffer */ 738 | printf("free mic buffer\n"); 739 | // delete [] mic_buffer; 740 | delete[] _rawData; 741 | delete[] _vReal; 742 | delete[] _vImag; 743 | delete[] _vReal_old; 744 | 745 | display->setRotation(0); 746 | 747 | printf("quit mic test\n"); 748 | } 749 | 750 | } 751 | -------------------------------------------------------------------------------- /src/test/test_rtc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_rtc.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | // #include "../../lib/rtc/cplus_RTC.h" 13 | 14 | namespace TEST 15 | { 16 | 17 | cplus_RTC _rtc; 18 | 19 | void TEST::DisplayRTC() 20 | { 21 | 22 | display->setFont(&fonts::Font0); 23 | 24 | Disbuff->fillRect(0, 0, 240, 135, Disbuff->color565(0, 0, 0)); 25 | // Displaybuff(); 26 | _rtc.GetBm8563Time(); 27 | RTC_TimeTypeDef time; 28 | _rtc.GetTime(&time); 29 | 30 | Disbuff->setTextSize(4); 31 | Disbuff->setCursor(6, 25); 32 | Disbuff->setTextColor(TFT_WHITE); 33 | 34 | while (1) 35 | { 36 | Disbuff->fillRect(0, 0, 240, 135, Disbuff->color565(0, 0, 0)); 37 | _rtc.GetTime(&time); 38 | Disbuff->setTextSize(4); 39 | Disbuff->setTextColor(TFT_WHITE); 40 | Disbuff->setCursor(25, 50); 41 | Disbuff->printf("%02d:%02d:%02d", time.Hours, time.Minutes, 42 | time.Seconds); 43 | Disbuff->fillRect(0, 0, 240, 25, Disbuff->color565(20, 20, 20)); 44 | Disbuff->setTextSize(2); 45 | Disbuff->drawString("BMP8563 RTC Time", 26, 5, 1); 46 | 47 | if (is_test_mode) 48 | { 49 | display->setFont(&fonts::efontCN_24); 50 | display->setTextColor(TFT_YELLOW, TFT_BLACK); 51 | display->setTextSize(1); 52 | display->setCursor(0, 80); 53 | display->printf("确保数值正常且变化"); 54 | display->setFont(&fonts::Font0); 55 | } 56 | 57 | Displaybuff(); 58 | 59 | // M5.update(); 60 | // checkAXPPress(); 61 | delay(100); 62 | 63 | checkReboot(); 64 | if (checkNext()) 65 | { 66 | break; 67 | } 68 | } 69 | } 70 | 71 | void TEST::rtc_init() 72 | { 73 | // rtc.begin(); 74 | _rtc.clearIRQ(); 75 | _rtc.disableIRQ(); 76 | } 77 | 78 | void TEST::rtc_test() 79 | { 80 | printf("rtc test\n"); 81 | DisplayRTC(); 82 | printf("quit rtc test\n"); 83 | } 84 | 85 | void TEST::rtc_wakeup_test() 86 | { 87 | display->fillScreen(TFT_BLACK); 88 | display->setCursor(0, 10); 89 | display->setFont(&fonts::efontCN_24); 90 | display->setTextColor(TFT_YELLOW); 91 | display->setTextSize(1); 92 | display->printf(" [RTC 唤醒测试]\n - 请移除电源 -\n\n 按下按键[关机]\n 数秒后将自动启动"); 93 | displayUpdate(); 94 | 95 | while (1) 96 | { 97 | if (btnA.pressed()) 98 | { 99 | _tone(5000, 50); 100 | break; 101 | } 102 | if (btnB.pressed()) 103 | { 104 | _tone(5500, 50); 105 | break; 106 | } 107 | if (btnPWR.pressed()) 108 | { 109 | _tone(3500, 50); 110 | break; 111 | } 112 | } 113 | 114 | // waitNext(); 115 | _rtc.clearIRQ(); 116 | _rtc.SetAlarmIRQ(4); 117 | display->fillScreen(TFT_BLACK); 118 | displayUpdate(); 119 | delay(500); 120 | // power_off(); 121 | 122 | digitalWrite(POWER_HOLD_PIN, 0); 123 | 124 | while (1) 125 | { 126 | printf("%d\n", btnPWR.read()); 127 | delay(50); 128 | } 129 | } 130 | 131 | // void TEST::gpio_test() 132 | // { 133 | // printf("hat test\n"); 134 | 135 | // display->fillScreen(TFT_BLACK); 136 | // display->setCursor(0, 5); 137 | // display->setFont(&fonts::efontCN_24); 138 | // display->setTextColor(TFT_YELLOW); 139 | // display->setTextSize(1); 140 | // display->printf("[HAT接口测试]\n\n请插上治具\n观察 [流水灯]\n和 [主机LED灯]"); 141 | // displayUpdate(); 142 | 143 | // // gpio_reset_pin(GPIO_NUM_19); 144 | // // pinMode(19, OUTPUT); 145 | // // while (1) { 146 | // // digitalWrite(19, 0); 147 | // // printf("19 %d\n", digitalRead(19)); 148 | // // delay(1000); 149 | // // digitalWrite(19, 1); 150 | // // printf("19 %d\n", digitalRead(19)); 151 | // // delay(1000); 152 | // // } 153 | 154 | // std::vector gpio_list = {GPIO_NUM_26, GPIO_NUM_25, GPIO_NUM_0, GPIO_NUM_19}; 155 | 156 | // /* Reset */ 157 | // for (auto i : gpio_list) { 158 | // gpio_reset_pin(i); 159 | // pinMode(i, OUTPUT); 160 | // } 161 | 162 | // uint32_t time_count = 0; 163 | // auto iter = gpio_list.begin(); 164 | // while (1) { 165 | 166 | // if ((millis() - time_count) > 600) { 167 | 168 | // printf("set %d %d\n", *iter, !digitalRead(*iter)); 169 | // digitalWrite(*iter, !digitalRead(*iter)); 170 | 171 | // iter++; 172 | // if (iter == gpio_list.end()) { 173 | // iter = gpio_list.begin(); 174 | // } 175 | 176 | // time_count = millis(); 177 | // } 178 | 179 | // checkReboot(); 180 | // if (checkNext()) { 181 | // break; 182 | // } 183 | 184 | // } 185 | 186 | // /* Reset */ 187 | // for (auto i : gpio_list) { 188 | // gpio_reset_pin(i); 189 | // } 190 | 191 | // display->setFont(&fonts::Font0); 192 | // display->setTextSize(1); 193 | 194 | // printf("quit hat test\n"); 195 | 196 | // } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /src/test/test_wifi.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file test_wifi.cpp 3 | * @author Forairaaaaa 4 | * @brief 5 | * @version 0.1 6 | * @date 2023-05-26 7 | * 8 | * @copyright Copyright (c) 2023 9 | * 10 | */ 11 | #include "test.h" 12 | 13 | namespace TEST 14 | { 15 | 16 | struct WiFiList_t 17 | { 18 | String ssid; 19 | int8_t rssi = 0; 20 | }; 21 | static WiFiList_t _wifi_list[13]; 22 | static bool _wifi_tested = false; 23 | 24 | void TEST::wifi_display_normal_mode() 25 | { 26 | printf("wifi scan\n"); 27 | 28 | display->fillScreen(TFT_BLACK); 29 | display->setFont(&fonts::Font0); 30 | display->setTextSize(2); 31 | display->setTextColor(TFT_WHITE); 32 | display->setCursor(0, 6); 33 | 34 | display->fillRect(0, 0, 240, 25, Disbuff->color565(20, 20, 20)); 35 | display->printf(" WiFi Scan\n"); 36 | 37 | display->setTextSize(1); 38 | display->setCursor(0, 28); 39 | display->printf(" Scanning...\n"); 40 | displayUpdate(); 41 | display->setCursor(0, 28); 42 | 43 | if (!_wifi_tested) 44 | { 45 | _wifi_tested = true; 46 | 47 | // Set WiFi to station mode and disconnect from an AP if it was previously connected. 48 | WiFi.mode(WIFI_STA); 49 | WiFi.disconnect(); 50 | delay(100); 51 | 52 | /* ------------------------------------- Scan test ------------------------------------- */ 53 | printf("Wifi scan start\n"); 54 | int n = WiFi.scanNetworks(); 55 | if (n == 0) 56 | { 57 | printf("scan error\n"); 58 | } 59 | else 60 | { 61 | for (int i = 0; i < 13; ++i) 62 | { 63 | // display->setTextColor((WiFi.RSSI(i) > -75) ? TFT_GREEN : TFT_RED, TFT_BLACK); 64 | // display->printf(" %s ", WiFi.SSID(i).c_str()); 65 | // display->printf(" %d\n", WiFi.RSSI(i)); 66 | // displayUpdate(); 67 | 68 | _wifi_list[i].rssi = WiFi.RSSI(i); 69 | _wifi_list[i].ssid = WiFi.SSID(i); 70 | 71 | switch (WiFi.encryptionType(i)) 72 | { 73 | case WIFI_AUTH_OPEN: 74 | _wifi_list[i].ssid += " (open)"; 75 | break; 76 | case WIFI_AUTH_WEP: 77 | _wifi_list[i].ssid += " (WEP)"; 78 | break; 79 | case WIFI_AUTH_WPA_PSK: 80 | _wifi_list[i].ssid += " (WPA)"; 81 | break; 82 | case WIFI_AUTH_WPA2_PSK: 83 | _wifi_list[i].ssid += " (WPA2)"; 84 | break; 85 | case WIFI_AUTH_WPA_WPA2_PSK: 86 | _wifi_list[i].ssid += " (WPA+WPA2)"; 87 | break; 88 | case WIFI_AUTH_WPA2_ENTERPRISE: 89 | _wifi_list[i].ssid += " (WPA2-EAP)"; 90 | break; 91 | case WIFI_AUTH_WPA3_PSK: 92 | _wifi_list[i].ssid += " (WPA3)"; 93 | break; 94 | case WIFI_AUTH_WPA2_WPA3_PSK: 95 | _wifi_list[i].ssid += " (WPA2+WPA3)"; 96 | break; 97 | case WIFI_AUTH_WAPI_PSK: 98 | _wifi_list[i].ssid += " (WAPI)"; 99 | break; 100 | default: 101 | break; 102 | } 103 | } 104 | } 105 | // Delete the scan result to free memory for code below. 106 | WiFi.scanDelete(); 107 | 108 | WiFi.disconnect(true); 109 | esp_wifi_disconnect(); 110 | esp_wifi_stop(); 111 | esp_wifi_deinit(); 112 | esp_wifi_clear_ap_list(); 113 | } 114 | 115 | /* Display result */ 116 | for (int i = 0; i < 13; ++i) 117 | { 118 | display->setTextColor((_wifi_list[i].rssi > -75) ? TFT_GREEN : TFT_RED, TFT_BLACK); 119 | display->printf(" %s ", _wifi_list[i].ssid.c_str()); 120 | display->printf(" %d\n", _wifi_list[i].rssi); 121 | displayUpdate(); 122 | 123 | // _wifi_list[i].rssi = WiFi.RSSI(i); 124 | // _wifi_list[i].ssid = WiFi.SSID(i); 125 | } 126 | 127 | waitNext(); 128 | } 129 | 130 | void TEST::wifi_test() 131 | { 132 | printf("wifi test\n"); 133 | 134 | if (!is_test_mode) 135 | { 136 | wifi_display_normal_mode(); 137 | } 138 | 139 | printf("quit wifi test\n"); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PlatformIO Test Runner and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PlatformIO Unit Testing: 11 | - https://docs.platformio.org/en/latest/advanced/unit-testing/index.html 12 | --------------------------------------------------------------------------------