├── lepton3 ├── Datasheet │ ├── lepthon3.0.pdf │ ├── Lepton3_LWIR_DS_Rev100_4-4-17.pdf │ └── Lepton_vs_Lepton3_Rev100_4-4-17.pdf └── Src │ ├── Lepton_Bot │ ├── 741915384200290613.bmp │ ├── espnow.h │ ├── lepton.h │ ├── color.c │ ├── Lepton_Bot.ino │ ├── lepton.cpp │ └── espnow.cpp │ └── Lepton_Remoter │ ├── 741915384200290613.bmp │ ├── espnow.h │ ├── color.c │ ├── Lepton_Remoter.ino │ └── espnow.cpp └── README.md /lepton3/Datasheet/lepthon3.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/Applications-Lepton3.0/master/lepton3/Datasheet/lepthon3.0.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Application-Lepton3.0 2 | this repository contains code and libraries developed for a FLIR Lepton 3.0 Thermal imaging camera module. 3 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/741915384200290613.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/Applications-Lepton3.0/master/lepton3/Src/Lepton_Bot/741915384200290613.bmp -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Remoter/741915384200290613.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/Applications-Lepton3.0/master/lepton3/Src/Lepton_Remoter/741915384200290613.bmp -------------------------------------------------------------------------------- /lepton3/Datasheet/Lepton3_LWIR_DS_Rev100_4-4-17.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/Applications-Lepton3.0/master/lepton3/Datasheet/Lepton3_LWIR_DS_Rev100_4-4-17.pdf -------------------------------------------------------------------------------- /lepton3/Datasheet/Lepton_vs_Lepton3_Rev100_4-4-17.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m5stack/Applications-Lepton3.0/master/lepton3/Datasheet/Lepton_vs_Lepton3_Rev100_4-4-17.pdf -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/espnow.h: -------------------------------------------------------------------------------- 1 | #ifndef __ESPNOW_H__ 2 | #define __ESPNOW_H__ 3 | #define bot 1 4 | #include 5 | #include 6 | #include "Arduino.h" 7 | #define CHANNEL 1 8 | #define PRINTSCANRESULTS 0 9 | 10 | 11 | class Espnow { 12 | 13 | 14 | public: 15 | Espnow(); 16 | void BotInit(void); 17 | void RemoteInit(void); 18 | 19 | void OnRemotSent(const uint8_t *mac_addr, esp_now_send_status_t status); 20 | void OnRemotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len); 21 | 22 | void OnBotSent(const uint8_t *mac_addr, esp_now_send_status_t status); 23 | void OnBotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len); 24 | 25 | void RemoteConnectUpdate(void); 26 | void BotConnectUpdate(void); 27 | 28 | //uint8_t peer_addr[6]= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 29 | public: 30 | uint8_t peer_addr[6];//= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 31 | esp_now_peer_info_t slave; 32 | private: 33 | 34 | void ConfigDeviceAP(void); 35 | void InitEspNow(void); 36 | void ScanForSlave(void); 37 | void manageSlave(void); 38 | void sendData(void); 39 | 40 | private: 41 | Preferences preferences; 42 | uint8_t sta_addr[6]; 43 | //esp_now_peer_info_t slave; 44 | esp_now_peer_info_t slaves[20] = {}; 45 | int SlaveCnt = 0; 46 | bool connectflag = false; 47 | uint8_t connect_addr[20][6]; 48 | int connect_num; 49 | //uint8_t peer_addr[6]= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 50 | }; 51 | #endif 52 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Remoter/espnow.h: -------------------------------------------------------------------------------- 1 | #ifndef __ESPNOW_H__ 2 | #define __ESPNOW_H__ 3 | #define bot 0 4 | #include 5 | #include 6 | #include "Arduino.h" 7 | #define CHANNEL 1 8 | #define PRINTSCANRESULTS 0 9 | 10 | 11 | class Espnow { 12 | 13 | 14 | public: 15 | Espnow(); 16 | void BotInit(void); 17 | void RemoteInit(void); 18 | 19 | void OnRemotSent(const uint8_t *mac_addr, esp_now_send_status_t status); 20 | void OnRemotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len); 21 | 22 | void OnBotSent(const uint8_t *mac_addr, esp_now_send_status_t status); 23 | void OnBotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len); 24 | 25 | void RemoteConnectUpdate(void); 26 | void BotConnectUpdate(void); 27 | 28 | //uint8_t peer_addr[6]= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 29 | public: 30 | uint8_t peer_addr[6];//= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 31 | esp_now_peer_info_t slave; 32 | private: 33 | 34 | void ConfigDeviceAP(void); 35 | void InitEspNow(void); 36 | void ScanForSlave(void); 37 | void manageSlave(void); 38 | void sendData(void); 39 | 40 | private: 41 | Preferences preferences; 42 | uint8_t sta_addr[6]; 43 | //esp_now_peer_info_t slave; 44 | esp_now_peer_info_t slaves[20] = {}; 45 | int SlaveCnt = 0; 46 | bool connectflag = false; 47 | uint8_t connect_addr[20][6]; 48 | int connect_num; 49 | //uint8_t peer_addr[6]= {0xB4, 0xE6, 0x2D, 0x8B, 0x7D, 0x42}; 50 | }; 51 | #endif 52 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Remoter/color.c: -------------------------------------------------------------------------------- 1 | const unsigned short camColors[] = {0x480F, 2 | 0x400F, 0x400F, 0x400F, 0x4010, 0x3810, 0x3810, 0x3810, 0x3810, 0x3010, 0x3010, 3 | 0x3010, 0x2810, 0x2810, 0x2810, 0x2810, 0x2010, 0x2010, 0x2010, 0x1810, 0x1810, 4 | 0x1811, 0x1811, 0x1011, 0x1011, 0x1011, 0x0811, 0x0811, 0x0811, 0x0011, 0x0011, 5 | 0x0011, 0x0011, 0x0011, 0x0031, 0x0031, 0x0051, 0x0072, 0x0072, 0x0092, 0x00B2, 6 | 0x00B2, 0x00D2, 0x00F2, 0x00F2, 0x0112, 0x0132, 0x0152, 0x0152, 0x0172, 0x0192, 7 | 0x0192, 0x01B2, 0x01D2, 0x01F3, 0x01F3, 0x0213, 0x0233, 0x0253, 0x0253, 0x0273, 8 | 0x0293, 0x02B3, 0x02D3, 0x02D3, 0x02F3, 0x0313, 0x0333, 0x0333, 0x0353, 0x0373, 9 | 0x0394, 0x03B4, 0x03D4, 0x03D4, 0x03F4, 0x0414, 0x0434, 0x0454, 0x0474, 0x0474, 10 | 0x0494, 0x04B4, 0x04D4, 0x04F4, 0x0514, 0x0534, 0x0534, 0x0554, 0x0554, 0x0574, 11 | 0x0574, 0x0573, 0x0573, 0x0573, 0x0572, 0x0572, 0x0572, 0x0571, 0x0591, 0x0591, 12 | 0x0590, 0x0590, 0x058F, 0x058F, 0x058F, 0x058E, 0x05AE, 0x05AE, 0x05AD, 0x05AD, 13 | 0x05AD, 0x05AC, 0x05AC, 0x05AB, 0x05CB, 0x05CB, 0x05CA, 0x05CA, 0x05CA, 0x05C9, 14 | 0x05C9, 0x05C8, 0x05E8, 0x05E8, 0x05E7, 0x05E7, 0x05E6, 0x05E6, 0x05E6, 0x05E5, 15 | 0x05E5, 0x0604, 0x0604, 0x0604, 0x0603, 0x0603, 0x0602, 0x0602, 0x0601, 0x0621, 16 | 0x0621, 0x0620, 0x0620, 0x0620, 0x0620, 0x0E20, 0x0E20, 0x0E40, 0x1640, 0x1640, 17 | 0x1E40, 0x1E40, 0x2640, 0x2640, 0x2E40, 0x2E60, 0x3660, 0x3660, 0x3E60, 0x3E60, 18 | 0x3E60, 0x4660, 0x4660, 0x4E60, 0x4E80, 0x5680, 0x5680, 0x5E80, 0x5E80, 0x6680, 19 | 0x6680, 0x6E80, 0x6EA0, 0x76A0, 0x76A0, 0x7EA0, 0x7EA0, 0x86A0, 0x86A0, 0x8EA0, 20 | 0x8EC0, 0x96C0, 0x96C0, 0x9EC0, 0x9EC0, 0xA6C0, 0xAEC0, 0xAEC0, 0xB6E0, 0xB6E0, 21 | 0xBEE0, 0xBEE0, 0xC6E0, 0xC6E0, 0xCEE0, 0xCEE0, 0xD6E0, 0xD700, 0xDF00, 0xDEE0, 22 | 0xDEC0, 0xDEA0, 0xDE80, 0xDE80, 0xE660, 0xE640, 0xE620, 0xE600, 0xE5E0, 0xE5C0, 23 | 0xE5A0, 0xE580, 0xE560, 0xE540, 0xE520, 0xE500, 0xE4E0, 0xE4C0, 0xE4A0, 0xE480, 24 | 0xE460, 0xEC40, 0xEC20, 0xEC00, 0xEBE0, 0xEBC0, 0xEBA0, 0xEB80, 0xEB60, 0xEB40, 25 | 0xEB20, 0xEB00, 0xEAE0, 0xEAC0, 0xEAA0, 0xEA80, 0xEA60, 0xEA40, 0xF220, 0xF200, 26 | 0xF1E0, 0xF1C0, 0xF1A0, 0xF180, 0xF160, 0xF140, 0xF100, 0xF0E0, 0xF0C0, 0xF0A0, 27 | 0xF080, 0xF060, 0xF040, 0xF020, 0xF800, 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/lepton.h: -------------------------------------------------------------------------------- 1 | #ifndef Lepton_h 2 | #define Lepton_h 3 | 4 | #include "Arduino.h" 5 | 6 | class Lepton { 7 | public: 8 | // Registers for use with readRegister and writeRegister. 9 | static const uint16_t REG_POWER = 0; 10 | static const uint16_t REG_STATUS = 2; 11 | static const uint16_t REG_COMMAND_ID = 4; 12 | static const uint16_t REG_DATA_LEN = 6; 13 | static const uint16_t REG_DATA_BASE = 8; 14 | 15 | // Automatic Gain Control commands 16 | static const uint16_t CMD_AGC_ENABLE = 0x0100; 17 | static const uint16_t CMD_AGC_ROI = 0x0108; 18 | static const uint16_t CMD_AGC_HISTOGRAM_STATISTICS = 0x010c; 19 | static const uint16_t CMD_AGC_HEQ_DAMPING_FACTOR = 0x0124; 20 | static const uint16_t CMD_AGC_HEQ_CLIP_LIMIT_HIGH = 0x012c; 21 | static const uint16_t CMD_AGC_HEQ_CLIP_LIMIT_LOW = 0x0130; 22 | static const uint16_t CMD_AGC_HEQ_EMPTY_COUNT = 0x013c; 23 | static const uint16_t CMD_AGC_HEQ_SCALE_FACTOR = 0x0144; 24 | static const uint16_t CMD_AGC_HEQ_CALC_ENABLE_STATE = 0x0148; 25 | 26 | // System commands 27 | static const uint16_t CMD_SYS_PING = 0x0200; 28 | static const uint16_t CMD_SYS_STATUS = 0x0204; 29 | static const uint16_t CMD_SYS_FLIR_SERIAL_NUMBER = 0x0208; 30 | static const uint16_t CMD_SYS_CAMERA_UPTIME = 0x020C; 31 | static const uint16_t CMD_SYS_AUX_TEMPERATURE_KELVIN = 0x0210; 32 | static const uint16_t CMD_SYS_FPA_TEMPERATURE_KELVIN = 0x0214; 33 | static const uint16_t CMD_SYS_TELEMETRY_ENABLE = 0x0218; 34 | static const uint16_t CMD_SYS_TELEMETRY_LOCATION = 0x021c; 35 | static const uint16_t CMD_SYS_FRAMES_TO_AVERAGE = 0x0224; 36 | static const uint16_t CMD_SYS_CUST_SERIAL_NUMBER = 0x0228; 37 | static const uint16_t CMD_SYS_SCENE_STATISTICS = 0x022c; 38 | static const uint16_t CMD_SYS_SCENE_ROI = 0x0230; 39 | static const uint16_t CMD_SYS_THERMAL_SHUTDOWN_COUNT = 0x0234; 40 | static const uint16_t CMD_SYS_SHUTTER_POSITION = 0x0238; 41 | static const uint16_t CMD_SYS_FFC_SHUTTER_MODE = 0x023c; 42 | static const uint16_t CMD_SYS_FFC_NORMALIZATION = 0x0240; 43 | static const uint16_t CMD_SYS_FFC_STATUS = 0x0244; 44 | 45 | // Video commands 46 | static const uint16_t CMD_VID_USER_LUT = 0x0308; 47 | static const uint16_t CMD_VID_FOCUS_CALC_ENABLE = 0x030c; 48 | static const uint16_t CMD_VID_FOCUS_ROI = 0x0310; 49 | static const uint16_t CMD_VID_FOCUS_METRIC_THRESHOLD = 0x0314; 50 | static const uint16_t CMD_VID_FOCUS_METRIC = 0x0318; 51 | static const uint16_t CMD_VID_FREEZE_ENABLE = 0x0324; 52 | 53 | 54 | 55 | // 56 | static const uint16_t CMD_OEM_SYNC_SET = 0x4854; 57 | //static const uint16_t CMD_OEM_SYNC_GET = 0x4864; 58 | 59 | static const uint16_t STATUS_BIT_BUSY = 1; 60 | static const uint16_t STATUS_BIT_BOOT_MODE = 2; 61 | static const uint16_t STATUS_BIT_BOOT_STATUS = 4; 62 | 63 | // Create a new Lepton instance 64 | Lepton(int sdaPin, int sclPin, int ssPin); 65 | 66 | // Start Lepton access 67 | void begin(); 68 | 69 | // Read a (16-bit) register 70 | uint16_t readRegister(uint16_t reg); 71 | 72 | // Write a (16-bit) register 73 | void writeRegister(uint16_t reg, uint16_t value); 74 | 75 | // Do a get command, and get the resulting data 76 | uint16_t doGetCommand(uint16_t commandIdBase, uint16_t* data); 77 | 78 | // Do a set command, using the provided data 79 | void doSetCommand(uint16_t commandIdBase, uint16_t* data, uint16_t dataLen); 80 | 81 | // Do a run command, using the provided data and returning the result in the same buffer 82 | uint16_t doRunCommand(uint16_t commandIdBase, uint16_t* data, uint16_t dataLen); 83 | void end(); 84 | // (Re-)synchronize the frame stream 85 | uint16_t syncFrame(); 86 | void getRawValues(); 87 | // Read a frame into a 80 * 60 uint16_t buffer 88 | int readFrame(uint16_t* data); 89 | //int read160X120Frame(uint16_t* data); 90 | int read_160x120_Frame(uint16_t* data); 91 | void reset(); 92 | // Read completely raw frame data - for debugging purposes 93 | void readFrameRaw(uint16_t* data); 94 | uint16_t wait_160X120_NextFrame(); 95 | private: 96 | // Device ID on the I2C interface 97 | static const uint8_t DEVICE_ID = 0x2A; 98 | 99 | // Command types 100 | static const uint16_t TYPE_GET = 0; 101 | static const uint16_t TYPE_SET = 1; 102 | static const uint16_t TYPE_RUN = 2; 103 | 104 | // Start I2C transmission relating to a specific register 105 | void startTransmission(uint16_t reg); 106 | 107 | // Transmit a word over I2C 108 | void transmitWord(uint16_t value); 109 | 110 | // End I2C transmission 111 | void endTransmission(); 112 | 113 | // Read a word over I2C 114 | uint16_t readWord(); 115 | 116 | // Set the current register over I2C 117 | void setRegister(uint16_t reg); 118 | 119 | // Wait for the camera to become idle, e.g. after performing a command 120 | void waitIdle(); 121 | 122 | // Read data from a buffer 123 | uint16_t readData(uint16_t* data); 124 | 125 | // Write data to a buffer 126 | void writeData(uint16_t* data, uint16_t dataLen); 127 | 128 | // Read a word of frame data over SPI 129 | uint16_t readFrameWord(); 130 | 131 | // Wait for the next frame over SPI 132 | uint16_t waitNextFrame(); 133 | //uint16_t wait_160X120_NextFrame(); 134 | 135 | // Dump a buffer as hex to serial - for debugging purposes 136 | void dumpHex(uint16_t *data, int dataLen); 137 | bool savePackage(byte line, byte segment); 138 | int getPackage(byte line, byte seg); 139 | // SDA, SCL and SPI CS pins 140 | int _sdaPin; 141 | int _sclPin; 142 | int _ssPin; 143 | }; 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/color.c: -------------------------------------------------------------------------------- 1 | /* 2 | const unsigned char camColors[] = { 3 | 0X04,0XDF,0X04,0XDF,0X04,0XDF,0X04,0XFF,0X05,0X1F,0X05,0X1F,0X05,0X3F,0X05,0X3F, 4 | 0X05,0X5E,0X05,0X7E,0X05,0X9E,0X05,0X9E,0X05,0XBE,0X05,0XDE,0X05,0XDE,0X05,0XFD, 5 | 0X06,0X1D,0X06,0X1D,0X06,0X3D,0X06,0X5D,0X06,0X5C,0X06,0X5C,0X06,0X7C,0X06,0X9C, 6 | 0X06,0XBC,0X06,0XBC,0X06,0XDB,0X06,0XFB,0X06,0XFB,0X07,0X1B,0X07,0X3B,0X07,0X3B, 7 | 0X07,0X5A,0X07,0X7A,0X07,0X7A,0X07,0X7A,0X07,0XBA,0X07,0XBA,0X07,0XD9,0X07,0XF9, 8 | 0X07,0XF9,0X07,0XF8,0X07,0XF8,0X07,0XF8,0X07,0XF8,0X07,0XF7,0X07,0XF7,0X07,0XF6, 9 | 0X07,0XF5,0X07,0XF5,0X0F,0XF5,0X0F,0XF5,0X0F,0XF4,0X0F,0XF4,0X0F,0XF3,0X0F,0XF3, 10 | 0X0F,0XF3,0X0F,0XF2,0X0F,0XF2,0X0F,0XF1,0X17,0XF1,0X17,0XF1,0X17,0XF0,0X17,0XF0, 11 | 0X17,0XEF,0X17,0XEF,0X17,0XEF,0X17,0XEE,0X17,0XEE,0X1F,0XED,0X1F,0XED,0X1F,0XED, 12 | 0X1F,0XEC,0X1F,0XEC,0X1F,0XEB,0X1F,0XEB,0X1F,0XEA,0X1F,0XEA,0X1F,0XEA,0X1F,0XE9, 13 | 0X27,0XE9,0X27,0XE9,0X27,0XE8,0X27,0XE7,0X27,0XE7,0X27,0XE7,0X27,0XE7,0X27,0XE6, 14 | 0X27,0XE6,0X2F,0XE5,0X2F,0XE4,0X2F,0XE4,0X2F,0XE4,0X2F,0XE4,0X2F,0XE3,0X2F,0XE3, 15 | 0X2F,0XE2,0X2F,0XE2,0X2F,0XE2,0X2F,0XE1,0X37,0XE1,0X37,0XE0,0X37,0XE0,0X37,0XE0, 16 | 0X3F,0XE0,0X3F,0XE0,0X3F,0XE0,0X47,0XE0,0X47,0XE0,0X4F,0XE0,0X57,0XE0,0X57,0XE0, 17 | 0X57,0XE0,0X5F,0XE0,0X5F,0XE0,0X67,0XE0,0X67,0XE0,0X6F,0XE0,0X6F,0XE0,0X6F,0XE0, 18 | 0X77,0XE0,0X77,0XE0,0X7F,0XE0,0X87,0XE0,0X87,0XE0,0X8F,0XE0,0X8F,0XE0,0X8F,0XE0, 19 | 0X97,0XE0,0X97,0XE0,0X9F,0XE0,0XA7,0XE0,0XA7,0XE0,0XA7,0XE0,0XAF,0XE0,0XAF,0XE0, 20 | 0XAF,0XE0,0XB7,0XE0,0XBF,0XE0,0XBF,0XE0,0XBF,0XE0,0XC7,0XE0,0XC7,0XE0,0XCF,0XE0, 21 | 0XD7,0XE0,0XD7,0XE0,0XDF,0XE0,0XDF,0XE0,0XDF,0XE0,0XE7,0XE0,0XEF,0XE0,0XEF,0XE0, 22 | 0XEF,0XE0,0XEF,0XE0,0XF7,0XE0,0XF7,0XE0,0XFF,0XE0,0XFF,0XE0,0XFF,0XC0,0XFF,0XA0, 23 | 0XFF,0XA0,0XFF,0XA0,0XFF,0X80,0XFF,0X60,0XFF,0X40,0XFF,0X20,0XFF,0X00,0XFF,0X00, 24 | 0XFF,0X00,0XFE,0XE0,0XFE,0XC0,0XFE,0XA0,0XFE,0X80,0XFE,0X60,0XFE,0X60,0XFE,0X60, 25 | 0XFE,0X40,0XFE,0X20,0XFE,0X00,0XFD,0XE0,0XFD,0XC0,0XFD,0XC0,0XFD,0XC0,0XFD,0XA0, 26 | 0XFD,0X80,0XFD,0X60,0XFD,0X40,0XFD,0X40,0XFD,0X40,0XFD,0X20,0XFD,0X00,0XFC,0XE0, 27 | 0XFC,0XC0,0XFC,0XA0,0XFC,0XA0,0XFC,0XA0,0XFC,0X80,0XFC,0X60,0XFC,0X40,0XFC,0X20, 28 | 0XFC,0X00,0XFC,0X00,0XFC,0X00,0XFB,0XE0,0XFB,0XC0,0XFB,0XA0,0XFB,0X80,0XFB,0X60, 29 | 0XFB,0X60,0XFB,0X60,0XFB,0X40,0XFB,0X20,0XFB,0X00,0XFB,0X00,0XFA,0XE0,0XFA,0XE0, 30 | 0XFA,0XE0,0XFA,0XE0,0XFA,0XC0,0XFA,0XA1,0XFA,0XA1,0XFA,0X81,0XFA,0X81,0XFA,0X81, 31 | 0XFA,0X61,0XFA,0X61,0XFA,0X41,0XFA,0X41,0XFA,0X22,0XFA,0X22,0XFA,0X22,0XFA,0X02, 32 | 0XF9,0XE2,0XF9,0XE2,0XF9,0XE2,0XF9,0XC2,0XF9,0XC2,0XF9,0XC2,0XF9,0XA3,0XF9,0X83, 33 | 0XF9,0X83,0XF9,0X63,0XF9,0X63,0XF9,0X43,0XF9,0X43,0XF9,0X43,0XF9,0X24,0XF9,0X24, 34 | 0XF9,0X04,0XF9,0X04,0XF8,0XE4,0XF8,0XE4,0XF8,0XE4,0XF8,0XC4,0XF8,0XC4,0XF8,0XA5, 35 | 0XF8,0XA5,0XF8,0X85,0XF8,0X85,0XF8,0X85,0XF8,0X65,0XF8,0X45,0XF8,0X45,0XF8,0X45, 36 | 0XF8,0X26,0XF8,0X26,0XF8,0X06,0XF8,0X06,0XF8,0X06,0XF8,0X07,0XF8,0X07,0XF8,0X07, 37 | 0XF8,0X07,0XF8,0X08,0XF8,0X09,0XF8,0X09,0XF8,0X09,0XF8,0X0A,0XF8,0X0A,0XF8,0X0A, 38 | 0XF8,0X0B,0XF8,0X0B,0XF8,0X0C,0XF8,0X0C,0XF8,0X0C,0XF8,0X0D,0XF8,0X0D,0XF8,0X0E, 39 | 0XF8,0X0E,0XF8,0X0E,0XF8,0X0F,0XF8,0X0F,0XF8,0X10,0XF8,0X10,0XF8,0X10,0XF8,0X11, 40 | 0XF8,0X11,0XF8,0X11,0XF8,0X13,0X00,0X00,}; 41 | */ 42 | 43 | const unsigned short camColors[] = {0x480F, 44 | 0x400F, 0x400F, 0x400F, 0x4010, 0x3810, 0x3810, 0x3810, 0x3810, 0x3010, 0x3010, 45 | 0x3010, 0x2810, 0x2810, 0x2810, 0x2810, 0x2010, 0x2010, 0x2010, 0x1810, 0x1810, 46 | 0x1811, 0x1811, 0x1011, 0x1011, 0x1011, 0x0811, 0x0811, 0x0811, 0x0011, 0x0011, 47 | 0x0011, 0x0011, 0x0011, 0x0031, 0x0031, 0x0051, 0x0072, 0x0072, 0x0092, 0x00B2, 48 | 0x00B2, 0x00D2, 0x00F2, 0x00F2, 0x0112, 0x0132, 0x0152, 0x0152, 0x0172, 0x0192, 49 | 0x0192, 0x01B2, 0x01D2, 0x01F3, 0x01F3, 0x0213, 0x0233, 0x0253, 0x0253, 0x0273, 50 | 0x0293, 0x02B3, 0x02D3, 0x02D3, 0x02F3, 0x0313, 0x0333, 0x0333, 0x0353, 0x0373, 51 | 0x0394, 0x03B4, 0x03D4, 0x03D4, 0x03F4, 0x0414, 0x0434, 0x0454, 0x0474, 0x0474, 52 | 0x0494, 0x04B4, 0x04D4, 0x04F4, 0x0514, 0x0534, 0x0534, 0x0554, 0x0554, 0x0574, 53 | 0x0574, 0x0573, 0x0573, 0x0573, 0x0572, 0x0572, 0x0572, 0x0571, 0x0591, 0x0591, 54 | 0x0590, 0x0590, 0x058F, 0x058F, 0x058F, 0x058E, 0x05AE, 0x05AE, 0x05AD, 0x05AD, 55 | 0x05AD, 0x05AC, 0x05AC, 0x05AB, 0x05CB, 0x05CB, 0x05CA, 0x05CA, 0x05CA, 0x05C9, 56 | 0x05C9, 0x05C8, 0x05E8, 0x05E8, 0x05E7, 0x05E7, 0x05E6, 0x05E6, 0x05E6, 0x05E5, 57 | 0x05E5, 0x0604, 0x0604, 0x0604, 0x0603, 0x0603, 0x0602, 0x0602, 0x0601, 0x0621, 58 | 0x0621, 0x0620, 0x0620, 0x0620, 0x0620, 0x0E20, 0x0E20, 0x0E40, 0x1640, 0x1640, 59 | 0x1E40, 0x1E40, 0x2640, 0x2640, 0x2E40, 0x2E60, 0x3660, 0x3660, 0x3E60, 0x3E60, 60 | 0x3E60, 0x4660, 0x4660, 0x4E60, 0x4E80, 0x5680, 0x5680, 0x5E80, 0x5E80, 0x6680, 61 | 0x6680, 0x6E80, 0x6EA0, 0x76A0, 0x76A0, 0x7EA0, 0x7EA0, 0x86A0, 0x86A0, 0x8EA0, 62 | 0x8EC0, 0x96C0, 0x96C0, 0x9EC0, 0x9EC0, 0xA6C0, 0xAEC0, 0xAEC0, 0xB6E0, 0xB6E0, 63 | 0xBEE0, 0xBEE0, 0xC6E0, 0xC6E0, 0xCEE0, 0xCEE0, 0xD6E0, 0xD700, 0xDF00, 0xDEE0, 64 | 0xDEC0, 0xDEA0, 0xDE80, 0xDE80, 0xE660, 0xE640, 0xE620, 0xE600, 0xE5E0, 0xE5C0, 65 | 0xE5A0, 0xE580, 0xE560, 0xE540, 0xE520, 0xE500, 0xE4E0, 0xE4C0, 0xE4A0, 0xE480, 66 | 0xE460, 0xEC40, 0xEC20, 0xEC00, 0xEBE0, 0xEBC0, 0xEBA0, 0xEB80, 0xEB60, 0xEB40, 67 | 0xEB20, 0xEB00, 0xEAE0, 0xEAC0, 0xEAA0, 0xEA80, 0xEA60, 0xEA40, 0xF220, 0xF200, 68 | 0xF1E0, 0xF1C0, 0xF1A0, 0xF180, 0xF160, 0xF140, 0xF100, 0xF0E0, 0xF0C0, 0xF0A0, 69 | 0xF080, 0xF060, 0xF040, 0xF020, 0xF800, 70 | }; 71 | 72 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Remoter/Lepton_Remoter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include"espnow.h" 3 | #define expd 0 4 | Espnow espnow; 5 | char Title[] = {0x08,0x40,0x08,0x40,0x08,0x48,0x7F, 6 | 0xFC,0x08,0x48,0x0A,0x48,0x1C,0xC8, 7 | 0x68,0x48,0x08,0xA8,0x08,0x8A,0x29, 8 | 0x0A,0x12,0x04,0x00,0x00,0x48,0x88, 9 | 0x44,0x46,0x84,0x42, 10 | 0x00,0x80,0x00,0xA0,0x00,0x90,0x3F, 11 | 0xFC,0x20,0x80,0x20,0x80,0x20,0x84, 12 | 0x3E,0x44,0x22,0x48,0x22,0x48,0x22, 13 | 0x30,0x2A,0x20,0x24,0x62,0x40,0x92, 14 | 0x81,0x0A,0x00,0x06, 15 | 0x09,0x00,0x09,0xF0,0x0A,0x24,0x17, 16 | 0xFE,0x1C,0x44,0x37,0xFC,0x50,0x80, 17 | 0x91,0x44,0x16,0x68,0x10,0xB0,0x17, 18 | 0x30,0x10,0x68,0x11,0xA6,0x16,0x20, 19 | 0x10,0xA0,0x10,0x40, 20 | 0x08,0x00,0x08,0x80,0x08,0x64,0x12, 21 | 0x24,0x12,0x04,0x32,0x08,0x51,0x08, 22 | 0x91,0x10,0x10,0x90,0x10,0xA0,0x10, 23 | 0x40,0x10,0xA0,0x11,0x10,0x12,0x08, 24 | 0x14,0x0E,0x18,0x04}; 25 | uint16_t frameData[160 * 120]; 26 | uint16_t expframeData[320 * 9]; 27 | uint8_t TempData[160 * 120]; 28 | uint16_t num; 29 | float fpa_temp; 30 | float max_temp; 31 | float min_temp; 32 | extern const unsigned short camColors[]; 33 | 34 | void display_ch(int16_t x0, int16_t y0, 35 | int16_t w, int16_t h){ 36 | uint16_t posX = x0, posY = y0; 37 | for(int count = 0; count < 4;count++){ 38 | int k,j,i; 39 | byte flag; 40 | for(k=0; k<16; k++){ 41 | for(j=0; j<2; j++){ 42 | for(i=0; i<8; i++){ 43 | flag = Title[count * 32 +k*2+j]&(0x80 >> i); 44 | if(flag) 45 | M5.Lcd.drawPixel(posX + 8 * j + i, posY + k, WHITE); 46 | else 47 | M5.Lcd.drawPixel(posX + 8 * j + i, posY + k, BLACK); 48 | } 49 | } 50 | M5.Lcd.println(); 51 | } 52 | posX += 20; 53 | } 54 | } 55 | // callback when data is sent from Master to Slave 56 | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) 57 | { 58 | 59 | } 60 | 61 | void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) 62 | { 63 | if(bot) 64 | espnow.OnBotRecv(mac_addr,data,data_len); 65 | else 66 | espnow.OnRemotRecv(mac_addr,data,data_len); 67 | 68 | 69 | if(data_len == 10){ 70 | num = (data[0] << 8 | data[1]); 71 | fpa_temp = (float)((data[2] << 8 | data[3])) / 10.0; 72 | max_temp = (float)((data[4] << 8 | data[5])) / 10.0; 73 | min_temp = (float)((data[6] << 8 | data[7])) / 10.0; 74 | } 75 | 76 | if(data_len == 241){ 77 | for(int i = 1; i < 241; i++) 78 | TempData[data[0] * 240 + i - 1] = data[i]; 79 | } 80 | } 81 | 82 | void infodisplay(void) { 83 | 84 | M5.Lcd.setCursor(58, 0, 4); 85 | //M5.Lcd.print("THERMOGRAPHY"); 86 | display_ch(120, 3,122, 24); 87 | 88 | M5.Lcd.fillRect(0, 206, 320, 4, TFT_WHITE); 89 | M5.Lcd.setTextColor(TFT_WHITE); 90 | M5.Lcd.fillRect(0, 22, 320, 4, TFT_WHITE); 91 | M5.Lcd.setTextColor(TFT_WHITE); 92 | } 93 | float old_fpa_temp,old_max_temp,old_min_temp; 94 | void CursorLocation(int num, float fpa_temp,float max_temp,float min_temp){ 95 | 96 | if(fpa_temp >= 120) fpa_temp = old_fpa_temp; 97 | if(max_temp >= 120) max_temp = old_max_temp; 98 | if(min_temp >= 120) min_temp = old_min_temp; 99 | old_fpa_temp = fpa_temp; 100 | old_max_temp = max_temp; 101 | old_min_temp = min_temp; 102 | #if expd 103 | int centre_x = (int)(M5.Lcd.width()-160)/2 + num % 160; 104 | int centre_y = (int)(M5.Lcd.height()-120)/2 + num / 160; 105 | 106 | if(centre_x <= (int)(M5.Lcd.width()-160)/2+10) 107 | centre_x = (int)(M5.Lcd.width()-160)/2+10; 108 | else if(centre_x >= (int)(M5.Lcd.width()-160)/2 + 160 - 12) 109 | centre_x = (int)(M5.Lcd.width()-160)/2 + 160 - 12; 110 | 111 | 112 | if(centre_y <= (int)(M5.Lcd.height()-120)/2+10) 113 | centre_y = (int)(M5.Lcd.height()-120)/2+10; 114 | else if(centre_y >= (int)(M5.Lcd.height()-120)/2 + 120 - 11) 115 | centre_y = (int)(M5.Lcd.height()-120)/2 + 120 - 11; 116 | #else 117 | int centre_x = num % 160; 118 | int centre_y = num / 160; 119 | centre_x = centre_x * 2; 120 | centre_y = 27 + centre_y * 3/2; 121 | 122 | if(centre_y <= (int)(27+10)) 123 | centre_y = 27+10; 124 | else if(centre_y >= (int)(207 - 11)) 125 | centre_y = 207 - 11; 126 | #endif 127 | M5.Lcd.drawCircle(centre_x, centre_y, 6, TFT_WHITE); // update center spot icon 128 | M5.Lcd.drawLine(centre_x, centre_y-10, centre_x, centre_y+10, TFT_WHITE); // vertical line 129 | M5.Lcd.drawLine(centre_x-10, centre_y, centre_x+10, centre_y, TFT_WHITE); // horizontal lin 130 | 131 | if(centre_x >= ((int)(M5.Lcd.width()-160)/2 + 160 - 12 - 45)) 132 | M5.Lcd.setCursor(centre_x-55, centre_y-10,2); 133 | else 134 | M5.Lcd.setCursor(centre_x+20, centre_y-10,2); 135 | M5.Lcd.print(max_temp, 1); 136 | M5.Lcd.printf("C" ,1); 137 | #if 0 138 | M5.Lcd.fillRect(270, 160, 60, 15, TFT_BLACK); //Clear fps text area 139 | M5.Lcd.setTextSize(1); 140 | M5.Lcd.setCursor(250, 160); 141 | M5.Lcd.print("aux:" + String(max_temp)+"C"); 142 | #endif 143 | //M5.Lcd.fillRect(270, 180, 60, 15, TFT_BLACK); //Clear fps text area 144 | M5.Lcd.setTextSize(1); 145 | M5.Lcd.setCursor(250, 190); 146 | M5.Lcd.print("fpa:" + String(max_temp)+"C"); 147 | int icolor = 0; 148 | for (int icol = 0; icol <= 360; icol++){ 149 | //彩色条 150 | //M5.Lcd.drawRect(36, 208, icol, 284 , camColors[icolor]); 151 | M5.Lcd.drawRect(0, 210, icol, 284 , camColors[icolor]); 152 | if(icolor <= 250) 153 | icolor++; 154 | } 155 | M5.Lcd.setCursor(30, 215,4); 156 | M5.Lcd.printf("min = %0.1fC max = %0.1fC",min_temp,max_temp); 157 | } 158 | void setup() { 159 | // put your setup code here, to run once: 160 | delay(100); 161 | m5.begin(); 162 | espnow.RemoteInit(); 163 | esp_now_register_recv_cb(OnDataRecv); 164 | esp_now_register_send_cb(OnDataSent); 165 | infodisplay(); 166 | } 167 | void loop() { 168 | if(bot) 169 | espnow.BotConnectUpdate(); 170 | else 171 | espnow.RemoteConnectUpdate(); 172 | for(int num = 0; num < 120 * 160; num++) 173 | frameData[num] = camColors[TempData[num]]; 174 | #if expd 175 | M5.Lcd.drawBitmap((int)(M5.Lcd.width()-160)/2 , (int)(M5.Lcd.height()-120)/2, (int)160, (int)120,frameData); 176 | CursorLocation(num,fpa_temp,max_temp,min_temp); 177 | #else 178 | for(int z = 0; z < 20; z++){ 179 | for(int rows = 0; rows < 9; rows++){ 180 | for(int columns = 0; columns < 320;columns++){ 181 | expframeData[rows * 320 + columns] = frameData[960 * z + rows * 2 / 3 * 160 + columns/2]; 182 | } 183 | } 184 | M5.Lcd.drawBitmap(0, 27 + 9 * z, 320, 10,expframeData); 185 | } 186 | CursorLocation(num,fpa_temp,max_temp,min_temp); 187 | #endif 188 | 189 | } 190 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/Lepton_Bot.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Lepton.h" 5 | #include "espnow.h" 6 | #define expd 0 7 | Espnow espnow; 8 | char Title[] = {0x08,0x40,0x08,0x40,0x08,0x48,0x7F, 9 | 0xFC,0x08,0x48,0x0A,0x48,0x1C,0xC8, 10 | 0x68,0x48,0x08,0xA8,0x08,0x8A,0x29, 11 | 0x0A,0x12,0x04,0x00,0x00,0x48,0x88, 12 | 0x44,0x46,0x84,0x42, 13 | 0x00,0x80,0x00,0xA0,0x00,0x90,0x3F, 14 | 0xFC,0x20,0x80,0x20,0x80,0x20,0x84, 15 | 0x3E,0x44,0x22,0x48,0x22,0x48,0x22, 16 | 0x30,0x2A,0x20,0x24,0x62,0x40,0x92, 17 | 0x81,0x0A,0x00,0x06, 18 | 0x09,0x00,0x09,0xF0,0x0A,0x24,0x17, 19 | 0xFE,0x1C,0x44,0x37,0xFC,0x50,0x80, 20 | 0x91,0x44,0x16,0x68,0x10,0xB0,0x17, 21 | 0x30,0x10,0x68,0x11,0xA6,0x16,0x20, 22 | 0x10,0xA0,0x10,0x40, 23 | 0x08,0x00,0x08,0x80,0x08,0x64,0x12, 24 | 0x24,0x12,0x04,0x32,0x08,0x51,0x08, 25 | 0x91,0x10,0x10,0x90,0x10,0xA0,0x10, 26 | 0x40,0x10,0xA0,0x11,0x10,0x12,0x08, 27 | 0x14,0x0E,0x18,0x04}; 28 | uint8_t IndexData[19280]; 29 | extern unsigned short smallBuffer[160 * 120]; 30 | unsigned short expframeData[320 * 9]; 31 | extern uint16_t fpa_temp,aux_temp; 32 | uint8_t frameData[241] = {0}; 33 | extern const unsigned short camColors[]; 34 | float temp; 35 | float value_max; 36 | float value_min; 37 | Lepton lepton(21, 22, 5); 38 | void display_ch(int16_t x0, int16_t y0, 39 | int16_t w, int16_t h){ 40 | uint16_t posX = x0, posY = y0; 41 | 42 | for(int count = 0; count < 4;count++){ 43 | int k,j,i; 44 | byte flag; 45 | for(k=0; k<16; k++){ 46 | for(j=0; j<2; j++){ 47 | for(i=0; i<8; i++){ 48 | flag = Title[count * 32 +k*2+j]&(0x80 >> i); 49 | if(flag) 50 | M5.Lcd.drawPixel(posX + 8 * j + i, posY + k, WHITE); 51 | else 52 | M5.Lcd.drawPixel(posX + 8 * j + i, posY + k, BLACK); 53 | } 54 | } 55 | M5.Lcd.println(); 56 | } 57 | posX += 20; 58 | } 59 | } 60 | void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) 61 | { 62 | 63 | } 64 | 65 | void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) 66 | { 67 | // Serial.print("data_len = ");Serial.println(data_len); 68 | if(bot) 69 | espnow.OnBotRecv(mac_addr,data,data_len); 70 | else 71 | espnow.OnRemotRecv(mac_addr,data,data_len); 72 | } 73 | /***infodisplay()*****/ 74 | void infodisplay(void) { 75 | 76 | M5.Lcd.setCursor(58, 0, 4); 77 | //M5.Lcd.print("THERMOGRAPHY"); 78 | display_ch(120, 3,122, 24); 79 | 80 | M5.Lcd.fillRect(0, 206, 320, 4, TFT_WHITE); 81 | M5.Lcd.setTextColor(TFT_WHITE); 82 | M5.Lcd.fillRect(0, 22, 320, 4, TFT_WHITE); 83 | M5.Lcd.setTextColor(TFT_WHITE); 84 | } 85 | int max_num,old_max_num; 86 | void task1(void * pvParameters) { 87 | 88 | for(;;) { 89 | delay(100); 90 | #if 0 91 | 92 | uint8_t data[10]; 93 | data[0] = (uint8_t)(max_num>>8); 94 | data[1] = (uint8_t)(max_num&0xff); 95 | if(temp >= 120) return; 96 | data[2] = (uint8_t)((uint16_t)(temp * 10)>>8); 97 | data[3] = (uint8_t)((uint16_t)(temp * 10)&0xff); 98 | if(value_max >= 120) return; 99 | data[4] = (uint8_t)((uint16_t)(value_max * 10)>>8); 100 | data[5] = (uint8_t)((uint16_t)(value_max * 10)&0xff); 101 | if(value_min >= 120) return; 102 | data[6] = (uint8_t)((uint16_t)(value_min * 10)>>8); 103 | data[7] = (uint8_t)((uint16_t)(value_min * 10)&0xff); 104 | esp_now_send(espnow.peer_addr, data,10); 105 | 106 | 107 | for(byte frame = 0; frame < 10 * 8; frame++){ 108 | frameData[0] = frame; 109 | for(int i = 1; i < 241; i++){ 110 | frameData[i] = IndexData[frame * 240 + i - 1]; 111 | } 112 | while(esp_now_send(espnow.peer_addr, frameData,241) !=ESP_OK) ; 113 | } 114 | #endif 115 | } 116 | } 117 | 118 | void setup() { 119 | delay(100); 120 | M5.begin(); 121 | espnow.BotInit(); 122 | esp_now_register_recv_cb(OnDataRecv); 123 | esp_now_register_send_cb(OnDataSent); 124 | pinMode(13, INPUT); 125 | digitalWrite(13, HIGH); 126 | lepton.begin(); 127 | lepton.syncFrame(); 128 | uint16_t SYNC = 5,DELAY = 3,oen = 1,dat; 129 | lepton.doSetCommand(0x4854, &SYNC, 1); 130 | lepton.doSetCommand(0x4858, &DELAY, 1); 131 | //lepton.doSetCommand(0x4E10, &oen, 1); 132 | //lepton.doGetCommand(0x4E10, &dat); 133 | //Serial.print(" gpio6 = ");Serial.println(dat); 134 | lepton.end(); 135 | infodisplay(); 136 | 137 | // Task 1 138 | xTaskCreatePinnedToCore( 139 | task1, /* Function to implement the task */ 140 | "task1", /* Name of the task */ 141 | 4096, /* Stack size in words */ 142 | NULL, /* Task input parameter */ 143 | 1, /* Priority of the task */ 144 | NULL, /* Task handle. */ 145 | 0); 146 | } 147 | void CursorLocation(uint16_t num, float fpa_temp,float max_temp,float min_temp){ 148 | #if expd 149 | int centre_x = (int)(M5.Lcd.width()-160)/2 + num % 160; 150 | int centre_y = (int)(M5.Lcd.height()-120)/2 + num / 160; 151 | 152 | if(centre_x <= (int)(M5.Lcd.width()-160)/2+10) 153 | centre_x = (int)(M5.Lcd.width()-160)/2+10; 154 | else if(centre_x >= (int)(M5.Lcd.width()-160)/2 + 160 - 12) 155 | centre_x = (int)(M5.Lcd.width()-160)/2 + 160 - 12; 156 | 157 | 158 | if(centre_y <= (int)(M5.Lcd.height()-120)/2+10) 159 | centre_y = (int)(M5.Lcd.height()-120)/2+10; 160 | else if(centre_y >= (int)(M5.Lcd.height()-120)/2 + 120 - 11) 161 | centre_y = (int)(M5.Lcd.height()-120)/2 + 120 - 11; 162 | #else 163 | int centre_x = num % 160; 164 | int centre_y = num / 160; 165 | centre_x = centre_x * 2; 166 | centre_y = 27 + centre_y * 3/2; 167 | 168 | if(centre_y <= (int)(27+10)) 169 | centre_y = 27+10; 170 | else if(centre_y >= (int)(207 - 11)) 171 | centre_y = 207 - 11; 172 | #endif 173 | M5.Lcd.drawCircle(centre_x, centre_y, 6, TFT_WHITE); // update center spot icon 174 | M5.Lcd.drawLine(centre_x, centre_y-10, centre_x, centre_y+10, TFT_WHITE); // vertical line 175 | M5.Lcd.drawLine(centre_x-10, centre_y, centre_x+10, centre_y, TFT_WHITE); // horizontal lin 176 | 177 | if(centre_x >= ((int)(M5.Lcd.width()-160)/2 + 160 - 12 - 45)) 178 | M5.Lcd.setCursor(centre_x-55, centre_y-10,2); 179 | else 180 | M5.Lcd.setCursor(centre_x+20, centre_y-10,2); 181 | M5.Lcd.print(max_temp, 1); 182 | M5.Lcd.printf("C" ,1); 183 | #if 0 184 | M5.Lcd.fillRect(270, 160, 60, 15, TFT_BLACK); //Clear fps text area 185 | M5.Lcd.setTextSize(1); 186 | M5.Lcd.setCursor(250, 160); 187 | M5.Lcd.print("aux:" + String(max_temp)+"C"); 188 | #endif 189 | //M5.Lcd.fillRect(270, 180, 60, 15, TFT_BLACK); //Clear fps text area 190 | M5.Lcd.setTextSize(1); 191 | M5.Lcd.setCursor(250, 190); 192 | M5.Lcd.print("fpa:" + String(max_temp)+"C"); 193 | int icolor = 0; 194 | for (int icol = 0; icol <= 360; icol++){ 195 | //彩色条 196 | //M5.Lcd.drawRect(36, 208, icol, 284 , camColors[icolor]); 197 | M5.Lcd.drawRect(0, 210, icol, 284 , camColors[icolor]); 198 | if(icolor <= 250) 199 | icolor++; 200 | } 201 | M5.Lcd.setCursor(30, 215,4); 202 | M5.Lcd.printf("min = %0.1fC max = %0.1fC",min_temp,max_temp); 203 | } 204 | void loop() { 205 | espnow.BotConnectUpdate(); 206 | #if 0 207 | lepton.syncFrame(); 208 | lepton.readFrame(frameData); 209 | lepton.end(); 210 | #else 211 | error1: 212 | lepton.getRawValues(); 213 | #endif 214 | 215 | #if 1 216 | float fpatemp = fpa_temp/100.0f; 217 | temp = fpatemp-273.15; 218 | uint16_t minValue = 65535, maxValue = 0; 219 | uint16_t value; 220 | for(int num = 0; num < 120 * 160; num++) 221 | { 222 | if(smallBuffer[num] > maxValue) { 223 | maxValue = smallBuffer[num]; 224 | max_num = num; 225 | } 226 | if(smallBuffer[num] < minValue) { 227 | minValue = smallBuffer[num]; 228 | } 229 | } 230 | //delay(10); 231 | //Serial.printf("maxValue %d\n",maxValue);Serial.printf("minValue %d\n",minValue); 232 | #if 1 233 | float diff = (maxValue - minValue); 234 | diff = diff / 256.0f; 235 | if(diff < 0.56f) diff = 0.56f; 236 | float fpatemp_f = fpatemp * 1.8f - 459.67f; 237 | value_min = ((0.05872 * (float)minValue - 472.22999f + fpatemp_f)); 238 | value_min= (value_min - 32.0f) / 1.8f; 239 | value_max = ((0.05872 * (float)maxValue - 472.22999f + fpatemp_f)); 240 | value_max = (value_max - 32.0f) / 1.8f; 241 | if(value_min < -100 || value_max > 500){ 242 | Serial.println("Error!"); 243 | goto error1; 244 | } 245 | 246 | value_min = 0.0217 *((float)minValue - 8292)+ fpatemp - 273.16; 247 | value_max = 0.0217 *((float)maxValue - 8292)+ fpatemp - 273.16; 248 | #else 249 | float diff = (maxValue - minValue); 250 | if(diff >= 255) diff = 255; 251 | //float scale = diff/300.0;0x04df 252 | float scale = (float)(0xf813 - 0xe0ff)/diff ; 253 | //Serial.printf("maxValue %d\n",maxValue);Serial.printf("minValue %d\n",minValue);Serial.printf(" %f\n",diff);Serial.printf(" %f\n",scale); 254 | //Serial.printf("maxValue %d\n",maxValue);Serial.printf("minValue %d\n",minValue);Serial.printf(" %f\n",diff);Serial.printf(" %f\n",scale); 255 | float *buf = &scale; 256 | #endif 257 | int colorIndex = 0; 258 | for(int num = 0; num < 120 * 160; num++){ 259 | colorIndex = (smallBuffer[num] - minValue)/diff; 260 | if(colorIndex <= 0) colorIndex = 0; 261 | if(colorIndex > 255) colorIndex = 255; 262 | IndexData[num] = colorIndex; 263 | smallBuffer[num] = camColors[colorIndex]; 264 | } 265 | #if expd 266 | M5.Lcd.drawBitmap((int)(M5.Lcd.width()-160)/2 , (int)(M5.Lcd.height()-120)/2, (int)160, (int)120,smallBuffer); 267 | CursorLocation(max_num,temp,value_max,value_min); 268 | #else 269 | for(int z = 0; z < 20; z++){ 270 | for(int rows = 0; rows < 9; rows++){ 271 | for(int columns = 0; columns < 320;columns++){ 272 | expframeData[rows * 320 + columns] = smallBuffer[960 * z + rows * 2 / 3 * 160 + columns/2]; 273 | } 274 | } 275 | M5.Lcd.drawBitmap(0, 27 + 9 * z, 320, 10,expframeData); 276 | } 277 | CursorLocation(max_num,temp,value_max,value_min); 278 | #endif 279 | #if 0 280 | uint8_t data[10]; 281 | data[0] = (uint8_t)(max_num>>8); 282 | data[1] = (uint8_t)(max_num&0xff); 283 | data[2] = (uint8_t)((uint16_t)(temp * 10)>>8); 284 | data[3] = (uint8_t)((uint16_t)(temp * 10)&0xff); 285 | data[4] = (uint8_t)((uint16_t)(value_max * 10)>>8); 286 | data[5] = (uint8_t)((uint16_t)(value_max * 10)&0xff); 287 | data[6] = (uint8_t)((uint16_t)(value_min * 10)>>8); 288 | data[7] = (uint8_t)((uint16_t)(value_min * 10)&0xff); 289 | esp_now_send(espnow.peer_addr, data,10); 290 | esp_err_t result; 291 | #if 0 292 | for(byte frame = 0; frame < 10 * 8 * 2; frame++){ 293 | frameData[0] = frame; 294 | for(int i = 1; i < 241; i++){ 295 | if(i%2) 296 | frameData[i] = smallBuffer[frame * 120 + (i - 1)/2] & 0x00ff; 297 | else 298 | frameData[i] = (smallBuffer[frame * 120 + (i - 1)/2] >> 8); 299 | } 300 | esp_now_send(espnow.peer_addr, frameData,241); 301 | #else 302 | for(byte frame = 0; frame < 10 * 8; frame++){ 303 | frameData[0] = frame; 304 | for(int i = 1; i < 241; i++) 305 | { 306 | frameData[i] = IndexData[frame * 240 + i - 1]; 307 | } 308 | while(esp_now_send(espnow.peer_addr, frameData,241) !=ESP_OK) ; 309 | #endif 310 | } 311 | #endif 312 | #endif 313 | 314 | } 315 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/lepton.cpp: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "Lepton.h" 3 | #include "Wire.h" 4 | #include "SPI.h" 5 | #define rotationHorizont 0 6 | #define rotationVert 0 7 | static byte leptonFrame[164]; 8 | unsigned short smallBuffer[160 * 120]; 9 | //unsigned char temp[240][4] = {0}; 10 | //byte segm = 0; 11 | uint16_t aux_temp = 0, fpa_temp = 0; 12 | Lepton::Lepton(int sdaPin, int sclPin, int ssPin) : _sdaPin(sdaPin), _sclPin(sclPin), _ssPin(ssPin) { 13 | } 14 | void Lepton::begin() { 15 | 16 | Wire.begin(_sdaPin, _sclPin); 17 | 18 | pinMode(_ssPin, OUTPUT); 19 | digitalWrite(_ssPin, HIGH); 20 | 21 | SPI.begin(); 22 | } 23 | 24 | uint16_t Lepton::readRegister(uint16_t reg) { 25 | setRegister(reg); 26 | Wire.requestFrom(DEVICE_ID, (uint8_t)2); 27 | return readWord(); 28 | } 29 | 30 | void Lepton::writeRegister(uint16_t reg, uint16_t value) { 31 | startTransmission(reg); 32 | transmitWord(value); 33 | endTransmission(); 34 | } 35 | 36 | /* Get one line package from the Lepton */ 37 | int Lepton::getPackage(byte line, byte seg) 38 | { 39 | 40 | SPI.transferBytes(0x0000,leptonFrame,164); 41 | 42 | if((leptonFrame[0] & 0x0F) == 0x0F) 43 | return 1; 44 | 45 | //Check if the line number matches the expected line 46 | if (leptonFrame[1] != line) 47 | return 2; 48 | 49 | //For the Lepton3.x, check if the segment number matches 50 | if (line == 20) 51 | { 52 | byte segment = (leptonFrame[0] >> 4); 53 | if (segment == 0) 54 | return 3; 55 | if (segment != seg) 56 | return 4; 57 | } 58 | 59 | /* 60 | temp[(seg - 1)* 60 + line][0] = seg; 61 | temp[(seg - 1) * 60 + line][1] = line; 62 | 63 | temp[(seg - 1)* 60 + line][2] = (leptonFrame[0] >> 4); 64 | temp[(seg - 1) * 60 + line][3] = leptonFrame[1]; 65 | */ 66 | 67 | //Everything worked 68 | return 0; 69 | } 70 | 71 | /* Store one package of 80 columns into RAM */ 72 | bool Lepton::savePackage(byte line, byte segment) 73 | { 74 | //Go through the video pixels for one video line 75 | for (int column = 0; column < 80; column++) 76 | { 77 | //Apply horizontal mirroring 78 | if (rotationHorizont) 79 | column = 79 - column; 80 | 81 | //Make a 16-bit rawvalue from the lepton frame 82 | uint16_t result = (uint16_t) (leptonFrame[2 * column + 4] << 8 83 | | leptonFrame[2 * column + 5]); 84 | 85 | //Discard horizontal mirroring 86 | if (rotationHorizont) 87 | column = 79 - column; 88 | 89 | //Invalid value, return 90 | if (result == 0) 91 | { 92 | return 0; 93 | } 94 | /* 95 | //Lepton2.x 96 | if ((leptonVersion != leptonVersion_3_0_shutter) 97 | && (leptonVersion != leptonVersion_3_5_shutter)) 98 | { 99 | //Rotated or old hardware version 100 | if (((mlx90614Version == mlx90614Version_old) && (!rotationVert)) 101 | || ((mlx90614Version == mlx90614Version_new) 102 | && (rotationVert))) 103 | { 104 | smallBuffer[(line * 2 * 160) + (column * 2)] = result; 105 | smallBuffer[(line * 2 * 160) + (column * 2) + 1] = result; 106 | smallBuffer[(line * 2 * 160) + 160 + (column * 2)] = result; 107 | smallBuffer[(line * 2 * 160) + 160 + (column * 2) + 1] = result; 108 | } 109 | //Non-rotated 110 | else 111 | { 112 | smallBuffer[19199 - ((line * 2 * 160) + (column * 2))] = result; 113 | smallBuffer[19199 - ((line * 2 * 160) + (column * 2) + 1)] = 114 | result; 115 | smallBuffer[19199 - ((line * 2 * 160) + 160 + (column * 2))] = 116 | result; 117 | smallBuffer[19199 - ((line * 2 * 160) + 160 + (column * 2) + 1)] = 118 | result; 119 | } 120 | } 121 | */ 122 | //Lepton3 123 | // else 124 | { 125 | //Non-rotated 126 | if (!rotationVert) 127 | { 128 | switch (segment) 129 | { 130 | case 1: 131 | if (rotationHorizont) 132 | smallBuffer[19199 133 | - (((line / 2) * 160) + ((1 - (line % 2)) * 80) 134 | + (column))] = result; 135 | else 136 | smallBuffer[19199 137 | - (((line / 2) * 160) + ((line % 2) * 80) 138 | + (column))] = result; 139 | break; 140 | case 2: 141 | if (rotationHorizont) 142 | smallBuffer[14399 143 | - (((line / 2) * 160) + ((1 - (line % 2)) * 80) 144 | + (column))] = result; 145 | else 146 | smallBuffer[14399 147 | - (((line / 2) * 160) + ((line % 2) * 80) 148 | + (column))] = result; 149 | break; 150 | case 3: 151 | if (rotationHorizont) 152 | smallBuffer[9599 153 | - (((line / 2) * 160) + ((1 - (line % 2)) * 80) 154 | + (column))] = result; 155 | else 156 | smallBuffer[9599 157 | - (((line / 2) * 160) + ((line % 2) * 80) 158 | + (column))] = result; 159 | break; 160 | case 4: 161 | if (rotationHorizont) 162 | smallBuffer[4799 163 | - (((line / 2) * 160) + ((1 - (line % 2)) * 80) 164 | + (column))] = result; 165 | else 166 | smallBuffer[4799 167 | - (((line / 2) * 160) + ((line % 2) * 80) 168 | + (column))] = result; 169 | break; 170 | default:break; 171 | } 172 | } 173 | //Rotated 174 | else 175 | { 176 | switch (segment) 177 | { 178 | case 1: 179 | smallBuffer[((line / 2) * 160) + ((line % 2) * 80) 180 | + (column)] = result; 181 | break; 182 | case 2: 183 | smallBuffer[4800 184 | + (((line / 2) * 160) + ((line % 2) * 80) + (column))] = 185 | result; 186 | break; 187 | case 3: 188 | smallBuffer[9600 189 | + (((line / 2) * 160) + ((line % 2) * 80) + (column))] = 190 | result; 191 | break; 192 | case 4: 193 | smallBuffer[14400 194 | + (((line / 2) * 160) + ((line % 2) * 80) + (column))] = 195 | result; 196 | break; 197 | default:break; 198 | } 199 | } 200 | } 201 | 202 | } 203 | //Everything worked 204 | return 1; 205 | } 206 | uint16_t Lepton::doGetCommand(uint16_t commandIdBase, uint16_t* data) { 207 | writeRegister(REG_COMMAND_ID, commandIdBase | TYPE_GET); 208 | waitIdle(); 209 | return readData(data); 210 | } 211 | 212 | void Lepton::doSetCommand(uint16_t commandIdBase, uint16_t* data, uint16_t dataLen) { 213 | writeData(data, dataLen); 214 | writeRegister(REG_COMMAND_ID, commandIdBase | TYPE_SET); 215 | waitIdle(); 216 | } 217 | 218 | uint16_t Lepton::doRunCommand(uint16_t commandIdBase, uint16_t* data, uint16_t dataLen) { 219 | writeData(data, dataLen); 220 | writeRegister(REG_COMMAND_ID, commandIdBase | TYPE_RUN); 221 | waitIdle(); 222 | return readData(data); 223 | } 224 | 225 | /* Get one frame of raw values from the lepton */ 226 | void Lepton::getRawValues() 227 | { 228 | byte line, error, segmentNumbers = 4; 229 | 230 | //Begin SPI Transmission 231 | //lepton_begin(); 232 | syncFrame(); 233 | 234 | //Go through the segments 235 | for (byte segment = 1; segment <= segmentNumbers; segment++) 236 | { 237 | //Sync 238 | uint16_t delay_time = 0; 239 | while(digitalRead(13) == HIGH) 240 | { 241 | delay_time++; 242 | if(delay_time>=20) 243 | break; 244 | } 245 | 246 | //Reset error counter for each segment 247 | error = 0; 248 | //Go through one segment, equals 60 lines of 80 values 249 | do 250 | { 251 | //int retVal = 0; 252 | for (line = 0; line < 60; line++) 253 | { 254 | 255 | //Maximum error count 256 | if (error == 255) 257 | { 258 | //Reset segment 259 | segment = 1; 260 | //Reset error 261 | error = 0; 262 | //Reset Lepton SPI 263 | reset(); 264 | //Restart at line 0 265 | break; 266 | } 267 | //Get a package from the lepton 268 | int retVal = getPackage(line, segment); 269 | //If everythin worked, continue 270 | if (retVal == 0){ 271 | if (savePackage(line, segment)) 272 | //if (savePackage(line, segm)) 273 | continue; 274 | } 275 | 276 | //Raise lepton error 277 | error++; 278 | 279 | //Stabilize framerate 280 | uint32_t time = micros(); 281 | while ((micros() - time) < 800) 282 | __asm__ volatile ("nop"); 283 | 284 | //Restart at line 0 285 | break; 286 | } 287 | } while (line != 60); 288 | 289 | } 290 | 291 | doGetCommand(CMD_SYS_FPA_TEMPERATURE_KELVIN, &fpa_temp); 292 | doGetCommand(CMD_SYS_AUX_TEMPERATURE_KELVIN, &aux_temp); 293 | 294 | //End SPI Transmission 295 | end(); 296 | } 297 | 298 | void Lepton::reset() 299 | { 300 | //End SPI Transmission 301 | end(); 302 | delay(186); 303 | syncFrame(); 304 | } 305 | uint16_t Lepton::syncFrame() { 306 | 307 | SPI.beginTransaction(SPISettings(15000000, MSBFIRST, SPI_MODE3)); 308 | digitalWrite(_ssPin, LOW); 309 | delay(0.02); 310 | 311 | static int count; 312 | if(count < 1) 313 | delay(1000); 314 | count++; 315 | if(count>=5) 316 | count = 5; 317 | 318 | 319 | } 320 | 321 | void Lepton::end() { 322 | digitalWrite(_ssPin, HIGH); 323 | SPI.endTransaction(); 324 | } 325 | 326 | int Lepton::readFrame(uint16_t* data) { 327 | for (byte segment = 1; segment <= 4; segment++){ 328 | uint16_t row = 0; 329 | uint16_t id = waitNextFrame(); 330 | while ((id & 0xfff) == row) { 331 | uint16_t crc = readFrameWord(); 332 | for (int col = 0; col < 80; col++) { 333 | data[(segment - 1) * 4800 + row * 80 + col] = readFrameWord(); 334 | } 335 | 336 | if ((row == 20)){ 337 | //byte seg = (id >> 12); 338 | //if (seg == 0) 339 | // return 1; 340 | ///if (segment != seg) 341 | // return 2; 342 | } 343 | //Serial.printf("row = %d, segment = %d, id = %d,id_row = %d\n", row, segment, id >> 12, id & 0xfff); 344 | row++; 345 | if (row < 60) { 346 | id = readFrameWord(); 347 | } else { 348 | //return 1; 349 | break; 350 | } 351 | //Serial.printf("................readFrame ended with row %4x != id %4x\n", row, id); 352 | } 353 | 354 | 355 | //for(;row<60;row++) 356 | //for (int col = 0; col < 80; col++) { 357 | // data[(segment - 1) * 4800 + row * 80 + col] = 0x1f40; 358 | //} 359 | //Serial.printf("readFrame ended with row %4x != id %4x\n", row, id); 360 | } 361 | return 0; 362 | } 363 | 364 | /* 365 | uint16_t Lepton::wait_160x120_Seg(void) 366 | { 367 | //uint16_t Lepton::wait_160X120_NextFrame() { 368 | uint16_t id = readFrameWord(); 369 | Serial.printf("id = %d\n", id); 370 | while ((id & 0x0f00) == 0x0f00) { 371 | for (int i = 0; i < 161; i++) { 372 | readFrameWord(); 373 | } 374 | id = readFrameWord(); 375 | //Serial.printf("id = %d\n", id); 376 | } 377 | return id; 378 | } 379 | } 380 | */ 381 | int Lepton::read_160x120_Frame(uint16_t* data) { 382 | uint16_t row = 0; 383 | uint16_t id = waitNextFrame(); 384 | while ((id & 0xfff) == row) { 385 | uint16_t crc = readFrameWord(); 386 | for (int col = 0; col < 80; col++) { 387 | data[row * 80 + col] = readFrameWord(); 388 | } 389 | 390 | // Serial.printf(" %d %d %d\n", (id & 0x7000)>>12 ,(id & 0xfff) , row); 391 | row++; 392 | if (row < 60) { 393 | id = readFrameWord(); 394 | } else { 395 | return 1; 396 | } 397 | //Serial.printf("................readFrame ended with row %4x != id %4x\n", row, id); 398 | } 399 | //Serial.printf("readFrame ended with row %4x != id %4x\n", row, id); 400 | return 0; 401 | } 402 | 403 | 404 | 405 | void Lepton::readFrameRaw(uint16_t* data) { 406 | data[0] = waitNextFrame(); 407 | for (int i = 1; i < 82 * 60; i++) { 408 | data[i] = readFrameWord(); 409 | } 410 | } 411 | 412 | void Lepton::startTransmission(uint16_t reg) { 413 | Wire.beginTransmission(DEVICE_ID); 414 | transmitWord(reg); 415 | } 416 | 417 | void Lepton::transmitWord(uint16_t value) { 418 | Wire.write(value >> 8 & 0xff); 419 | Wire.write(value & 0xff); 420 | } 421 | 422 | void Lepton::endTransmission() { 423 | uint8_t error = Wire.endTransmission(); 424 | if (error != 0) { 425 | Serial.print("error="); 426 | Serial.println(error); 427 | } 428 | } 429 | 430 | uint16_t Lepton::readWord() { 431 | uint16_t value = Wire.read() << 8; 432 | value |= Wire.read(); 433 | return value; 434 | } 435 | 436 | void Lepton::setRegister(uint16_t reg) { 437 | startTransmission(reg); 438 | endTransmission(); 439 | } 440 | 441 | void Lepton::waitIdle() { 442 | while (readRegister(REG_STATUS) & STATUS_BIT_BUSY) { 443 | } 444 | } 445 | 446 | uint16_t Lepton::readData(uint16_t* data) { 447 | uint16_t dataLen = readRegister(REG_DATA_LEN) / 2; // The data sheet says the data length register is in 16-bit words, but it actually seems to be in bytes 448 | setRegister(REG_DATA_BASE); 449 | Wire.requestFrom(DEVICE_ID, (uint8_t)(dataLen * 2)); 450 | for (int i = 0; i < dataLen; i++) { 451 | data[i] = readWord(); 452 | } 453 | // TODO Check CRC 454 | return dataLen; 455 | } 456 | 457 | void Lepton::writeData(uint16_t* data, uint16_t dataLen) { 458 | startTransmission(REG_DATA_LEN); 459 | transmitWord(dataLen); 460 | for (int i = 0; i < dataLen; i++) { 461 | transmitWord(data[i]); 462 | } 463 | endTransmission(); 464 | } 465 | 466 | uint16_t Lepton::readFrameWord() { 467 | uint16_t data = SPI.transfer(0x00) << 8; 468 | data |= SPI.transfer(0x00); 469 | return data; 470 | } 471 | 472 | uint16_t Lepton::waitNextFrame() { 473 | uint16_t id = readFrameWord(); 474 | //Serial.printf("id = %d\n", id); 475 | while ((id & 0x0f00) == 0x0f00) { 476 | for (int i = 0; i < 81; i++) { 477 | readFrameWord(); 478 | } 479 | id = readFrameWord(); 480 | //Serial.printf(" %d %d %d\n", id,(id & 0xfff) , (id & 0x0f00)); 481 | //Serial.printf("ID = %X \n", id); 482 | } 483 | //Serial.printf("idwhile = %d\n", id); 484 | return id; 485 | } 486 | uint16_t Lepton::wait_160X120_NextFrame() { 487 | /* 488 | uint16_t seg = readFrameWord(); 489 | Serial.printf("seg = %d\n", seg); 490 | //while ((id & 0x0e00) == 0x0e00) { 491 | 492 | for (int i = 0; i < 81; i++) { 493 | id = readFrameWord(); 494 | } 495 | id = readFrameWord(); 496 | //Serial.printf("id = %d\n", id); 497 | */ 498 | uint16_t seg = 0; 499 | for(int i = 0; i < 82 * 60; i++) 500 | { 501 | seg = readFrameWord(); 502 | Serial.printf("seg = %d ", (seg & 0x7000)>>12);Serial.printf("id = %d\n", seg & 0x0fff); 503 | } 504 | //return id; 505 | } 506 | 507 | 508 | void Lepton::dumpHex(uint16_t *data, int dataLen) { 509 | for (int i = 0; i < dataLen; i++) { 510 | Serial.printf("%4x ", data[i]); 511 | } 512 | Serial.println(); 513 | } 514 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Remoter/espnow.cpp: -------------------------------------------------------------------------------- 1 | #include"espnow.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | Espnow::Espnow(void) 8 | { 9 | 10 | } 11 | 12 | void Espnow::BotInit(void){ 13 | 14 | //m5.begin(); 15 | //Serial.begin(115200); 16 | 17 | pinMode(37, INPUT); 18 | pinMode(38, INPUT); 19 | pinMode(39, INPUT); 20 | //digitalWrite(37, HIGH); 21 | // digitalWrite(38, HIGH); 22 | //digitalWrite(39, HIGH); 23 | 24 | WiFi.mode(WIFI_STA); 25 | Serial.println("ESPNow Master Example"); 26 | // This is the mac address of the Master in Station Mode 27 | Serial.print("STA MAC: "); 28 | Serial.println(WiFi.macAddress()); 29 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 30 | //WiFi.softAPmacAddress() 31 | //if(!bot) 32 | sscanf(WiFi.macAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 33 | //else 34 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 35 | //WiFi.softAPmacAddress() 36 | //WiFi.softAPmacAddress() 37 | InitEspNow(); 38 | 39 | preferences.begin("my-app", false); 40 | String mac_addr; 41 | mac_addr = preferences.getString("mac_addr", "error"); 42 | Serial.print("mac_addr = ");Serial.print(mac_addr); 43 | 44 | sscanf(mac_addr.c_str(), "%x:%x:%x:%x:%x:%x%c", &peer_addr[0], &peer_addr[1], &peer_addr[2], &peer_addr[3], &peer_addr[4], &peer_addr[5]); 45 | 46 | for (int i = 0; i < 6; ++i ){ 47 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 48 | } 49 | slave.channel = CHANNEL; 50 | esp_now_add_peer(&slave); 51 | } 52 | 53 | void Espnow::RemoteInit(void) 54 | { 55 | //m5.begin(); 56 | //Serial.begin(115200); 57 | 58 | pinMode(37, INPUT); 59 | pinMode(38, INPUT); 60 | pinMode(39, INPUT); 61 | //digitalWrite(37, HIGH); 62 | // digitalWrite(38, HIGH); 63 | //digitalWrite(39, HIGH); 64 | 65 | WiFi.mode(WIFI_AP_STA); 66 | //WiFi.mode(WIFI_AP); 67 | ConfigDeviceAP(); 68 | Serial.println("ESPNow Master Example"); 69 | // This is the mac address of the Master in Station Mode 70 | Serial.print(" AP MAC: "); 71 | Serial.println(WiFi.softAPmacAddress()); 72 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 73 | //WiFi.softAPmacAddress() 74 | //if(!bot) 75 | sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 76 | //else 77 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 78 | //WiFi.softAPmacAddress() 79 | //WiFi.softAPmacAddress() 80 | InitEspNow(); 81 | 82 | preferences.begin("my-app", false); 83 | String mac_addr; 84 | mac_addr = preferences.getString("mac_addr", "error"); 85 | Serial.print("mac_addr = ");Serial.print(mac_addr); 86 | 87 | sscanf(mac_addr.c_str(), "%x:%x:%x:%x:%x:%x%c", &peer_addr[0], &peer_addr[1], &peer_addr[2], &peer_addr[3], &peer_addr[4], &peer_addr[5]); 88 | 89 | for (int i = 0; i < 6; ++i ){ 90 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 91 | } 92 | slave.channel = CHANNEL; 93 | esp_now_add_peer(&slave); 94 | } 95 | 96 | // config AP SSID 97 | void Espnow::ConfigDeviceAP(void) 98 | { 99 | 100 | String Mac = WiFi.macAddress(); 101 | String SSID = "Slave:"+ Mac; 102 | bool result = WiFi.softAP(SSID.c_str(), "12345678", CHANNEL, 0); 103 | if (!result) 104 | { 105 | Serial.println("AP Config failed."); 106 | } else 107 | { 108 | Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID)); 109 | } 110 | } 111 | 112 | // Init ESP Now with fallback 113 | void Espnow::InitEspNow(void) 114 | { 115 | if (esp_now_init() == ESP_OK) 116 | { 117 | Serial.println("ESPNow Init Success"); 118 | } 119 | else 120 | { 121 | Serial.println("ESPNow Init Failed"); 122 | ESP.restart(); 123 | } 124 | } 125 | 126 | void Espnow::OnRemotSent(const uint8_t *mac_addr, esp_now_send_status_t status) 127 | { 128 | 129 | } 130 | void Espnow::OnRemotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len){ 131 | 132 | if(data_len == 4) 133 | { 134 | connectflag = true; 135 | } 136 | if(data_len == 6) 137 | { 138 | int i = 0; 139 | for(i = 0; i < connect_num; i++) 140 | { 141 | int j = 0; 142 | for(j = 0; j < 6; j++) 143 | { 144 | if(connect_addr[i][j] != data[j]) 145 | { 146 | break; 147 | } 148 | } 149 | //Serial.printf("j = %d",j); 150 | if(j == 6) 151 | { 152 | break; 153 | } 154 | } 155 | 156 | if(i == connect_num) 157 | { 158 | for(int i = 0; i < 6;i++) 159 | { 160 | connect_addr[connect_num][i] = data[i]; 161 | } 162 | connect_num++; 163 | } 164 | } 165 | if(connect_num> 20) connect_num = 0; 166 | 167 | 168 | int mac_comp = 0; 169 | for(mac_comp = 0; mac_comp < 6; mac_comp++){ 170 | if(mac_addr[mac_comp] != peer_addr[mac_comp]){ 171 | return; 172 | } 173 | } 174 | } 175 | 176 | void Espnow::OnBotSent(const uint8_t *mac_addr, esp_now_send_status_t status) 177 | { 178 | } 179 | void Espnow::OnBotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) 180 | { 181 | Serial.print("connectflag = ");Serial.println(connectflag); 182 | if ((data_len == 7) && (!connectflag)) 183 | { 184 | connectflag = true; 185 | int i = 0; 186 | for (i = 0; i < connect_num; i++) 187 | { 188 | int j = 0; 189 | for (j = 0; j < 6; j++) 190 | { 191 | if (connect_addr[i][j] != mac_addr[j]) 192 | { 193 | break; 194 | } 195 | } 196 | //Serial.printf("j = %d",j); 197 | if (j == 6) 198 | { 199 | break; 200 | } 201 | } 202 | if (i == connect_num) 203 | { 204 | for (int i = 0; i < 6; i++) 205 | { 206 | connect_addr[connect_num][i] = mac_addr[i]; 207 | } 208 | connect_num++; 209 | } 210 | } 211 | //if (connect_num > 20) connect_num = 0; 212 | 213 | int mac_comp = 0; 214 | for(mac_comp = 0; mac_comp < 6; mac_comp++){ 215 | if(mac_addr[mac_comp] != peer_addr[mac_comp]){ 216 | return; 217 | } 218 | } 219 | } 220 | 221 | void Espnow::RemoteConnectUpdate(){ 222 | 223 | static int updatetime; 224 | if (digitalRead(38) == LOW) 225 | { 226 | updatetime++; 227 | } 228 | Serial.println(updatetime); 229 | if (updatetime >= 30){ 230 | updatetime = 0; 231 | delay(200); 232 | M5.Speaker.tone(80, 200); 233 | delay(200); 234 | M5.Lcd.fillScreen(TFT_BLACK); 235 | M5.Speaker.mute(); 236 | int ypos = 0; 237 | int old_ypos = 0; 238 | connect_num = 0; 239 | connectflag = false; 240 | while(true) 241 | { 242 | M5.Lcd.setCursor(0, 0, 4); 243 | M5.Lcd.println("LidarBot Scanning...."); 244 | for(int i = 0; i < connect_num; i++) 245 | { 246 | M5.Lcd.setCursor(30, 25 + 25 * i); // Set cursor near top left corner of screen 247 | M5.Lcd.printf("%02x:%02x:%02x:%02x:%02x:%02x", connect_addr[i][0], connect_addr[i][1], connect_addr[i][2], connect_addr[i][3], connect_addr[i][4], connect_addr[i][5]); 248 | } 249 | if(connect_num){ 250 | M5.Lcd.setCursor(270, 25 + ypos * 25); 251 | M5.Lcd.println("<<"); 252 | } 253 | 254 | if(ypos < 1){ 255 | //M5.Lcd.fillScreen(TFT_BLACK); 256 | if(old_ypos != ypos) 257 | M5.Lcd.fillRect(30, 210, 90, 50, TFT_BLACK); 258 | M5.Lcd.setCursor(30, 210); 259 | M5.Lcd.println("update"); 260 | } 261 | else 262 | { 263 | if(old_ypos != ypos) 264 | M5.Lcd.fillRect(30, 210, 100, 50, TFT_BLACK); 265 | //M5.Lcd.fillScreen(TFT_BLACK); 266 | M5.Lcd.setCursor(50, 210); 267 | M5.Lcd.println("up"); 268 | } 269 | old_ypos = ypos; 270 | M5.Lcd.setCursor(125, 210); 271 | M5.Lcd.println("down"); 272 | M5.Lcd.setCursor(220, 210); 273 | M5.Lcd.println("select"); 274 | 275 | 276 | //select down 277 | if ((digitalRead(37) == LOW) && (connect_num)) 278 | { 279 | M5.Lcd.fillScreen(TFT_BLACK); 280 | for (int i = 0; i < 6; ++i ){ 281 | peer_addr[i] = (uint8_t) connect_addr[ypos][i]; 282 | } 283 | //Serial.printf("%2x:%2x:%2x:%2x:%2x:%2x",slave.peer_addr[0],slave.peer_addr[1],slave.peer_addr[2], slave.peer_addr[3],slave.peer_addr[4], slave.peer_addr[5]); 284 | for (int i = 0; i < 6; ++i ){ 285 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 286 | } 287 | slave.channel = CHANNEL; 288 | esp_now_add_peer(&slave); 289 | M5.Lcd.setCursor(140, 210); 290 | M5.Lcd.println("Quit"); 291 | while(!connectflag){ 292 | //for(int i = 0;i < 6; i++){ 293 | esp_err_t result = esp_now_send(slave.peer_addr, sta_addr, sizeof(sta_addr)+ 1); 294 | Serial.print("Send Status: "); 295 | if (result == ESP_OK) { 296 | Serial.println("Success"); 297 | }else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 298 | Serial.println("ESPNOW not Init."); 299 | } else if (result == ESP_ERR_ESPNOW_ARG) { 300 | Serial.println("Invalid Argument"); 301 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 302 | Serial.println("Internal Error"); 303 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 304 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 305 | }else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 306 | Serial.println("Peer not found."); 307 | }else { 308 | Serial.println("Not sure what happened"); 309 | } 310 | delay(100); 311 | // } 312 | 313 | 314 | 315 | // while(!connectflag) 316 | // { 317 | if(digitalRead(38) == LOW) break; 318 | } 319 | if(connectflag){ 320 | char macStr[18]; 321 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", peer_addr[0], peer_addr[1], peer_addr[2], peer_addr[3], peer_addr[4], peer_addr[5]); 322 | String mac_addr = (char *)macStr; 323 | preferences.putString("mac_addr", mac_addr); 324 | delay(100); 325 | M5.Lcd.fillScreen(TFT_BLACK); 326 | break; 327 | } 328 | } 329 | 330 | 331 | delay(100); 332 | if (digitalRead(39) == LOW && (connect_num) ) 333 | { 334 | M5.Lcd.fillScreen(TFT_BLACK); 335 | ypos--; 336 | if(ypos <= 0) 337 | { 338 | ypos = 0; 339 | } 340 | } 341 | 342 | if (digitalRead(38) == LOW && (connect_num)) 343 | { 344 | // Serial.println("IdigitalRead(38) == LOW"); 345 | //M5.Lcd.print("39 low"); 346 | M5.Lcd.fillScreen(TFT_BLACK); 347 | ypos++; 348 | if(ypos >= connect_num - 1) 349 | { 350 | ypos = connect_num - 1; 351 | } 352 | } 353 | 354 | } 355 | } 356 | } 357 | 358 | 359 | void Espnow::ScanForSlave(void) { 360 | int8_t scanResults = WiFi.scanNetworks(); 361 | //reset slaves 362 | memset(slaves, 0, sizeof(slaves)); 363 | SlaveCnt = 0; 364 | Serial.println(""); 365 | if (scanResults == 0) { 366 | Serial.println("No WiFi devices in AP Mode found"); 367 | } else { 368 | Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices "); 369 | for (int i = 0; i < scanResults; ++i) { 370 | // Print SSID and RSSI for each device found 371 | String SSID = WiFi.SSID(i); 372 | int32_t RSSI = WiFi.RSSI(i); 373 | String BSSIDstr = WiFi.BSSIDstr(i); 374 | 375 | if (PRINTSCANRESULTS) { 376 | Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); 377 | } 378 | delay(10); 379 | // Check if the current device starts with `Slave` 380 | if (SSID.indexOf("Slave") == 0) { 381 | // SSID of interest 382 | Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); 383 | // Get BSSID => Mac Address of the Slave 384 | int mac[6]; 385 | 386 | if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { 387 | for (int ii = 0; ii < 6; ++ii ) { 388 | slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii]; 389 | } 390 | } 391 | slaves[SlaveCnt].channel = CHANNEL; // pick a channel 392 | slaves[SlaveCnt].encrypt = 0; // no encryption 393 | SlaveCnt++; 394 | } 395 | } 396 | } 397 | 398 | if (SlaveCnt > 0) { 399 | Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing.."); 400 | } else { 401 | Serial.println("No Slave Found, trying again."); 402 | } 403 | 404 | // clean up ram 405 | WiFi.scanDelete(); 406 | } 407 | 408 | // Check if the slave is already paired with the master. 409 | // If not, pair the slave with master 410 | void Espnow::manageSlave(void) { 411 | if (SlaveCnt > 0) { 412 | for (int i = 0; i < SlaveCnt; i++) { 413 | const esp_now_peer_info_t *peer = &slaves[i]; 414 | const uint8_t *peer_addr = slaves[i].peer_addr; 415 | Serial.print("Processing: "); 416 | for (int ii = 0; ii < 6; ++ii ) { 417 | Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX); 418 | if (ii != 5) Serial.print(":"); 419 | } 420 | Serial.print(" Status: "); 421 | // check if the peer exists 422 | bool exists = esp_now_is_peer_exist(peer_addr); 423 | if (exists) { 424 | // Slave already paired. 425 | Serial.println("Already Paired"); 426 | } else { 427 | // Slave not paired, attempt pair 428 | esp_err_t addStatus = esp_now_add_peer(peer); 429 | if (addStatus == ESP_OK) { 430 | // Pair success 431 | Serial.println("Pair success"); 432 | } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) { 433 | // How did we get so far!! 434 | Serial.println("ESPNOW Not Init"); 435 | } else if (addStatus == ESP_ERR_ESPNOW_ARG) { 436 | Serial.println("Add Peer - Invalid Argument"); 437 | } else if (addStatus == ESP_ERR_ESPNOW_FULL) { 438 | Serial.println("Peer list full"); 439 | } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) { 440 | Serial.println("Out of memory"); 441 | } else if (addStatus == ESP_ERR_ESPNOW_EXIST) { 442 | Serial.println("Peer Exists"); 443 | } else { 444 | Serial.println("Not sure what happened"); 445 | } 446 | delay(100); 447 | } 448 | } 449 | } else { 450 | // No slave found to process 451 | Serial.println("No Slave found to process"); 452 | } 453 | } 454 | 455 | 456 | // send data 457 | void Espnow::sendData(void) { 458 | //const uint8_t *phy_addr = peer_addr; 459 | for (int i = 0; i < SlaveCnt; i++) { 460 | const uint8_t *scan_addr = slaves[i].peer_addr; 461 | if (i == 0) { // print only for first slave 462 | Serial.print("Sending: "); 463 | //Serial.println(phy_addr); 464 | //Serial.print(phy_addr); 465 | for (int ii = 0; ii < 6; ++ii ) { 466 | Serial.print((uint8_t) sta_addr[ii], HEX); 467 | if (ii != 5) Serial.print(":"); 468 | } 469 | } 470 | //WiFi.softAPmacAddress() 471 | //esp_err_t result = esp_now_send(scan_addr, WiFi.softAPmacAddress(), sizeof(WiFi.softAPmacAddress())); 472 | esp_err_t result = esp_now_send(scan_addr, sta_addr, sizeof(sta_addr)); 473 | Serial.print("Send Status: "); 474 | if (result == ESP_OK) { 475 | Serial.println("Success"); 476 | } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 477 | // How did we get so far!! 478 | Serial.println("ESPNOW not Init."); 479 | } else if (result == ESP_ERR_ESPNOW_ARG) { 480 | Serial.println("Invalid Argument"); 481 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 482 | Serial.println("Internal Error"); 483 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 484 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 485 | } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 486 | Serial.println("Peer not found."); 487 | } else { 488 | Serial.println("Not sure what happened"); 489 | } 490 | delay(100); 491 | } 492 | } 493 | 494 | 495 | void Espnow::BotConnectUpdate(void) 496 | { 497 | static int updatetime; 498 | if (digitalRead(38) == LOW) 499 | { 500 | updatetime++; 501 | } 502 | //Serial.println(updatetime); 503 | if (updatetime >= 10){ 504 | updatetime = 0; 505 | delay(200); 506 | M5.Speaker.tone(80, 200); 507 | delay(200); 508 | M5.Lcd.fillScreen(TFT_BLACK); 509 | M5.Speaker.mute(); 510 | int ypos = 0; 511 | connect_num = 0; 512 | connectflag = false; 513 | while (true){ 514 | M5.Lcd.setCursor(0, 0, 4); 515 | M5.Lcd.println("Broadcasting..."); 516 | M5.Lcd.printf("("); 517 | M5.Lcd.print(WiFi.softAPmacAddress()); 518 | M5.Lcd.printf(")"); 519 | if(connect_num>=1) connect_num = 1; 520 | for (int i = 0; i < connect_num; i++){ 521 | M5.Lcd.setCursor(30, 75 + 25 * i); // Set cursor near top left corner of screen 522 | M5.Lcd.printf("%02x:%02x:%02x:%02x:%02x:%02x", connect_addr[i][0], connect_addr[i][1], connect_addr[i][2], connect_addr[i][3], connect_addr[i][4], connect_addr[i][5]); 523 | } 524 | if (connect_num) { 525 | M5.Lcd.setCursor(30, 125); 526 | M5.Lcd.println("Accept?"); 527 | M5.Lcd.setCursor(220, 210); 528 | M5.Lcd.println("Confirm"); 529 | } 530 | if ((digitalRead(37) == LOW) && (connect_num)){ 531 | M5.Lcd.fillScreen(TFT_BLACK); 532 | for (int i = 0; i < 6; ++i ) 533 | { 534 | peer_addr[i] = (uint8_t) connect_addr[ypos][i]; 535 | } 536 | for (int i = 0; i < 6; ++i ) 537 | { 538 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 539 | } 540 | slave.channel = CHANNEL; 541 | esp_now_add_peer(&slave); 542 | uint8_t ack[4] = {0x41, 0x43, 0x4B}; 543 | for (int i = 0; i < 6; i++) 544 | { 545 | esp_err_t result = esp_now_send(slave.peer_addr, ack, sizeof(ack)); 546 | /* 547 | Serial.print("Send Status: "); 548 | if (result == ESP_OK) { 549 | Serial.println("Success"); 550 | } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 551 | // How did we get so far!! 552 | Serial.println("ESPNOW not Init."); 553 | } else if (result == ESP_ERR_ESPNOW_ARG) { 554 | Serial.println("Invalid Argument"); 555 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 556 | Serial.println("Internal Error"); 557 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 558 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 559 | } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 560 | Serial.println("Peer not found."); 561 | } else { 562 | Serial.println("Not sure what happened"); 563 | }*/ 564 | } 565 | char macStr[18]; 566 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", peer_addr[0], peer_addr[1], peer_addr[2], peer_addr[3], peer_addr[4], peer_addr[5]); 567 | String mac_addr = (char *)macStr; 568 | preferences.putString("mac_addr", mac_addr); 569 | delay(100); 570 | //preferences.end(); 571 | break; 572 | } 573 | if (digitalRead(39) == LOW && (connect_num)) 574 | { 575 | M5.Lcd.fillScreen(TFT_BLACK); 576 | ypos--; 577 | if (ypos <= 0) 578 | { 579 | ypos = 0; 580 | } 581 | } 582 | 583 | if (!connect_num) 584 | { 585 | ScanForSlave(); 586 | if (SlaveCnt > 0) 587 | { 588 | manageSlave(); 589 | sendData(); 590 | } 591 | } 592 | } 593 | } 594 | } 595 | -------------------------------------------------------------------------------- /lepton3/Src/Lepton_Bot/espnow.cpp: -------------------------------------------------------------------------------- 1 | //#include"espnow.h 2 | #include"espnow.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | Espnow::Espnow(void) 9 | { 10 | 11 | } 12 | 13 | void Espnow::BotInit(void){ 14 | 15 | //m5.begin(); 16 | //Serial.begin(115200); 17 | 18 | pinMode(37, INPUT); 19 | pinMode(38, INPUT); 20 | pinMode(39, INPUT); 21 | //digitalWrite(37, HIGH); 22 | // digitalWrite(38, HIGH); 23 | //digitalWrite(39, HIGH); 24 | 25 | WiFi.mode(WIFI_STA); 26 | Serial.println("ESPNow Master Example"); 27 | // This is the mac address of the Master in Station Mode 28 | Serial.print("STA MAC: "); 29 | Serial.println(WiFi.macAddress()); 30 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 31 | //WiFi.softAPmacAddress() 32 | //if(!bot) 33 | sscanf(WiFi.macAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 34 | //else 35 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 36 | //WiFi.softAPmacAddress() 37 | //WiFi.softAPmacAddress() 38 | InitEspNow(); 39 | 40 | preferences.begin("my-app", false); 41 | String mac_addr; 42 | mac_addr = preferences.getString("mac_addr", "error"); 43 | Serial.print("mac_addr = ");Serial.print(mac_addr); 44 | 45 | sscanf(mac_addr.c_str(), "%x:%x:%x:%x:%x:%x%c", &peer_addr[0], &peer_addr[1], &peer_addr[2], &peer_addr[3], &peer_addr[4], &peer_addr[5]); 46 | 47 | for (int i = 0; i < 6; ++i ){ 48 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 49 | } 50 | slave.channel = CHANNEL; 51 | esp_now_add_peer(&slave); 52 | } 53 | 54 | void Espnow::RemoteInit(void) 55 | { 56 | //m5.begin(); 57 | //Serial.begin(115200); 58 | 59 | pinMode(37, INPUT); 60 | pinMode(38, INPUT); 61 | pinMode(39, INPUT); 62 | //digitalWrite(37, HIGH); 63 | // digitalWrite(38, HIGH); 64 | //digitalWrite(39, HIGH); 65 | 66 | WiFi.mode(WIFI_AP_STA); 67 | //WiFi.mode(WIFI_AP); 68 | ConfigDeviceAP(); 69 | Serial.println("ESPNow Master Example"); 70 | // This is the mac address of the Master in Station Mode 71 | Serial.print(" AP MAC: "); 72 | Serial.println(WiFi.softAPmacAddress()); 73 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 74 | //WiFi.softAPmacAddress() 75 | //if(!bot) 76 | sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 77 | //else 78 | //sscanf(WiFi.softAPmacAddress().c_str(), "%x:%x:%x:%x:%x:%x", &sta_addr[0], &sta_addr[1], &sta_addr[2], &sta_addr[3], &sta_addr[4], &sta_addr[5] ); 79 | //WiFi.softAPmacAddress() 80 | //WiFi.softAPmacAddress() 81 | InitEspNow(); 82 | 83 | preferences.begin("my-app", false); 84 | String mac_addr; 85 | mac_addr = preferences.getString("mac_addr", "error"); 86 | Serial.print("mac_addr = ");Serial.print(mac_addr); 87 | 88 | sscanf(mac_addr.c_str(), "%x:%x:%x:%x:%x:%x%c", &peer_addr[0], &peer_addr[1], &peer_addr[2], &peer_addr[3], &peer_addr[4], &peer_addr[5]); 89 | 90 | for (int i = 0; i < 6; ++i ){ 91 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 92 | } 93 | slave.channel = CHANNEL; 94 | esp_now_add_peer(&slave); 95 | } 96 | 97 | // config AP SSID 98 | void Espnow::ConfigDeviceAP(void) 99 | { 100 | 101 | String Mac = WiFi.macAddress(); 102 | String SSID = "Slave:"+ Mac; 103 | bool result = WiFi.softAP(SSID.c_str(), "12345678", CHANNEL, 0); 104 | if (!result) 105 | { 106 | Serial.println("AP Config failed."); 107 | } else 108 | { 109 | Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID)); 110 | } 111 | } 112 | 113 | // Init ESP Now with fallback 114 | void Espnow::InitEspNow(void) 115 | { 116 | if (esp_now_init() == ESP_OK) 117 | { 118 | Serial.println("ESPNow Init Success"); 119 | } 120 | else 121 | { 122 | Serial.println("ESPNow Init Failed"); 123 | ESP.restart(); 124 | } 125 | } 126 | 127 | void Espnow::OnRemotSent(const uint8_t *mac_addr, esp_now_send_status_t status) 128 | { 129 | 130 | } 131 | void Espnow::OnRemotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len){ 132 | 133 | if(data_len == 4) 134 | { 135 | connectflag = true; 136 | } 137 | if(data_len == 6) 138 | { 139 | int i = 0; 140 | for(i = 0; i < connect_num; i++) 141 | { 142 | int j = 0; 143 | for(j = 0; j < 6; j++) 144 | { 145 | if(connect_addr[i][j] != data[j]) 146 | { 147 | break; 148 | } 149 | } 150 | //Serial.printf("j = %d",j); 151 | if(j == 6) 152 | { 153 | break; 154 | } 155 | } 156 | 157 | if(i == connect_num) 158 | { 159 | for(int i = 0; i < 6;i++) 160 | { 161 | connect_addr[connect_num][i] = data[i]; 162 | } 163 | connect_num++; 164 | } 165 | } 166 | if(connect_num> 20) connect_num = 0; 167 | 168 | 169 | int mac_comp = 0; 170 | for(mac_comp = 0; mac_comp < 6; mac_comp++){ 171 | if(mac_addr[mac_comp] != peer_addr[mac_comp]){ 172 | return; 173 | } 174 | } 175 | } 176 | 177 | void Espnow::OnBotSent(const uint8_t *mac_addr, esp_now_send_status_t status) 178 | { 179 | } 180 | void Espnow::OnBotRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) 181 | { 182 | Serial.print("connectflag = ");Serial.println(connectflag); 183 | if ((data_len == 7) && (!connectflag)) 184 | { 185 | connectflag = true; 186 | int i = 0; 187 | for (i = 0; i < connect_num; i++) 188 | { 189 | int j = 0; 190 | for (j = 0; j < 6; j++) 191 | { 192 | if (connect_addr[i][j] != mac_addr[j]) 193 | { 194 | break; 195 | } 196 | } 197 | //Serial.printf("j = %d",j); 198 | if (j == 6) 199 | { 200 | break; 201 | } 202 | } 203 | if (i == connect_num) 204 | { 205 | for (int i = 0; i < 6; i++) 206 | { 207 | connect_addr[connect_num][i] = mac_addr[i]; 208 | } 209 | connect_num++; 210 | } 211 | } 212 | //if (connect_num > 20) connect_num = 0; 213 | 214 | int mac_comp = 0; 215 | for(mac_comp = 0; mac_comp < 6; mac_comp++){ 216 | if(mac_addr[mac_comp] != peer_addr[mac_comp]){ 217 | return; 218 | } 219 | } 220 | } 221 | 222 | void Espnow::RemoteConnectUpdate(){ 223 | 224 | static int updatetime; 225 | if (digitalRead(38) == LOW) 226 | { 227 | updatetime++; 228 | } 229 | Serial.println(updatetime); 230 | if (updatetime >= 30){ 231 | updatetime = 0; 232 | delay(200); 233 | M5.Speaker.tone(80, 200); 234 | delay(200); 235 | M5.Lcd.fillScreen(TFT_BLACK); 236 | M5.Speaker.mute(); 237 | int ypos = 0; 238 | int old_ypos = 0; 239 | connect_num = 0; 240 | connectflag = false; 241 | while(true) 242 | { 243 | M5.Lcd.setCursor(0, 0, 4); 244 | M5.Lcd.println("LidarBot Scanning...."); 245 | for(int i = 0; i < connect_num; i++) 246 | { 247 | M5.Lcd.setCursor(30, 25 + 25 * i); // Set cursor near top left corner of screen 248 | M5.Lcd.printf("%02x:%02x:%02x:%02x:%02x:%02x", connect_addr[i][0], connect_addr[i][1], connect_addr[i][2], connect_addr[i][3], connect_addr[i][4], connect_addr[i][5]); 249 | } 250 | if(connect_num){ 251 | M5.Lcd.setCursor(270, 25 + ypos * 25); 252 | M5.Lcd.println("<<"); 253 | } 254 | 255 | if(ypos < 1){ 256 | //M5.Lcd.fillScreen(TFT_BLACK); 257 | if(old_ypos != ypos) 258 | M5.Lcd.fillRect(30, 210, 90, 50, TFT_BLACK); 259 | M5.Lcd.setCursor(30, 210); 260 | M5.Lcd.println("update"); 261 | } 262 | else 263 | { 264 | if(old_ypos != ypos) 265 | M5.Lcd.fillRect(30, 210, 100, 50, TFT_BLACK); 266 | //M5.Lcd.fillScreen(TFT_BLACK); 267 | M5.Lcd.setCursor(50, 210); 268 | M5.Lcd.println("up"); 269 | } 270 | old_ypos = ypos; 271 | M5.Lcd.setCursor(125, 210); 272 | M5.Lcd.println("down"); 273 | M5.Lcd.setCursor(220, 210); 274 | M5.Lcd.println("select"); 275 | 276 | 277 | //select down 278 | if ((digitalRead(37) == LOW) && (connect_num)) 279 | { 280 | M5.Lcd.fillScreen(TFT_BLACK); 281 | for (int i = 0; i < 6; ++i ){ 282 | peer_addr[i] = (uint8_t) connect_addr[ypos][i]; 283 | } 284 | //Serial.printf("%2x:%2x:%2x:%2x:%2x:%2x",slave.peer_addr[0],slave.peer_addr[1],slave.peer_addr[2], slave.peer_addr[3],slave.peer_addr[4], slave.peer_addr[5]); 285 | for (int i = 0; i < 6; ++i ){ 286 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 287 | } 288 | slave.channel = CHANNEL; 289 | esp_now_add_peer(&slave); 290 | M5.Lcd.setCursor(140, 210); 291 | M5.Lcd.println("Quit"); 292 | while(!connectflag){ 293 | //for(int i = 0;i < 6; i++){ 294 | esp_err_t result = esp_now_send(slave.peer_addr, sta_addr, sizeof(sta_addr)+ 1); 295 | Serial.print("Send Status: "); 296 | if (result == ESP_OK) { 297 | Serial.println("Success"); 298 | }else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 299 | Serial.println("ESPNOW not Init."); 300 | } else if (result == ESP_ERR_ESPNOW_ARG) { 301 | Serial.println("Invalid Argument"); 302 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 303 | Serial.println("Internal Error"); 304 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 305 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 306 | }else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 307 | Serial.println("Peer not found."); 308 | }else { 309 | Serial.println("Not sure what happened"); 310 | } 311 | delay(100); 312 | // } 313 | 314 | 315 | 316 | // while(!connectflag) 317 | // { 318 | if(digitalRead(38) == LOW) break; 319 | } 320 | if(connectflag){ 321 | char macStr[18]; 322 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", peer_addr[0], peer_addr[1], peer_addr[2], peer_addr[3], peer_addr[4], peer_addr[5]); 323 | String mac_addr = (char *)macStr; 324 | preferences.putString("mac_addr", mac_addr); 325 | delay(100); 326 | M5.Lcd.fillScreen(TFT_BLACK); 327 | break; 328 | } 329 | } 330 | 331 | 332 | delay(100); 333 | if (digitalRead(39) == LOW && (connect_num) ) 334 | { 335 | M5.Lcd.fillScreen(TFT_BLACK); 336 | ypos--; 337 | if(ypos <= 0) 338 | { 339 | ypos = 0; 340 | } 341 | } 342 | 343 | if (digitalRead(38) == LOW && (connect_num)) 344 | { 345 | // Serial.println("IdigitalRead(38) == LOW"); 346 | //M5.Lcd.print("39 low"); 347 | M5.Lcd.fillScreen(TFT_BLACK); 348 | ypos++; 349 | if(ypos >= connect_num - 1) 350 | { 351 | ypos = connect_num - 1; 352 | } 353 | } 354 | 355 | } 356 | } 357 | } 358 | 359 | 360 | void Espnow::ScanForSlave(void) { 361 | int8_t scanResults = WiFi.scanNetworks(); 362 | //reset slaves 363 | memset(slaves, 0, sizeof(slaves)); 364 | SlaveCnt = 0; 365 | Serial.println(""); 366 | if (scanResults == 0) { 367 | Serial.println("No WiFi devices in AP Mode found"); 368 | } else { 369 | Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices "); 370 | for (int i = 0; i < scanResults; ++i) { 371 | // Print SSID and RSSI for each device found 372 | String SSID = WiFi.SSID(i); 373 | int32_t RSSI = WiFi.RSSI(i); 374 | String BSSIDstr = WiFi.BSSIDstr(i); 375 | 376 | if (PRINTSCANRESULTS) { 377 | Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); 378 | } 379 | delay(10); 380 | // Check if the current device starts with `Slave` 381 | if (SSID.indexOf("Slave") == 0) { 382 | // SSID of interest 383 | Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); 384 | // Get BSSID => Mac Address of the Slave 385 | int mac[6]; 386 | 387 | if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { 388 | for (int ii = 0; ii < 6; ++ii ) { 389 | slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii]; 390 | } 391 | } 392 | slaves[SlaveCnt].channel = CHANNEL; // pick a channel 393 | slaves[SlaveCnt].encrypt = 0; // no encryption 394 | SlaveCnt++; 395 | } 396 | } 397 | } 398 | 399 | if (SlaveCnt > 0) { 400 | Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing.."); 401 | } else { 402 | Serial.println("No Slave Found, trying again."); 403 | } 404 | 405 | // clean up ram 406 | WiFi.scanDelete(); 407 | } 408 | 409 | // Check if the slave is already paired with the master. 410 | // If not, pair the slave with master 411 | void Espnow::manageSlave(void) { 412 | if (SlaveCnt > 0) { 413 | for (int i = 0; i < SlaveCnt; i++) { 414 | const esp_now_peer_info_t *peer = &slaves[i]; 415 | const uint8_t *peer_addr = slaves[i].peer_addr; 416 | Serial.print("Processing: "); 417 | for (int ii = 0; ii < 6; ++ii ) { 418 | Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX); 419 | if (ii != 5) Serial.print(":"); 420 | } 421 | Serial.print(" Status: "); 422 | // check if the peer exists 423 | bool exists = esp_now_is_peer_exist(peer_addr); 424 | if (exists) { 425 | // Slave already paired. 426 | Serial.println("Already Paired"); 427 | } else { 428 | // Slave not paired, attempt pair 429 | esp_err_t addStatus = esp_now_add_peer(peer); 430 | if (addStatus == ESP_OK) { 431 | // Pair success 432 | Serial.println("Pair success"); 433 | } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) { 434 | // How did we get so far!! 435 | Serial.println("ESPNOW Not Init"); 436 | } else if (addStatus == ESP_ERR_ESPNOW_ARG) { 437 | Serial.println("Add Peer - Invalid Argument"); 438 | } else if (addStatus == ESP_ERR_ESPNOW_FULL) { 439 | Serial.println("Peer list full"); 440 | } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) { 441 | Serial.println("Out of memory"); 442 | } else if (addStatus == ESP_ERR_ESPNOW_EXIST) { 443 | Serial.println("Peer Exists"); 444 | } else { 445 | Serial.println("Not sure what happened"); 446 | } 447 | delay(100); 448 | } 449 | } 450 | } else { 451 | // No slave found to process 452 | Serial.println("No Slave found to process"); 453 | } 454 | } 455 | 456 | 457 | // send data 458 | void Espnow::sendData(void) { 459 | //const uint8_t *phy_addr = peer_addr; 460 | for (int i = 0; i < SlaveCnt; i++) { 461 | const uint8_t *scan_addr = slaves[i].peer_addr; 462 | if (i == 0) { // print only for first slave 463 | Serial.print("Sending: "); 464 | //Serial.println(phy_addr); 465 | //Serial.print(phy_addr); 466 | for (int ii = 0; ii < 6; ++ii ) { 467 | Serial.print((uint8_t) sta_addr[ii], HEX); 468 | if (ii != 5) Serial.print(":"); 469 | } 470 | } 471 | //WiFi.softAPmacAddress() 472 | //esp_err_t result = esp_now_send(scan_addr, WiFi.softAPmacAddress(), sizeof(WiFi.softAPmacAddress())); 473 | esp_err_t result = esp_now_send(scan_addr, sta_addr, sizeof(sta_addr)); 474 | Serial.print("Send Status: "); 475 | if (result == ESP_OK) { 476 | Serial.println("Success"); 477 | } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 478 | // How did we get so far!! 479 | Serial.println("ESPNOW not Init."); 480 | } else if (result == ESP_ERR_ESPNOW_ARG) { 481 | Serial.println("Invalid Argument"); 482 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 483 | Serial.println("Internal Error"); 484 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 485 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 486 | } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 487 | Serial.println("Peer not found."); 488 | } else { 489 | Serial.println("Not sure what happened"); 490 | } 491 | delay(100); 492 | } 493 | } 494 | 495 | 496 | void Espnow::BotConnectUpdate(void) 497 | { 498 | static int updatetime; 499 | if (digitalRead(38) == LOW) 500 | { 501 | updatetime++; 502 | } 503 | //Serial.println(updatetime); 504 | if (updatetime >= 10){ 505 | updatetime = 0; 506 | delay(200); 507 | M5.Speaker.tone(80, 200); 508 | delay(200); 509 | M5.Lcd.fillScreen(TFT_BLACK); 510 | M5.Speaker.mute(); 511 | int ypos = 0; 512 | connect_num = 0; 513 | connectflag = false; 514 | while (true){ 515 | M5.Lcd.setCursor(0, 0, 4); 516 | M5.Lcd.println("Broadcasting..."); 517 | M5.Lcd.printf("("); 518 | M5.Lcd.print(WiFi.softAPmacAddress()); 519 | M5.Lcd.printf(")"); 520 | if(connect_num>=1) connect_num = 1; 521 | for (int i = 0; i < connect_num; i++){ 522 | M5.Lcd.setCursor(30, 75 + 25 * i); // Set cursor near top left corner of screen 523 | M5.Lcd.printf("%02x:%02x:%02x:%02x:%02x:%02x", connect_addr[i][0], connect_addr[i][1], connect_addr[i][2], connect_addr[i][3], connect_addr[i][4], connect_addr[i][5]); 524 | } 525 | if (connect_num) { 526 | M5.Lcd.setCursor(30, 125); 527 | M5.Lcd.println("Accept?"); 528 | M5.Lcd.setCursor(220, 210); 529 | M5.Lcd.println("Confirm"); 530 | } 531 | if ((digitalRead(37) == LOW) && (connect_num)){ 532 | M5.Lcd.fillScreen(TFT_BLACK); 533 | for (int i = 0; i < 6; ++i ) 534 | { 535 | peer_addr[i] = (uint8_t) connect_addr[ypos][i]; 536 | } 537 | for (int i = 0; i < 6; ++i ) 538 | { 539 | slave.peer_addr[i] = (uint8_t) peer_addr[i]; 540 | } 541 | slave.channel = CHANNEL; 542 | esp_now_add_peer(&slave); 543 | uint8_t ack[4] = {0x41, 0x43, 0x4B}; 544 | for (int i = 0; i < 6; i++) 545 | { 546 | esp_err_t result = esp_now_send(slave.peer_addr, ack, sizeof(ack)); 547 | /* 548 | Serial.print("Send Status: "); 549 | if (result == ESP_OK) { 550 | Serial.println("Success"); 551 | } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { 552 | // How did we get so far!! 553 | Serial.println("ESPNOW not Init."); 554 | } else if (result == ESP_ERR_ESPNOW_ARG) { 555 | Serial.println("Invalid Argument"); 556 | } else if (result == ESP_ERR_ESPNOW_INTERNAL) { 557 | Serial.println("Internal Error"); 558 | } else if (result == ESP_ERR_ESPNOW_NO_MEM) { 559 | Serial.println("ESP_ERR_ESPNOW_NO_MEM"); 560 | } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { 561 | Serial.println("Peer not found."); 562 | } else { 563 | Serial.println("Not sure what happened"); 564 | }*/ 565 | } 566 | char macStr[18]; 567 | snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", peer_addr[0], peer_addr[1], peer_addr[2], peer_addr[3], peer_addr[4], peer_addr[5]); 568 | String mac_addr = (char *)macStr; 569 | preferences.putString("mac_addr", mac_addr); 570 | delay(100); 571 | //preferences.end(); 572 | break; 573 | } 574 | if (digitalRead(39) == LOW && (connect_num)) 575 | { 576 | M5.Lcd.fillScreen(TFT_BLACK); 577 | ypos--; 578 | if (ypos <= 0) 579 | { 580 | ypos = 0; 581 | } 582 | } 583 | 584 | if (!connect_num) 585 | { 586 | ScanForSlave(); 587 | if (SlaveCnt > 0) 588 | { 589 | manageSlave(); 590 | sendData(); 591 | } 592 | } 593 | } 594 | } 595 | } 596 | --------------------------------------------------------------------------------