Здравствуйте уважаемые форумчане, столкнулся со следующей проблемой:
Использую модуль: ESP32-S3-Touch-LCD-4.3
Документация:
У данного модуля есть сенсор реагирующий на 5 одновременных касаний на контроллере GT911 и разъём под SD карту.
По отдельности они работают исправно, а при совместной работе модуль просто не видит SD карту, при чём я испробовал все библиотеки которые смог найти в интернете, результат у всех одинаковый - вместе не работаю.
В какую сторону мне копать?
Мой код:
#include <GT911.h>
#include <Arduino_GFX_Library.h>
#include <INA226_WE.h>
#include <RTClib.h>
#include <EEPROM.h>
#include <CRC8.h>
#include <CRC.h>
#include "waveshare_sd_card.h"
INA226_WE INA226_CH1 = INA226_WE(0x40);
INA226_WE INA226_CH2 = INA226_WE(0x44);
INA226_WE INA226_CH3 = INA226_WE(0x45);
RTC_DS3231 RTC;
GT911 TOUCH;
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
5 /* DE */, 3 /* VSYNC */, 46 /* HSYNC */, 7 /* PCLK */,
1 /* R0 */, 2 /* R1 */, 42 /* R2 */, 41 /* R3 */, 40 /* R4 */,
39 /* G0 */, 0 /* G1 */, 45 /* G2 */, 48 /* G3 */, 47 /* G4 */, 21 /* G5 */,
14 /* B0 */, 38 /* B1 */, 18 /* B2 */, 17 /* B3 */, 10 /* B4 */,
0 /* hsync_polarity */, 40 /* hsync_front_porch */, 48 /* hsync_pulse_width */, 88 /* hsync_back_porch */,
0 /* vsync_polarity */, 13 /* vsync_front_porch */, 3 /* vsync_pulse_width */, 32 /* vsync_back_porch */,
1 /* pclk_active_neg */, 16000000 /* prefer_speed */
);
Arduino_RGB_Display* GFX = new Arduino_RGB_Display(
800 /* width */, 480 /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */
);
Arduino_Canvas_Indexed *CANVAS = new Arduino_Canvas_Indexed(720, 480, GFX, 0, 0, 0, 0);
esp_expander::CH422G *expander = NULL;
// Initial Setup
void setup(){
Serial.begin(115200);
Serial.println("Initialize IO expander");
/* Initialize IO expander */
const __FlashStringHelper* OK = F("OK"); //Экономим оперативную память и сохраняем во флеш память
const __FlashStringHelper* NO = F("NO"); //Экономим оперативную память и сохраняем во флеш память
GFX->begin();
CANVAS->begin(GFX_SKIP_OUTPUT_BEGIN);
GFX->fillScreen(0x0000);
GFX->setTextColor(0xffff);
GFX->setCursor(200, 10);
GFX->print(F("Display..............................................................."));
GFX->println(OK);
GFX->print(F("SD..............................................................."));
expander = new esp_expander::CH422G(EXAMPLE_I2C_SCL_PIN, EXAMPLE_I2C_SDA_PIN, EXAMPLE_I2C_ADDR);
expander->init();
expander->begin();
expander->enableAllIO_Output();
expander->digitalWrite(TP_RST , HIGH);
expander->digitalWrite(LCD_RST , HIGH);
expander->digitalWrite(LCD_BL , HIGH);
expander->digitalWrite(SD_CS, LOW);
expander->digitalWrite(USB_SEL, LOW);
SPI.setHwCs(false);
SPI.begin(SD_CLK, SD_MISO, SD_MOSI, SD_SS);
if (!SD.begin(SD_SS)) {
GFX->println(NO);
}
else
GFX->println(OK);
uint8_t cardType = SD.cardType();
GFX->print(F("CARD..............................................................."));
if(cardType == CARD_NONE)
GFX->println("NONE");
else if(cardType == CARD_MMC)
GFX->println("MMC");
else if(cardType == CARD_SD)
GFX->println("SDSC");
else if(cardType == CARD_SDHC)
GFX->println("SDHC");
else
GFX->println("UNKNOWN");
GFX->print(F("TOUCH..............................................................."));
if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_28, 400000))
{
if (!TOUCH.begin(-1, -1, GT911_I2C_ADDR_BA, 400000))
{
GFX->println(NO);
}
else
GFX->println(OK);
}
else
GFX->println(OK);
}
// Main Loop
void loop() {
}
Библиотека waveshare_sd_card.h (взята из документации к данному модулю)
Файл waveshare_sd_card.h:
#include "SD.h"
#include "SPI.h"
#include <esp_io_expander.hpp>
// Extension IO pin definition
#define TP_RST 1 // Touch screen reset pin
#define LCD_BL 2 // LCD backlight pinout
#define LCD_RST 3 // LCD reset pin
#define SD_CS 4 // SD card select pin
#define USB_SEL 5 // USB select pin
// I2C pin definitions
#define EXAMPLE_I2C_ADDR (ESP_IO_EXPANDER_I2C_CH422G_ADDRESS)
#define EXAMPLE_I2C_SDA_PIN 8 // I2C data line pins
#define EXAMPLE_I2C_SCL_PIN 9 // I2C clock line pin
#define SD_MOSI 11 // SD card master output slave input pin
#define SD_CLK 12 // SD card clock pin
#define SD_MISO 13 // SD card master input slave output pin
#define SD_SS -1 // SD card select pin (not used)
void listDir(fs::FS &fs, const char * dirname, uint8_t levels);
void createDir(fs::FS &fs, const char * path);
void removeDir(fs::FS &fs, const char * path);
void writeFile(fs::FS &fs, const char * path, const char * message);
void appendFile(fs::FS &fs, const char * path, const char * message);
void readFile(fs::FS &fs, const char * path);
void deleteFile(fs::FS &fs, const char * path);
void renameFile(fs::FS &fs, const char * path1, const char * path2);
void testFileIO(fs::FS &fs, const char * path);
#endif
Файл waveshare_sd_card.cpp:
/*
* Connect the SD card to the following pins:
*
* SD Card | ESP32
* D2 - (Not connected)
* D3 SS (Chip Select)
* CMD MOSI (Master output slave input)
* VSS GND (Ground)
* VDD 3.3V (Power supply)
* CLK SCK (Clock)
* VSS GND (Ground)
* D0 MISO (Master Input Slave Output)
* D1 - (Not connected)
*/
#include "waveshare_sd_card.h"
// List files and subdirectories in a directory
void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
Serial.printf("Listing directory: %s\n", dirname);
// Listing Directories
File root = fs.open(dirname);
if (!root) {
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory()) {
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels) {
listDir(fs, file.path(), levels - 1);
}
} else {
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
// Creating Dir
void createDir(fs::FS &fs, const char * path) {
Serial.printf("Creating Dir: %s\n", path);
if (fs.mkdir(path)) {
Serial.println("Dir created");
} else {
Serial.println("mkdir failed");
}
}
// Remove a directory
void removeDir(fs::FS &fs, const char * path) {
Serial.printf("Removing Dir: %s\n", path);
if (fs.rmdir(path)) {
Serial.println("Dir removed");
} else {
Serial.println("rmdir failed");
}
}
// Reading a file
void readFile(fs::FS &fs, const char * path) {
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file) {
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available()) {
Serial.write(file.read());
}
file.close();
}
// Writing to a File
void writeFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
// Append to file
void appendFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if (!file) {
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
// Rename a file
void renameFile(fs::FS &fs, const char * path1, const char * path2) {
Serial.printf("Renaming file %s to %s\n", path1, path2);
if (fs.rename(path1, path2)) {
Serial.println("File renamed");
} else {
Serial.println("Rename failed");
}
}
// Deleting files
void deleteFile(fs::FS &fs, const char * path) {
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path)) {
Serial.println("File deleted");
} else {
Serial.println("Delete failed");
}
}
// Test file IO performance
void testFileIO(fs::FS &fs, const char * path) {
File file = fs.open(path);
static uint8_t buf[512]; // Buffer
size_t len = 0;
uint32_t start = millis();
uint32_t end = start;
if (file) {
len = file.size();
size_t flen = len;
start = millis();
while (len) {
size_t toRead = len;
if (toRead > 512) {
toRead = 512;
}
file.read(buf, toRead);
len -= toRead;
}
end = millis() - start;
Serial.printf(" %u bytes read for %u ms\n", flen, end);
file.close();
} else {
Serial.println("Failed to open file for reading");
}
// Write test
file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
return;
}
size_t i;
start = millis();
for (i = 0; i < 2048; i++) {
file.write(buf, 512);
}
end = millis() - start;
Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
file.close();
}
Библиотека GT911
Файл GT911.h
#ifndef GT911_H
#define GT911_H
#include <Arduino.h>
#include <Wire.h>
#include "GT911_Structs.h"
// 0x28/0x29 (0x14 7bit)
#define GT911_I2C_ADDR_28 0x14
// 0xBA/0xBB (0x5D 7bit)
#define GT911_I2C_ADDR_BA 0x5D
#define GT911_MAX_CONTACTS 5
#define GT911_REG_CFG 0x8047
#define GT911_REG_CHECKSUM 0x80FF
#define GT911_REG_DATA 0x8140
#define GT911_REG_ID 0x8140
#define GT911_REG_COORD_ADDR 0x814E
enum : uint8_t {
GT911_MODE_INTERRUPT,
GT911_MODE_POLLING
};
class GT911 {
public:
enum class Rotate {
_0,
_90,
_180,
_270,
};
private:
TwoWire *_wire;
int8_t _intPin;
int8_t _rstPin;
uint8_t _addr;
bool _configLoaded = false;
GTConfig _config;
GTInfo _info;
GTPoint _points[GT911_MAX_CONTACTS];
Rotate _rotation = Rotate::_0;
void reset();
void i2cStart(uint16_t reg);
bool write(uint16_t reg, uint8_t data);
uint8_t read(uint16_t reg);
bool writeBytes(uint16_t reg, uint8_t *data, uint16_t size);
bool readBytes(uint16_t reg, uint8_t *data, uint16_t size);
uint8_t calcChecksum(uint8_t *buf, uint8_t len);
uint8_t readChecksum();
int8_t readTouches();
bool readTouchPoints();
public:
GT911(TwoWire *twi = &Wire);
bool begin(int8_t intPin = -1, int8_t rstPin = -1, uint8_t addr = GT911_I2C_ADDR_BA,
uint32_t clk = 400000);
bool productID(uint8_t *buf, uint8_t len);
GTConfig* readConfig();
bool writeConfig();
GTInfo* readInfo();
uint8_t touched(uint8_t mode = GT911_MODE_INTERRUPT);
GTPoint getPoint(uint8_t num);
GTPoint *getPoints();
void setRotation(Rotate rotation);
};
#endif
Файл GT911_Structs.h
struct __attribute__((packed)) GTInfo {
char productId[4]; // 0x8140 - 0x8143
uint16_t fwId; // 0x8144 - 0x8145
uint16_t xResolution; // 0x8146 - 0x8147
uint16_t yResolution; // 0x8148 - 0x8149
uint8_t vendorId; // 0x814A
};
struct __attribute__((packed)) GTPoint {
// 0x814F-0x8156, ... 0x8176 (5 points)
uint8_t trackId;
uint16_t x;
uint16_t y;
uint16_t area;
uint8_t reserved;
};
struct __attribute__((packed)) GTConfig {
uint8_t configVersion; // 0x8047
uint16_t xResolution; // 0x8048 - 0x8049
uint16_t yResolution; // 0x804A - 0x804B
uint8_t touchNumber; // 0x804C
uint8_t moduleSwitch1; // 0x804D
uint8_t moduleSwitch2; // 0x804E
uint8_t shakeCount; // 0x804F
uint8_t filter; // 0x8050
uint8_t largeTouch; // 0x8051
uint8_t noiseReduction; // 0x8052
uint8_t screenTouchLevel; // 0x8053
uint8_t screenLeaveLevel; // 0x8054
uint8_t lowPowerControl; // 0x8055
uint8_t refreshRate; // 0x8056
uint8_t xThreshold; // 0x8057
uint8_t yThreshold; // 0x8058
uint8_t xSpeedLimit; // 0x8059 - reserved
uint8_t ySpeedLimit; // 0x805A - reserved
uint8_t vSpace; // 0x805B
uint8_t hSpace; // 0x805C
uint8_t miniFilter; // 0x805D
uint8_t stretchR0; // 0x805E
uint8_t stretchR1; // 0x805F
uint8_t stretchR2; // 0x8060
uint8_t stretchRM; // 0x8061
uint8_t drvGroupANum; // 0x8062
uint8_t drvGroupBNum; // 0x8063
uint8_t sensorNum; // 0x8064
uint8_t freqAFactor; // 0x8065
uint8_t freqBFactor; // 0x8066
uint16_t pannelBitFreq; // 0x8067 - 0x8068
uint16_t pannelSensorTime; // 0x8069 - 0x806A
uint8_t pannelTxGain; // 0x806B
uint8_t pannelRxGain; // 0x806C
uint8_t pannelDumpShift; // 0x806D
uint8_t drvFrameControl; // 0x806E
uint8_t chargingLevelUp; // 0x806F
uint8_t moduleSwitch3; // 0x8070
uint8_t gestureDis; // 0x8071
uint8_t gestureLongPressTime; // 0x8072
uint8_t xySlopeAdjust; // 0x8073
uint8_t gestureControl; // 0x8074
uint8_t gestureSwitch1; // 0x8075
uint8_t gestureSwitch2; // 0x8076
uint8_t gestureRefreshRate; // 0x8077
uint8_t gestureTouchLevel; // 0x8078
uint8_t newGreenWakeUpLevel; // 0x8079
uint8_t freqHoppingStart; // 0x807A
uint8_t freqHoppingEnd; // 0x807B
uint8_t noiseDetectTimes; // 0x807C
uint8_t hoppingFlag; // 0x807D
uint8_t hoppingThreshold; // 0x807E
uint8_t noiseThreshold; // 0x807F
uint8_t noiseMinThreshold; // 0x8080
uint8_t NC_1; // 0x8081
uint8_t hoppingSensorGroup; // 0x8082
uint8_t hoppingSeg1Normalize; // 0x8083
uint8_t hoppingSeg1Factor; // 0x8084
uint8_t mainClockAjdust; // 0x8085
uint8_t hoppingSeg2Normalize; // 0x8086
uint8_t hoppingSeg2Factor; // 0x8087
uint8_t NC_2; // 0x8088
uint8_t hoppingSeg3Normalize; // 0x8089
uint8_t hoppingSeg3Factor; // 0x808A
uint8_t NC_3; // 0x808B
uint8_t hoppingSeg4Normalize; // 0x808C
uint8_t hoppingSeg4Factor; // 0x808D
uint8_t NC_4; // 0x808E
uint8_t hoppingSeg5Normalize; // 0x808F
uint8_t hoppingSeg5Factor; // 0x8090
uint8_t NC_5; // 0x8091
uint8_t hoppingSeg6Normalize; // 0x8092
uint8_t key[4]; // 0x8093 - 0x8096
uint8_t keyArea; // 0x8097
uint8_t keyTouchLevel; // 0x8098
uint8_t keyLeaveLevel; // 0x8099
uint8_t keySens[2]; // 0x809A - 0x809B
uint8_t keyRestrain; // 0x809C
uint8_t keyRestrainTime; // 0x809D
uint8_t gestureLargeTouch; // 0x809E
uint8_t NC_6[2]; // 0x809F - 0x80A0
uint8_t hotknotNoiseMap; // 0x80A1
uint8_t linkThreshold; // 0x80A2
uint8_t pxyThreshold; // 0x80A3
uint8_t gHotDumpShift; // 0x80A4
uint8_t gHotRxGain; // 0x80A5
uint8_t freqGain[4]; // 0x80A6 - 0x80A9
uint8_t NC_7[9]; // 0x80AA - 0x80B2
uint8_t combineDis; // 0x80B3
uint8_t splitSet; // 0x80B4
uint8_t NC_8[2]; // 0x80B5 - 0x80B6
uint8_t sensorCH[14]; // 0x80B7 - 0x80C4
uint8_t NC_9[16]; // 0x80C5 - 0x80D4
uint8_t driverCH[26]; // 0x80D5 - 0x80EE
uint8_t NC_10[16]; // 0x80EF - 0x80FE
};
Файл GT911.cpp:
#include "GT911.h"
#include <Wire.h>
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR
#endif
// Interrupt handling
volatile bool gt911IRQ = false;
void IRAM_ATTR _gt911_irq_handler() {
noInterrupts();
gt911IRQ = true;
interrupts();
}
GT911::GT911(TwoWire *twi) : _wire(twi ? twi : &Wire) {
}
void GT911::reset() {
delay(1);
pinMode(_intPin, OUTPUT);
pinMode(_rstPin, OUTPUT);
digitalWrite(_intPin, LOW);
digitalWrite(_rstPin, LOW);
delay(11);
digitalWrite(_intPin, _addr == GT911_I2C_ADDR_28);
delayMicroseconds(110);
pinMode(_rstPin, INPUT);
delay(6);
digitalWrite(_intPin, LOW);
delay(51);
}
void GT911::i2cStart(uint16_t reg) {
_wire->beginTransmission(_addr);
_wire->write(reg >> 8);
_wire->write(reg & 0xFF);
}
bool GT911::write(uint16_t reg, uint8_t data) {
i2cStart(reg);
_wire->write(data);
return _wire->endTransmission() == 0;
}
uint8_t GT911::read(uint16_t reg) {
i2cStart(reg);
_wire->endTransmission();
_wire->requestFrom(_addr, (uint8_t)1);
while (_wire->available()) {
return _wire->read();
}
return 0;
}
bool GT911::writeBytes(uint16_t reg, uint8_t *data, uint16_t size) {
i2cStart(reg);
for (uint16_t i = 0; i < size; i++) {
_wire->write(data[i]);
}
return _wire->endTransmission() == 0;
}
bool GT911::readBytes(uint16_t reg, uint8_t *data, uint16_t size) {
i2cStart(reg);
_wire->endTransmission();
uint16_t index = 0;
while (index < size) {
uint8_t req = _min(size - index, I2C_BUFFER_LENGTH);
_wire->requestFrom(_addr, req);
while (_wire->available()) {
data[index++] = _wire->read();
}
index++;
}
return size == index - 1;
}
uint8_t GT911::calcChecksum(uint8_t *buf, uint8_t len) {
uint8_t ccsum = 0;
for (uint8_t i = 0; i < len; i++) {
ccsum += buf[i];
}
return (~ccsum) + 1;
}
uint8_t GT911::readChecksum() {
return read(GT911_REG_CHECKSUM);
}
int8_t GT911::readTouches() {
uint32_t timeout = millis() + 20;
do {
uint8_t flag = read(GT911_REG_COORD_ADDR);
if ((flag & 0x80) && ((flag & 0x0F) < GT911_MAX_CONTACTS)) {
write(GT911_REG_COORD_ADDR, 0);
return flag & 0x0F;
}
delay(1);
} while (millis() < timeout);
return 0;
}
bool GT911::readTouchPoints() {
bool result = readBytes(GT911_REG_COORD_ADDR + 1, (uint8_t*)_points, sizeof(GTPoint) * GT911_MAX_CONTACTS);
if (result && _rotation != Rotate::_0) {
for (uint8_t i = 0; i < GT911_MAX_CONTACTS; i++) {
if (_rotation == Rotate::_180) {
_points[i].x = _info.xResolution - _points[i].x;
_points[i].y = _info.yResolution - _points[i].y;
}
}
}
return result;
}
bool GT911::begin(int8_t intPin, int8_t rstPin, uint8_t addr, uint32_t clk) {
_intPin = intPin;
_rstPin = rstPin;
_addr = addr;
if (_rstPin > 0) {
delay(300);
reset();
delay(200);
}
if (intPin > 0) {
pinMode(_intPin, INPUT);
attachInterrupt(_intPin, _gt911_irq_handler, FALLING);
}
_wire->begin();
_wire->setClock(clk);
_wire->beginTransmission(_addr);
if (_wire->endTransmission() == 0) {
readInfo(); // Need to get resolution to use rotation
return true;
}
return false;
}
bool GT911::productID(uint8_t *buf, uint8_t len) {
if (len < 4) {
return false;
}
memset(buf, 0, 4);
return readBytes(GT911_REG_ID, buf, 4);
}
GTConfig* GT911::readConfig() {
readBytes(GT911_REG_CFG, (uint8_t*)&_config, sizeof(_config));
if (readChecksum() == calcChecksum((uint8_t*)&_config, sizeof(_config))) {
_configLoaded = true;
return &_config;
}
return nullptr;
}
bool GT911::writeConfig() {
uint8_t checksum = calcChecksum((uint8_t*)&_config, sizeof(_config));
if (_configLoaded && readChecksum() != checksum) { // Config is different
writeBytes(GT911_REG_CFG, (uint8_t*)&_config, sizeof(_config));
uint8_t buf[2] = { checksum, 1 };
writeBytes(GT911_REG_CHECKSUM, buf, sizeof(buf));
return true;
}
return false;
}
GTInfo* GT911::readInfo() {
readBytes(GT911_REG_DATA, (uint8_t*)&_info, sizeof(_info));
return &_info;
}
uint8_t GT911::touched(uint8_t mode) {
bool irq = false;
if (mode == GT911_MODE_INTERRUPT) {
noInterrupts();
irq = gt911IRQ;
gt911IRQ = false;
interrupts();
} else if (mode == GT911_MODE_POLLING) {
irq = true;
}
uint8_t contacts = 0;
if (irq) {
contacts = readTouches();
if (contacts > 0) {
readTouchPoints();
}
}
return contacts;
}
GTPoint GT911::getPoint(uint8_t num) {
return _points[num];
}
GTPoint *GT911::getPoints() {
return _points;
}
void GT911::setRotation(Rotate rotation) {
_rotation = rotation;
}